<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: querydlg.cxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 16:33:41 $
 *
 *  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 DBAUI_QUERYDLG_HXX
#include "querydlg.hxx"
#endif
#ifndef _DBU_QRY_HRC_
#include "dbu_qry.hrc"
#endif
#ifndef DBAUI_QUERYDLG_HRC
#include "querydlg.hrc"
#endif
#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef DBAUI_QTABLECONNECTIONDATA_HXX
#include "QTableConnectionData.hxx"
#endif
#ifndef _DBAUI_MODULE_DBU_HXX_
#include "moduledbu.hxx"
#endif
#ifndef DBAUI_QUERYCONTROLLER_HXX
#include "querycontroller.hxx"
#endif
#ifndef DBAUI_QUERYTABLEVIEW_HXX
#include "QueryTableView.hxx"
#endif
#ifndef DBAUI_QUERYDESIGNVIEW_HXX
#include "QueryDesignView.hxx"
#endif
#ifndef _COM_SUN_STAR_SDBC_XDATABASEMETADATA_HPP_
#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
#endif
#ifndef DBAUI_RELATIONCONTROL_HXX
#include "RelationControl.hxx"
#endif
#ifndef _SV_MSGBOX_HXX
#include <vcl/msgbox.hxx>
#endif

using namespace dbaui;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::sdbc;

DBG_NAME(DlgQryJoin);
DlgQryJoin::DlgQryJoin( Window * pParent,
                       OQueryTableConnectionData* _pData,
                       OJoinTableView::OTableWindowMap* _pTableMap,
                       const Reference< XConnection >& _xConnection,
                       BOOL _bAllowTableSelect)
    : ModalDialog( pParent, ModuleRes(DLG_QRY_JOIN) ),
    aFL_Join( this, ResId( FL_JOIN ) ),
    aML_HelpText( this, ResId(ML_HELPTEXT) ),
    aFT_Title( this, ResId(FT_LISTBOXTITLE) ),
    aLB_JoinType( this, ResId(LB_JOINTYPE) ),
    aPB_OK( this, ResId( PB_OK ) ),
    aPB_CANCEL( this, ResId( PB_CANCEL ) ),
    aPB_HELP( this, ResId( PB_HELP ) ),
    eJoinType(_pData->GetJoinType()),
    m_pConnData(NULL),
    m_xConnection(_xConnection),
    m_pTableMap(_pTableMap),
    m_pOrigConnData(_pData)

{
    DBG_CTOR(DlgQryJoin,NULL);

    aML_HelpText.SetControlBackground( GetSettings().GetStyleSettings().GetFaceColor() );
    //////////////////////////////////////////////////////////////////////
    // Connection kopieren
    m_pConnData = static_cast<OQueryTableConnectionData*>(_pData->NewInstance());
    m_pConnData->CopyFrom(*_pData);

    m_pTableControl = new OTableListBoxControl(this,ModuleRes(WND_CONTROL),m_pTableMap,this);

    if( _bAllowTableSelect )
    {
        m_pTableControl->Init( m_pConnData );
        m_pTableControl->fillListBoxes();
    }
    else
    {
        m_pTableControl->fillAndDisable(m_pConnData);
        m_pTableControl->Init( m_pConnData );
    }

    m_pTableControl->lateInit();

    sal_Bool bFull = sal_False;
    sal_Bool bOuter = sal_False;
    Reference<XDatabaseMetaData> xMeta;
    try
    {
        xMeta = m_xConnection->getMetaData();
        if ( xMeta.is() )
            bFull = xMeta->supportsFullOuterJoins();
    }
    catch(SQLException&)
    {
    }
    try
    {
        if ( xMeta.is() )
            bOuter= xMeta->supportsOuterJoins();
    }
    catch(SQLException&)
    {
    }

    setJoinType(eJoinType);

    aPB_OK.SetClickHdl( LINK(this, DlgQryJoin, OKClickHdl) );

    aLB_JoinType.SetSelectHdl(LINK(this,DlgQryJoin,LBChangeHdl));

    if ( static_cast<OQueryTableView*>(pParent)->getDesignView()->getController()->isReadOnly() )
    {
        aLB_JoinType.Disable();
        m_pTableControl->Disable();
    }
    else if ( !bFull && !bOuter )
        aLB_JoinType.Disable();
    else
    {
        if ( !bFull )
            aLB_JoinType.RemoveEntry(3);

        if ( !bOuter )
        {
            aLB_JoinType.RemoveEntry(0);
            aLB_JoinType.RemoveEntry(0);
            aLB_JoinType.RemoveEntry(0);
        }

        m_pTableControl->NotifyCellChange();
    }

    FreeResource();
}

//------------------------------------------------------------------------
DlgQryJoin::~DlgQryJoin()
{
    DBG_DTOR(DlgQryJoin,NULL);
    delete m_pTableControl;
    delete m_pConnData;
}
// -----------------------------------------------------------------------------
IMPL_LINK( DlgQryJoin, LBChangeHdl, ListBox*, pListBox )
{
    DBG_CHKTHIS(DlgQryJoin,NULL);
    aML_HelpText.SetText(String());

    String sFirstWinName,sSecondWinName;
    USHORT nResId = 0;
    USHORT nPos = aLB_JoinType.GetSelectEntryPos();
    sal_Bool bAddHint = sal_True;
    switch ( nPos )
    {
        default:
        case 0:
            nResId = STR_QUERY_INNER_JOIN;
            bAddHint = sal_False;
            break;
        case 1:
            nResId = STR_QUERY_LEFTRIGHT_JOIN;
            sFirstWinName   = m_pConnData->GetSourceWinName();
            sSecondWinName  = m_pConnData->GetDestWinName();
            break;
        case 2:
        case 3:
            nResId = (nPos == 2) ? STR_QUERY_LEFTRIGHT_JOIN : STR_QUERY_FULL_JOIN;

            sFirstWinName   = m_pConnData->GetDestWinName();
            sSecondWinName  = m_pConnData->GetSourceWinName();
            break;
    }

    String sHelpText = String( ModuleRes( nResId ) );
    if( sFirstWinName.Len() )
    {
        sHelpText.SearchAndReplace( String( RTL_CONSTASCII_STRINGPARAM( "%1" ) ), sFirstWinName );
        sHelpText.SearchAndReplace( String( RTL_CONSTASCII_STRINGPARAM( "%2" ) ), sSecondWinName );
    }
    if ( bAddHint )
    {
        sHelpText += String( RTL_CONSTASCII_STRINGPARAM( "\n" ) );
        sHelpText += String( ModuleRes( STR_JOIN_TYPE_HINT ) );
    }

    aML_HelpText.SetText( sHelpText );
    return 1;
}
// -----------------------------------------------------------------------------

IMPL_LINK( DlgQryJoin, OKClickHdl, Button*, pButton )
{
    DBG_CHKTHIS(DlgQryJoin,NULL);
    USHORT nPos = aLB_JoinType.GetSelectEntryPos();
    switch ( nPos )
    {
        case 0:
            eJoinType = INNER_JOIN;
            break;
        case 1:
            eJoinType = LEFT_JOIN;
            break;
        case 2:
            eJoinType = RIGHT_JOIN;
            break;
        case 3:
            eJoinType = FULL_JOIN;
            break;
    }

    m_pConnData->Update();
    m_pOrigConnData->CopyFrom( *m_pConnData );

    EndDialog(RET_OK);
    return 1;
}
// -----------------------------------------------------------------------------
OTableConnectionData* DlgQryJoin::getConnectionData() const
{
    return m_pConnData;
}
// -----------------------------------------------------------------------------
void DlgQryJoin::setValid(sal_Bool _bValid)
{
    LBChangeHdl(&aLB_JoinType);

    aPB_OK.Enable(_bValid);
}
// -----------------------------------------------------------------------------
void DlgQryJoin::notifyConnectionChange(OTableConnectionData* _pConnectionData)
{
    setJoinType(m_pConnData->GetJoinType());
}
// -----------------------------------------------------------------------------
void DlgQryJoin::setJoinType(EJoinType _eNewJoinType)
{
    eJoinType = _eNewJoinType;
    USHORT nPos = 0;
    switch(eJoinType)
    {
        case INNER_JOIN:
            break;
        case LEFT_JOIN:
            nPos = 1;
            break;
        case RIGHT_JOIN:
            nPos = 2;
            break;
        case FULL_JOIN:
            nPos = 3;
            break;
    }
    aLB_JoinType.SelectEntryPos(nPos);
    LBChangeHdl(&aLB_JoinType);
}
// -----------------------------------------------------------------------------

<commit_msg>INTEGRATION: CWS warnings01 (1.11.50); FILE MERGED 2006/03/24 15:36:28 fs 1.11.50.1: #i57457# warning-free code (unxlngi6/.pro + unxsoli4.pro)<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: querydlg.cxx,v $
 *
 *  $Revision: 1.12 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-20 03:30:08 $
 *
 *  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 DBAUI_QUERYDLG_HXX
#include "querydlg.hxx"
#endif
#ifndef _DBU_QRY_HRC_
#include "dbu_qry.hrc"
#endif
#ifndef DBAUI_QUERYDLG_HRC
#include "querydlg.hrc"
#endif
#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef DBAUI_QTABLECONNECTIONDATA_HXX
#include "QTableConnectionData.hxx"
#endif
#ifndef _DBAUI_MODULE_DBU_HXX_
#include "moduledbu.hxx"
#endif
#ifndef DBAUI_QUERYCONTROLLER_HXX
#include "querycontroller.hxx"
#endif
#ifndef DBAUI_QUERYTABLEVIEW_HXX
#include "QueryTableView.hxx"
#endif
#ifndef DBAUI_QUERYDESIGNVIEW_HXX
#include "QueryDesignView.hxx"
#endif
#ifndef _COM_SUN_STAR_SDBC_XDATABASEMETADATA_HPP_
#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
#endif
#ifndef DBAUI_RELATIONCONTROL_HXX
#include "RelationControl.hxx"
#endif
#ifndef _SV_MSGBOX_HXX
#include <vcl/msgbox.hxx>
#endif

using namespace dbaui;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::sdbc;

DBG_NAME(DlgQryJoin)
DlgQryJoin::DlgQryJoin( Window * pParent,
                       OQueryTableConnectionData* _pData,
                       OJoinTableView::OTableWindowMap* _pTableMap,
                       const Reference< XConnection >& _xConnection,
                       BOOL _bAllowTableSelect)
    :ModalDialog( pParent, ModuleRes(DLG_QRY_JOIN) )
    ,aFL_Join( this, ResId( FL_JOIN ) )
    ,aFT_Title( this, ResId(FT_LISTBOXTITLE) )
    ,aLB_JoinType( this, ResId(LB_JOINTYPE) )
    ,aML_HelpText( this, ResId(ML_HELPTEXT) )
    ,aPB_OK( this, ResId( PB_OK ) )
    ,aPB_CANCEL( this, ResId( PB_CANCEL ) )
    ,aPB_HELP( this, ResId( PB_HELP ) )
    ,m_pTableControl( NULL )
    ,m_pTableMap(_pTableMap)
    ,eJoinType(_pData->GetJoinType())
    ,m_pConnData(NULL)
    ,m_pOrigConnData(_pData)
    ,m_xConnection(_xConnection)
{
    DBG_CTOR(DlgQryJoin,NULL);

    aML_HelpText.SetControlBackground( GetSettings().GetStyleSettings().GetFaceColor() );
    //////////////////////////////////////////////////////////////////////
    // Connection kopieren
    m_pConnData = static_cast<OQueryTableConnectionData*>(_pData->NewInstance());
    m_pConnData->CopyFrom(*_pData);

    m_pTableControl = new OTableListBoxControl(this,ModuleRes(WND_CONTROL),m_pTableMap,this);

    if( _bAllowTableSelect )
    {
        m_pTableControl->Init( m_pConnData );
        m_pTableControl->fillListBoxes();
    }
    else
    {
        m_pTableControl->fillAndDisable(m_pConnData);
        m_pTableControl->Init( m_pConnData );
    }

    m_pTableControl->lateInit();

    sal_Bool bFull = sal_False;
    sal_Bool bOuter = sal_False;
    Reference<XDatabaseMetaData> xMeta;
    try
    {
        xMeta = m_xConnection->getMetaData();
        if ( xMeta.is() )
            bFull = xMeta->supportsFullOuterJoins();
    }
    catch(SQLException&)
    {
    }
    try
    {
        if ( xMeta.is() )
            bOuter= xMeta->supportsOuterJoins();
    }
    catch(SQLException&)
    {
    }

    setJoinType(eJoinType);

    aPB_OK.SetClickHdl( LINK(this, DlgQryJoin, OKClickHdl) );

    aLB_JoinType.SetSelectHdl(LINK(this,DlgQryJoin,LBChangeHdl));

    if ( static_cast<OQueryTableView*>(pParent)->getDesignView()->getController()->isReadOnly() )
    {
        aLB_JoinType.Disable();
        m_pTableControl->Disable();
    }
    else if ( !bFull && !bOuter )
        aLB_JoinType.Disable();
    else
    {
        if ( !bFull )
            aLB_JoinType.RemoveEntry(3);

        if ( !bOuter )
        {
            aLB_JoinType.RemoveEntry(0);
            aLB_JoinType.RemoveEntry(0);
            aLB_JoinType.RemoveEntry(0);
        }

        m_pTableControl->NotifyCellChange();
    }

    FreeResource();
}

//------------------------------------------------------------------------
DlgQryJoin::~DlgQryJoin()
{
    DBG_DTOR(DlgQryJoin,NULL);
    delete m_pTableControl;
    delete m_pConnData;
}
// -----------------------------------------------------------------------------
IMPL_LINK( DlgQryJoin, LBChangeHdl, ListBox*, /*pListBox*/ )
{
    DBG_CHKTHIS(DlgQryJoin,NULL);
    aML_HelpText.SetText(String());

    String sFirstWinName,sSecondWinName;
    USHORT nResId = 0;
    USHORT nPos = aLB_JoinType.GetSelectEntryPos();
    sal_Bool bAddHint = sal_True;
    switch ( nPos )
    {
        default:
        case 0:
            nResId = STR_QUERY_INNER_JOIN;
            bAddHint = sal_False;
            break;
        case 1:
            nResId = STR_QUERY_LEFTRIGHT_JOIN;
            sFirstWinName   = m_pConnData->GetSourceWinName();
            sSecondWinName  = m_pConnData->GetDestWinName();
            break;
        case 2:
        case 3:
            nResId = (nPos == 2) ? STR_QUERY_LEFTRIGHT_JOIN : STR_QUERY_FULL_JOIN;

            sFirstWinName   = m_pConnData->GetDestWinName();
            sSecondWinName  = m_pConnData->GetSourceWinName();
            break;
    }

    String sHelpText = String( ModuleRes( nResId ) );
    if( sFirstWinName.Len() )
    {
        sHelpText.SearchAndReplace( String( RTL_CONSTASCII_STRINGPARAM( "%1" ) ), sFirstWinName );
        sHelpText.SearchAndReplace( String( RTL_CONSTASCII_STRINGPARAM( "%2" ) ), sSecondWinName );
    }
    if ( bAddHint )
    {
        sHelpText += String( RTL_CONSTASCII_STRINGPARAM( "\n" ) );
        sHelpText += String( ModuleRes( STR_JOIN_TYPE_HINT ) );
    }

    aML_HelpText.SetText( sHelpText );
    return 1;
}
// -----------------------------------------------------------------------------

IMPL_LINK( DlgQryJoin, OKClickHdl, Button*, /*pButton*/ )
{
    DBG_CHKTHIS(DlgQryJoin,NULL);
    USHORT nPos = aLB_JoinType.GetSelectEntryPos();
    switch ( nPos )
    {
        case 0:
            eJoinType = INNER_JOIN;
            break;
        case 1:
            eJoinType = LEFT_JOIN;
            break;
        case 2:
            eJoinType = RIGHT_JOIN;
            break;
        case 3:
            eJoinType = FULL_JOIN;
            break;
    }

    m_pConnData->Update();
    m_pOrigConnData->CopyFrom( *m_pConnData );

    EndDialog(RET_OK);
    return 1;
}
// -----------------------------------------------------------------------------
OTableConnectionData* DlgQryJoin::getConnectionData() const
{
    return m_pConnData;
}
// -----------------------------------------------------------------------------
void DlgQryJoin::setValid(sal_Bool _bValid)
{
    LBChangeHdl(&aLB_JoinType);

    aPB_OK.Enable(_bValid);
}
// -----------------------------------------------------------------------------
void DlgQryJoin::notifyConnectionChange( )
{
    setJoinType( m_pConnData->GetJoinType() );
}
// -----------------------------------------------------------------------------
void DlgQryJoin::setJoinType(EJoinType _eNewJoinType)
{
    eJoinType = _eNewJoinType;
    USHORT nPos = 0;
    switch(eJoinType)
    {
        case INNER_JOIN:
            break;
        case LEFT_JOIN:
            nPos = 1;
            break;
        case RIGHT_JOIN:
            nPos = 2;
            break;
        case FULL_JOIN:
            nPos = 3;
            break;
        default:
            break;
    }
    aLB_JoinType.SelectEntryPos(nPos);
    LBChangeHdl(&aLB_JoinType);
}
// -----------------------------------------------------------------------------

<|endoftext|>


<commit_before>/*
 * Copyright 2018 Google, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#include "systemc/core/scheduler.hh"

#include "base/fiber.hh"
#include "base/logging.hh"
#include "sim/eventq.hh"
#include "systemc/core/kernel.hh"
#include "systemc/core/sc_main_fiber.hh"
#include "systemc/ext/core/messages.hh"
#include "systemc/ext/core/sc_main.hh"
#include "systemc/ext/utils/sc_report.hh"
#include "systemc/ext/utils/sc_report_handler.hh"
#include "systemc/utils/report.hh"
#include "systemc/utils/tracefile.hh"

namespace sc_gem5
{

Scheduler::Scheduler() :
    eq(nullptr), readyEvent(this, false, ReadyPriority),
    pauseEvent(this, false, PausePriority),
    stopEvent(this, false, StopPriority), _throwUp(nullptr),
    starvationEvent(this, false, StarvationPriority),
    _elaborationDone(false), _started(false), _stopNow(false),
    _status(StatusOther), maxTickEvent(this, false, MaxTickPriority),
    timeAdvancesEvent(this, false, TimeAdvancesPriority), _numCycles(0),
    _changeStamp(0), _current(nullptr), initDone(false), runOnce(false)
{}

Scheduler::~Scheduler()
{
    // Clear out everything that belongs to us to make sure nobody tries to
    // clear themselves out after the scheduler goes away.
    clear();
}

void
Scheduler::clear()
{
    // Delta notifications.
    while (!deltas.empty())
        deltas.front()->deschedule();

    // Timed notifications.
    for (auto &tsp: timeSlots) {
        TimeSlot *&ts = tsp.second;
        while (!ts->events.empty())
            ts->events.front()->deschedule();
        deschedule(ts);
    }
    timeSlots.clear();

    // gem5 events.
    if (readyEvent.scheduled())
        deschedule(&readyEvent);
    if (pauseEvent.scheduled())
        deschedule(&pauseEvent);
    if (stopEvent.scheduled())
        deschedule(&stopEvent);
    if (starvationEvent.scheduled())
        deschedule(&starvationEvent);
    if (maxTickEvent.scheduled())
        deschedule(&maxTickEvent);
    if (timeAdvancesEvent.scheduled())
        deschedule(&timeAdvancesEvent);

    Process *p;
    while ((p = initList.getNext()))
        p->popListNode();
    while ((p = readyListMethods.getNext()))
        p->popListNode();
    while ((p = readyListThreads.getNext()))
        p->popListNode();

    Channel *c;
    while ((c = updateList.getNext()))
        c->popListNode();
}

void
Scheduler::initPhase()
{
    runUpdate();

    for (Process *p = initList.getNext(); p; p = initList.getNext()) {
        p->popListNode();

        if (p->dontInitialize()) {
            if (!p->hasStaticSensitivities() && !p->internal()) {
                SC_REPORT_WARNING(sc_core::SC_ID_DISABLE_WILL_ORPHAN_PROCESS_,
                        p->name());
            }
        } else {
            p->ready();
        }
    }

    runDelta();

    for (auto ets: eventsToSchedule)
        eq->schedule(ets.first, ets.second);
    eventsToSchedule.clear();

    if (_started) {
        if (!runToTime && starved())
            scheduleStarvationEvent();
        kernel->status(::sc_core::SC_RUNNING);
    }

    initDone = true;

    status(StatusOther);

    scheduleTimeAdvancesEvent();
}

void
Scheduler::reg(Process *p)
{
    if (initDone) {
        // If not marked as dontInitialize, mark as ready.
        if (!p->dontInitialize())
            p->ready();
    } else {
        // Otherwise, record that this process should be initialized once we
        // get there.
        initList.pushLast(p);
    }
}

void
Scheduler::yield()
{
    // Pull a process from the active list.
    _current = getNextReady();
    if (!_current) {
        // There are no more processes, so return control to evaluate.
        Fiber::primaryFiber()->run();
    } else {
        _current->popListNode();
        _current->scheduled(false);
        // Switch to whatever Fiber is supposed to run this process. All
        // Fibers which aren't running should be parked at this line.
        _current->fiber()->run();
        // If the current process needs to be manually started, start it.
        if (_current && _current->needsStart()) {
            _current->needsStart(false);
            // If a process hasn't started yet, "resetting" it just starts it
            // and signals its reset event.
            if (_current->inReset())
                _current->resetEvent().notify();
            try {
                _current->run();
            } catch (...) {
                throwUp();
            }
        }
    }
    if (_current && !_current->needsStart()) {
        if (_current->excWrapper) {
            auto ew = _current->excWrapper;
            _current->excWrapper = nullptr;
            ew->throw_it();
        } else if (_current->inReset()) {
            _current->reset(false);
        }
    }
}

void
Scheduler::ready(Process *p)
{
    if (_stopNow)
        return;

    p->scheduled(true);

    if (p->procKind() == ::sc_core::SC_METHOD_PROC_)
        readyListMethods.pushLast(p);
    else
        readyListThreads.pushLast(p);

    if (!inEvaluate())
        scheduleReadyEvent();
}

void
Scheduler::resume(Process *p)
{
    if (initDone)
        ready(p);
    else
        initList.pushLast(p);
}

bool
listContains(ListNode *list, ListNode *target)
{
    ListNode *n = list->nextListNode;
    while (n != list)
        if (n == target)
            return true;
    return false;
}

bool
Scheduler::suspend(Process *p)
{
    bool was_ready;
    if (initDone) {
        // After initialization, check if we're on a ready list.
        was_ready = (p->nextListNode != nullptr);
        p->popListNode();
    } else {
        // Nothing is ready before init.
        was_ready = false;
    }
    return was_ready;
}

void
Scheduler::requestUpdate(Channel *c)
{
    updateList.pushLast(c);
    if (!inEvaluate())
        scheduleReadyEvent();
}

void
Scheduler::scheduleReadyEvent()
{
    // Schedule the evaluate and update phases.
    if (!readyEvent.scheduled()) {
        schedule(&readyEvent);
        if (starvationEvent.scheduled())
            deschedule(&starvationEvent);
    }
}

void
Scheduler::scheduleStarvationEvent()
{
    if (!starvationEvent.scheduled()) {
        schedule(&starvationEvent);
        if (readyEvent.scheduled())
            deschedule(&readyEvent);
    }
}

void
Scheduler::runReady()
{
    scheduleTimeAdvancesEvent();

    bool empty = readyListMethods.empty() && readyListThreads.empty();
    lastReadyTick = getCurTick();

    // The evaluation phase.
    status(StatusEvaluate);
    do {
        yield();
    } while (getNextReady());
    _current = nullptr;

    if (!empty) {
        _numCycles++;
        _changeStamp++;
    }

    if (_stopNow) {
        status(StatusOther);
        return;
    }

    runUpdate();
    if (!traceFiles.empty())
        trace(true);
    runDelta();

    if (!runToTime && starved())
        scheduleStarvationEvent();

    if (runOnce)
        schedulePause();

    status(StatusOther);
}

void
Scheduler::runUpdate()
{
    status(StatusUpdate);

    try {
        Channel *channel = updateList.getNext();
        while (channel) {
            channel->popListNode();
            channel->update();
            channel = updateList.getNext();
        }
    } catch (...) {
        throwUp();
    }
}

void
Scheduler::runDelta()
{
    status(StatusDelta);

    try {
        while (!deltas.empty())
            deltas.back()->run();
    } catch (...) {
        throwUp();
    }
}

void
Scheduler::pause()
{
    status(StatusPaused);
    kernel->status(::sc_core::SC_PAUSED);
    runOnce = false;
    if (scMainFiber.called() && !scMainFiber.finished())
        scMainFiber.run();
}

void
Scheduler::stop()
{
    status(StatusStopped);
    kernel->stop();

    clear();

    runOnce = false;
    if (scMainFiber.called() && !scMainFiber.finished())
        scMainFiber.run();
}

void
Scheduler::start(Tick max_tick, bool run_to_time)
{
    _started = true;
    status(StatusOther);
    runToTime = run_to_time;

    maxTick = max_tick;
    lastReadyTick = getCurTick();

    if (initDone) {
        if (!runToTime && starved())
            scheduleStarvationEvent();
        kernel->status(::sc_core::SC_RUNNING);
    }

    schedule(&maxTickEvent, maxTick);
    scheduleTimeAdvancesEvent();

    // Return to gem5 to let it run events, etc.
    Fiber::primaryFiber()->run();

    if (pauseEvent.scheduled())
        deschedule(&pauseEvent);
    if (stopEvent.scheduled())
        deschedule(&stopEvent);
    if (maxTickEvent.scheduled())
        deschedule(&maxTickEvent);
    if (starvationEvent.scheduled())
        deschedule(&starvationEvent);

    if (_throwUp) {
        const ::sc_core::sc_report *to_throw = _throwUp;
        _throwUp = nullptr;
        throw *to_throw;
    }
}

void
Scheduler::oneCycle()
{
    runOnce = true;
    scheduleReadyEvent();
    start(::MaxTick, false);
}

void
Scheduler::schedulePause()
{
    if (pauseEvent.scheduled())
        return;

    schedule(&pauseEvent);
}

void
Scheduler::throwUp()
{
    if (scMainFiber.called() && !scMainFiber.finished()) {
        ::sc_core::sc_report report = reportifyException();
        _throwUp = &report;
        status(StatusOther);
        scMainFiber.run();
    } else {
        reportHandlerProc(reportifyException(),
                ::sc_core::sc_report_handler::get_catch_actions());
    }
}

void
Scheduler::scheduleStop(bool finish_delta)
{
    if (stopEvent.scheduled())
        return;

    if (!finish_delta) {
        _stopNow = true;
        // If we're not supposed to finish the delta cycle, flush all
        // pending activity.
        clear();
    }
    schedule(&stopEvent);
}

void
Scheduler::trace(bool delta)
{
    for (auto tf: traceFiles)
        tf->trace(delta);
}

Scheduler scheduler;
Process *getCurrentProcess() { return scheduler.current(); }

namespace {

void
throwingReportHandler(const ::sc_core::sc_report &r,
                      const ::sc_core::sc_actions &)
{
    throw r;
}

} // anonymous namespace

const ::sc_core::sc_report
reportifyException()
{
    ::sc_core::sc_report_handler_proc old_handler = reportHandlerProc;
    ::sc_core::sc_report_handler::set_handler(&throwingReportHandler);

    try {
        try {
            // Rethrow the current exception so we can catch it and throw an
            // sc_report instead if it's not a type we recognize/can handle.
            throw;
        } catch (const ::sc_core::sc_report &) {
            // It's already a sc_report, so nothing to do.
            throw;
        } catch (const ::sc_core::sc_unwind_exception &) {
            panic("Kill/reset exception escaped a Process::run()");
        } catch (const std::exception &e) {
            SC_REPORT_ERROR(
                    sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, e.what());
        } catch (const char *msg) {
            SC_REPORT_ERROR(
                    sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, msg);
        } catch (...) {
            SC_REPORT_ERROR(
                    sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_,
                    "UNKNOWN EXCEPTION");
        }
    } catch (const ::sc_core::sc_report &r) {
        ::sc_core::sc_report_handler::set_handler(old_handler);
        return r;
    }
    panic("No exception thrown in reportifyException.");
}

} // namespace sc_gem5
<commit_msg>systemc: Init some values in the scheduler for running without sc_main.<commit_after>/*
 * Copyright 2018 Google, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#include "systemc/core/scheduler.hh"

#include "base/fiber.hh"
#include "base/logging.hh"
#include "sim/eventq.hh"
#include "systemc/core/kernel.hh"
#include "systemc/core/sc_main_fiber.hh"
#include "systemc/ext/core/messages.hh"
#include "systemc/ext/core/sc_main.hh"
#include "systemc/ext/utils/sc_report.hh"
#include "systemc/ext/utils/sc_report_handler.hh"
#include "systemc/utils/report.hh"
#include "systemc/utils/tracefile.hh"

namespace sc_gem5
{

Scheduler::Scheduler() :
    eq(nullptr), readyEvent(this, false, ReadyPriority),
    pauseEvent(this, false, PausePriority),
    stopEvent(this, false, StopPriority), _throwUp(nullptr),
    starvationEvent(this, false, StarvationPriority),
    _elaborationDone(false), _started(false), _stopNow(false),
    _status(StatusOther), maxTick(::MaxTick),
    maxTickEvent(this, false, MaxTickPriority),
    timeAdvancesEvent(this, false, TimeAdvancesPriority), _numCycles(0),
    _changeStamp(0), _current(nullptr), initDone(false), runToTime(true),
    runOnce(false)
{}

Scheduler::~Scheduler()
{
    // Clear out everything that belongs to us to make sure nobody tries to
    // clear themselves out after the scheduler goes away.
    clear();
}

void
Scheduler::clear()
{
    // Delta notifications.
    while (!deltas.empty())
        deltas.front()->deschedule();

    // Timed notifications.
    for (auto &tsp: timeSlots) {
        TimeSlot *&ts = tsp.second;
        while (!ts->events.empty())
            ts->events.front()->deschedule();
        deschedule(ts);
    }
    timeSlots.clear();

    // gem5 events.
    if (readyEvent.scheduled())
        deschedule(&readyEvent);
    if (pauseEvent.scheduled())
        deschedule(&pauseEvent);
    if (stopEvent.scheduled())
        deschedule(&stopEvent);
    if (starvationEvent.scheduled())
        deschedule(&starvationEvent);
    if (maxTickEvent.scheduled())
        deschedule(&maxTickEvent);
    if (timeAdvancesEvent.scheduled())
        deschedule(&timeAdvancesEvent);

    Process *p;
    while ((p = initList.getNext()))
        p->popListNode();
    while ((p = readyListMethods.getNext()))
        p->popListNode();
    while ((p = readyListThreads.getNext()))
        p->popListNode();

    Channel *c;
    while ((c = updateList.getNext()))
        c->popListNode();
}

void
Scheduler::initPhase()
{
    runUpdate();

    for (Process *p = initList.getNext(); p; p = initList.getNext()) {
        p->popListNode();

        if (p->dontInitialize()) {
            if (!p->hasStaticSensitivities() && !p->internal()) {
                SC_REPORT_WARNING(sc_core::SC_ID_DISABLE_WILL_ORPHAN_PROCESS_,
                        p->name());
            }
        } else {
            p->ready();
        }
    }

    runDelta();

    for (auto ets: eventsToSchedule)
        eq->schedule(ets.first, ets.second);
    eventsToSchedule.clear();

    if (_started) {
        if (!runToTime && starved())
            scheduleStarvationEvent();
        kernel->status(::sc_core::SC_RUNNING);
    }

    initDone = true;

    status(StatusOther);

    scheduleTimeAdvancesEvent();
}

void
Scheduler::reg(Process *p)
{
    if (initDone) {
        // If not marked as dontInitialize, mark as ready.
        if (!p->dontInitialize())
            p->ready();
    } else {
        // Otherwise, record that this process should be initialized once we
        // get there.
        initList.pushLast(p);
    }
}

void
Scheduler::yield()
{
    // Pull a process from the active list.
    _current = getNextReady();
    if (!_current) {
        // There are no more processes, so return control to evaluate.
        Fiber::primaryFiber()->run();
    } else {
        _current->popListNode();
        _current->scheduled(false);
        // Switch to whatever Fiber is supposed to run this process. All
        // Fibers which aren't running should be parked at this line.
        _current->fiber()->run();
        // If the current process needs to be manually started, start it.
        if (_current && _current->needsStart()) {
            _current->needsStart(false);
            // If a process hasn't started yet, "resetting" it just starts it
            // and signals its reset event.
            if (_current->inReset())
                _current->resetEvent().notify();
            try {
                _current->run();
            } catch (...) {
                throwUp();
            }
        }
    }
    if (_current && !_current->needsStart()) {
        if (_current->excWrapper) {
            auto ew = _current->excWrapper;
            _current->excWrapper = nullptr;
            ew->throw_it();
        } else if (_current->inReset()) {
            _current->reset(false);
        }
    }
}

void
Scheduler::ready(Process *p)
{
    if (_stopNow)
        return;

    p->scheduled(true);

    if (p->procKind() == ::sc_core::SC_METHOD_PROC_)
        readyListMethods.pushLast(p);
    else
        readyListThreads.pushLast(p);

    if (!inEvaluate())
        scheduleReadyEvent();
}

void
Scheduler::resume(Process *p)
{
    if (initDone)
        ready(p);
    else
        initList.pushLast(p);
}

bool
listContains(ListNode *list, ListNode *target)
{
    ListNode *n = list->nextListNode;
    while (n != list)
        if (n == target)
            return true;
    return false;
}

bool
Scheduler::suspend(Process *p)
{
    bool was_ready;
    if (initDone) {
        // After initialization, check if we're on a ready list.
        was_ready = (p->nextListNode != nullptr);
        p->popListNode();
    } else {
        // Nothing is ready before init.
        was_ready = false;
    }
    return was_ready;
}

void
Scheduler::requestUpdate(Channel *c)
{
    updateList.pushLast(c);
    if (!inEvaluate())
        scheduleReadyEvent();
}

void
Scheduler::scheduleReadyEvent()
{
    // Schedule the evaluate and update phases.
    if (!readyEvent.scheduled()) {
        schedule(&readyEvent);
        if (starvationEvent.scheduled())
            deschedule(&starvationEvent);
    }
}

void
Scheduler::scheduleStarvationEvent()
{
    if (!starvationEvent.scheduled()) {
        schedule(&starvationEvent);
        if (readyEvent.scheduled())
            deschedule(&readyEvent);
    }
}

void
Scheduler::runReady()
{
    scheduleTimeAdvancesEvent();

    bool empty = readyListMethods.empty() && readyListThreads.empty();
    lastReadyTick = getCurTick();

    // The evaluation phase.
    status(StatusEvaluate);
    do {
        yield();
    } while (getNextReady());
    _current = nullptr;

    if (!empty) {
        _numCycles++;
        _changeStamp++;
    }

    if (_stopNow) {
        status(StatusOther);
        return;
    }

    runUpdate();
    if (!traceFiles.empty())
        trace(true);
    runDelta();

    if (!runToTime && starved())
        scheduleStarvationEvent();

    if (runOnce)
        schedulePause();

    status(StatusOther);
}

void
Scheduler::runUpdate()
{
    status(StatusUpdate);

    try {
        Channel *channel = updateList.getNext();
        while (channel) {
            channel->popListNode();
            channel->update();
            channel = updateList.getNext();
        }
    } catch (...) {
        throwUp();
    }
}

void
Scheduler::runDelta()
{
    status(StatusDelta);

    try {
        while (!deltas.empty())
            deltas.back()->run();
    } catch (...) {
        throwUp();
    }
}

void
Scheduler::pause()
{
    status(StatusPaused);
    kernel->status(::sc_core::SC_PAUSED);
    runOnce = false;
    if (scMainFiber.called() && !scMainFiber.finished())
        scMainFiber.run();
}

void
Scheduler::stop()
{
    status(StatusStopped);
    kernel->stop();

    clear();

    runOnce = false;
    if (scMainFiber.called() && !scMainFiber.finished())
        scMainFiber.run();
}

void
Scheduler::start(Tick max_tick, bool run_to_time)
{
    _started = true;
    status(StatusOther);
    runToTime = run_to_time;

    maxTick = max_tick;
    lastReadyTick = getCurTick();

    if (initDone) {
        if (!runToTime && starved())
            scheduleStarvationEvent();
        kernel->status(::sc_core::SC_RUNNING);
    }

    schedule(&maxTickEvent, maxTick);
    scheduleTimeAdvancesEvent();

    // Return to gem5 to let it run events, etc.
    Fiber::primaryFiber()->run();

    if (pauseEvent.scheduled())
        deschedule(&pauseEvent);
    if (stopEvent.scheduled())
        deschedule(&stopEvent);
    if (maxTickEvent.scheduled())
        deschedule(&maxTickEvent);
    if (starvationEvent.scheduled())
        deschedule(&starvationEvent);

    if (_throwUp) {
        const ::sc_core::sc_report *to_throw = _throwUp;
        _throwUp = nullptr;
        throw *to_throw;
    }
}

void
Scheduler::oneCycle()
{
    runOnce = true;
    scheduleReadyEvent();
    start(::MaxTick, false);
}

void
Scheduler::schedulePause()
{
    if (pauseEvent.scheduled())
        return;

    schedule(&pauseEvent);
}

void
Scheduler::throwUp()
{
    if (scMainFiber.called() && !scMainFiber.finished()) {
        ::sc_core::sc_report report = reportifyException();
        _throwUp = &report;
        status(StatusOther);
        scMainFiber.run();
    } else {
        reportHandlerProc(reportifyException(),
                ::sc_core::sc_report_handler::get_catch_actions());
    }
}

void
Scheduler::scheduleStop(bool finish_delta)
{
    if (stopEvent.scheduled())
        return;

    if (!finish_delta) {
        _stopNow = true;
        // If we're not supposed to finish the delta cycle, flush all
        // pending activity.
        clear();
    }
    schedule(&stopEvent);
}

void
Scheduler::trace(bool delta)
{
    for (auto tf: traceFiles)
        tf->trace(delta);
}

Scheduler scheduler;
Process *getCurrentProcess() { return scheduler.current(); }

namespace {

void
throwingReportHandler(const ::sc_core::sc_report &r,
                      const ::sc_core::sc_actions &)
{
    throw r;
}

} // anonymous namespace

const ::sc_core::sc_report
reportifyException()
{
    ::sc_core::sc_report_handler_proc old_handler = reportHandlerProc;
    ::sc_core::sc_report_handler::set_handler(&throwingReportHandler);

    try {
        try {
            // Rethrow the current exception so we can catch it and throw an
            // sc_report instead if it's not a type we recognize/can handle.
            throw;
        } catch (const ::sc_core::sc_report &) {
            // It's already a sc_report, so nothing to do.
            throw;
        } catch (const ::sc_core::sc_unwind_exception &) {
            panic("Kill/reset exception escaped a Process::run()");
        } catch (const std::exception &e) {
            SC_REPORT_ERROR(
                    sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, e.what());
        } catch (const char *msg) {
            SC_REPORT_ERROR(
                    sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, msg);
        } catch (...) {
            SC_REPORT_ERROR(
                    sc_core::SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_,
                    "UNKNOWN EXCEPTION");
        }
    } catch (const ::sc_core::sc_report &r) {
        ::sc_core::sc_report_handler::set_handler(old_handler);
        return r;
    }
    panic("No exception thrown in reportifyException.");
}

} // namespace sc_gem5
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */

# include  "vtype.h"
# include  <typeinfo>

using namespace std;

std::map<perm_string, const VType*> global_types;

const VTypePrimitive primitive_BOOLEAN (VTypePrimitive::BOOLEAN);
const VTypePrimitive primitive_BIT     (VTypePrimitive::BIT);;
const VTypePrimitive primitive_INTEGER (VTypePrimitive::INTEGER);;
const VTypePrimitive primitive_STDLOGIC(VTypePrimitive::STDLOGIC);;

const VTypeArray primitive_BIT_VECTOR(&primitive_BIT,      vector<VTypeArray::range_t> (1));
const VTypeArray primitive_BOOL_VECTOR(&primitive_BOOLEAN, vector<VTypeArray::range_t> (1));

void preload_global_types(void)
{
      global_types[perm_string::literal("boolean")]   = &primitive_BOOLEAN;
      global_types[perm_string::literal("bit")]       = &primitive_BIT;
      global_types[perm_string::literal("integer")]   = &primitive_INTEGER;
      global_types[perm_string::literal("std_logic")] = &primitive_STDLOGIC;
      global_types[perm_string::literal("bit_vector")]= &primitive_BOOL_VECTOR;
}

void import_ieee(void)
{
}

static void import_ieee_use_std_logic_1164(perm_string)
{
}

static void import_ieee_use_numeric_bit(perm_string name)
{
      bool all_flag = name=="all";

      if (all_flag || name == "signed") {
	    vector<VTypeArray::range_t> dims (1);
	    global_types[perm_string::literal("signed")] = new VTypeArray(&primitive_STDLOGIC, dims, true);
      }
      if (all_flag || name == "unsigned") {
	    vector<VTypeArray::range_t> dims (1);
	    global_types[perm_string::literal("unsigned")] = new VTypeArray(&primitive_BIT, dims, false);
      }
}

static void import_ieee_use_numeric_std(perm_string name)
{
      bool all_flag = name=="all";

      if (all_flag || name == "signed") {
	    vector<VTypeArray::range_t> dims (1);
	    global_types[perm_string::literal("signed")] = new VTypeArray(&primitive_STDLOGIC, dims);
      }
      if (all_flag || name == "unsigned") {
	    vector<VTypeArray::range_t> dims (1);
	    global_types[perm_string::literal("unsigned")] = new VTypeArray(&primitive_STDLOGIC, dims);
      }
}

void import_ieee_use(perm_string package, perm_string name)
{
      if (package == "std_logic_1164") {
	    import_ieee_use_std_logic_1164(name);
	    return;
      }

      if (package == "numeric_bit") {
	    import_ieee_use_numeric_bit(name);
	    return;
      }

      if (package == "numeric_std") {
	    import_ieee_use_numeric_std(name);
	    return;
      }
}

VType::~VType()
{
}

void VType::show(ostream&out) const
{
      out << typeid(*this).name();
}

VTypePrimitive::VTypePrimitive(VTypePrimitive::type_t tt)
: type_(tt)
{
}

VTypePrimitive::~VTypePrimitive()
{
}

void VTypePrimitive::show(ostream&out) const
{
      switch (type_) {
	  case BOOLEAN:
	    out << "BOOLEAN";
	    break;
	  case BIT:
	    out << "BIT";
	    break;
	  case INTEGER:
	    out << "INTEGER";
	    break;
	  case STDLOGIC:
	    out << "std_logic";
	    break;
      }
}

VTypeArray::VTypeArray(const VType*element, const vector<VTypeArray::range_t>&r, bool sv)
: etype_(element), ranges_(r), signed_flag_(sv)
{
}

VTypeArray::~VTypeArray()
{
}

size_t VTypeArray::dimensions() const
{
      return ranges_.size();
}

const VType* VTypeArray::element_type() const
{
      return etype_;
}

void VTypeArray::show(ostream&out) const
{
      out << "array ";
      for (vector<range_t>::const_iterator cur = ranges_.begin()
		 ; cur != ranges_.end() ; ++cur) {
	    out << "(" << cur->msb() << " downto " << cur->lsb() << ")";
      }
      out << " of ";
      if (signed_flag_)
	    out << "signed ";
      if (etype_)
	    etype_->show(out);
      else
	    out << "<nil>";
}
<commit_msg>Handle signed stdlogic.<commit_after>/*
 * Copyright (c) 2011 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */

# include  "vtype.h"
# include  <typeinfo>

using namespace std;

std::map<perm_string, const VType*> global_types;

const VTypePrimitive primitive_BOOLEAN (VTypePrimitive::BOOLEAN);
const VTypePrimitive primitive_BIT     (VTypePrimitive::BIT);;
const VTypePrimitive primitive_INTEGER (VTypePrimitive::INTEGER);;
const VTypePrimitive primitive_STDLOGIC(VTypePrimitive::STDLOGIC);;

const VTypeArray primitive_BIT_VECTOR(&primitive_BIT,      vector<VTypeArray::range_t> (1));
const VTypeArray primitive_BOOL_VECTOR(&primitive_BOOLEAN, vector<VTypeArray::range_t> (1));

void preload_global_types(void)
{
      global_types[perm_string::literal("boolean")]   = &primitive_BOOLEAN;
      global_types[perm_string::literal("bit")]       = &primitive_BIT;
      global_types[perm_string::literal("integer")]   = &primitive_INTEGER;
      global_types[perm_string::literal("std_logic")] = &primitive_STDLOGIC;
      global_types[perm_string::literal("bit_vector")]= &primitive_BOOL_VECTOR;
}

void import_ieee(void)
{
}

static void import_ieee_use_std_logic_1164(perm_string name)
{
      bool all_flag = name=="all";

      if (all_flag || name == "std_logic_vector") {
	    vector<VTypeArray::range_t> dims (1);
	    global_types[perm_string::literal("std_logic_vector")] = new VTypeArray(&primitive_STDLOGIC, dims, false);
      }
}

static void import_ieee_use_numeric_bit(perm_string name)
{
      bool all_flag = name=="all";

      if (all_flag || name == "signed") {
	    vector<VTypeArray::range_t> dims (1);
	    global_types[perm_string::literal("signed")] = new VTypeArray(&primitive_STDLOGIC, dims, true);
      }
      if (all_flag || name == "unsigned") {
	    vector<VTypeArray::range_t> dims (1);
	    global_types[perm_string::literal("unsigned")] = new VTypeArray(&primitive_BIT, dims, false);
      }
}

static void import_ieee_use_numeric_std(perm_string name)
{
      bool all_flag = name=="all";

      if (all_flag || name == "signed") {
	    vector<VTypeArray::range_t> dims (1);
	    global_types[perm_string::literal("signed")] = new VTypeArray(&primitive_STDLOGIC, dims, true);
      }
      if (all_flag || name == "unsigned") {
	    vector<VTypeArray::range_t> dims (1);
	    global_types[perm_string::literal("unsigned")] = new VTypeArray(&primitive_STDLOGIC, dims, false);
      }
}

void import_ieee_use(perm_string package, perm_string name)
{
      if (package == "std_logic_1164") {
	    import_ieee_use_std_logic_1164(name);
	    return;
      }

      if (package == "numeric_bit") {
	    import_ieee_use_numeric_bit(name);
	    return;
      }

      if (package == "numeric_std") {
	    import_ieee_use_numeric_std(name);
	    return;
      }
}

VType::~VType()
{
}

void VType::show(ostream&out) const
{
      out << typeid(*this).name();
}

VTypePrimitive::VTypePrimitive(VTypePrimitive::type_t tt)
: type_(tt)
{
}

VTypePrimitive::~VTypePrimitive()
{
}

void VTypePrimitive::show(ostream&out) const
{
      switch (type_) {
	  case BOOLEAN:
	    out << "BOOLEAN";
	    break;
	  case BIT:
	    out << "BIT";
	    break;
	  case INTEGER:
	    out << "INTEGER";
	    break;
	  case STDLOGIC:
	    out << "std_logic";
	    break;
      }
}

VTypeArray::VTypeArray(const VType*element, const vector<VTypeArray::range_t>&r, bool sv)
: etype_(element), ranges_(r), signed_flag_(sv)
{
}

VTypeArray::~VTypeArray()
{
}

size_t VTypeArray::dimensions() const
{
      return ranges_.size();
}

const VType* VTypeArray::element_type() const
{
      return etype_;
}

void VTypeArray::show(ostream&out) const
{
      out << "array ";
      for (vector<range_t>::const_iterator cur = ranges_.begin()
		 ; cur != ranges_.end() ; ++cur) {
	    out << "(" << cur->msb() << " downto " << cur->lsb() << ")";
      }
      out << " of ";
      if (signed_flag_)
	    out << "signed ";
      if (etype_)
	    etype_->show(out);
      else
	    out << "<nil>";
}
<|endoftext|>


<commit_before>// Copyright 2016 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
#include <stddef.h>
#include <stdint.h>
#include <vector>

#include "archive.h"

struct Buffer {
  const uint8_t *buf;
  size_t len;
};

ssize_t reader_callback(struct archive *a, void *client_data,
                        const void **block) {
  Buffer *buffer = reinterpret_cast<Buffer *>(client_data);
  *block = buffer->buf;
  ssize_t len = buffer->len;
  buffer->len = 0;
  return len;
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
  int ret;
  ssize_t r;
  struct archive *a = archive_read_new();

  archive_read_support_filter_all(a);
  archive_read_support_format_all(a);
  archive_read_support_format_empty(a);
  archive_read_support_format_raw(a);

  archive_read_set_options(a, "zip:ignorecrc32");

  Buffer buffer = {buf, len};
  archive_read_open(a, &buffer, NULL, reader_callback, NULL);

  std::vector<uint8_t> data_buffer(getpagesize(), 0);
  struct archive_entry *entry;
  while(1) {
    ret = archive_read_next_header(a, &entry);
    if (ret == ARCHIVE_EOF || ret == ARCHIVE_FATAL)
      break;
    if (ret == ARCHIVE_RETRY)
      continue;
    while ((r = archive_read_data(a, data_buffer.data(),
            data_buffer.size())) > 0)
      ;
    if (r == ARCHIVE_FATAL)
      break;
  }

  archive_read_free(a);
  return 0;
}
<commit_msg>Improve coverage of tar files in libarchive (#8744)<commit_after>// Copyright 2016 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
#include <stddef.h>
#include <stdint.h>
#include <vector>

#include "archive.h"

struct Buffer {
  const uint8_t *buf;
  size_t len;
};

ssize_t reader_callback(struct archive *a, void *client_data,
                        const void **block) {
  Buffer *buffer = reinterpret_cast<Buffer *>(client_data);
  *block = buffer->buf;
  ssize_t len = buffer->len;
  buffer->len = 0;
  return len;
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
  int ret;
  ssize_t r;
  struct archive *a = archive_read_new();

  archive_read_support_filter_all(a);
  archive_read_support_format_all(a);
  archive_read_support_format_empty(a);
  archive_read_support_format_raw(a);

  if (ARCHIVE_OK != archive_read_set_options(a, "zip:ignorecrc32,tar:read_concatenated_archives,tar:mac-ext")) {
    return 0;
  }

  Buffer buffer = {buf, len};
  archive_read_open(a, &buffer, NULL, reader_callback, NULL);

  std::vector<uint8_t> data_buffer(getpagesize(), 0);
  struct archive_entry *entry;
  while(1) {
    ret = archive_read_next_header(a, &entry);
    if (ret == ARCHIVE_EOF || ret == ARCHIVE_FATAL)
      break;
    if (ret == ARCHIVE_RETRY)
      continue;
    while ((r = archive_read_data(a, data_buffer.data(),
            data_buffer.size())) > 0)
      ;
    if (r == ARCHIVE_FATAL)
      break;
  }

  archive_read_free(a);
  return 0;
}
<|endoftext|>


<commit_before>/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */

#include "proton_bits.hpp"

#include "proton/connection.hpp"
#include "proton/container.hpp"
#include "proton/error.hpp"
#include "proton/event_loop.hpp"
#include "proton/session.hpp"
#include "proton/transport.hpp"

#include "connector.hpp"
#include "contexts.hpp"
#include "msg.hpp"
#include "proton_bits.hpp"

#include <proton/connection.h>
#include <proton/session.h>
#include <proton/transport.h>
#include <proton/reactor.h>
#include <proton/object.h>

namespace proton {

transport connection::transport() const {
    return make_wrapper(pn_connection_transport(pn_object()));
}

void connection::open() {
    open(connection_options());
}

void connection::open(const connection_options &opts) {
    connector *connector = dynamic_cast<class connector*>(
        connection_context::get(pn_object()).handler.get());
    if (connector)
        // connector has an internal copy of opts
        connector->apply_options();
    else
        opts.apply(*this);
    pn_connection_open(pn_object());
}

void connection::close() { pn_connection_close(pn_object()); }

std::string connection::virtual_host() const {
    return str(pn_connection_get_hostname(pn_object()));
}

std::string connection::container_id() const {
    return str(pn_connection_get_container(pn_object()));
}

container& connection::container() const {
    class container* c = connection_context::get(pn_object()).container;
    if (!c) {
        pn_reactor_t *r = pn_object_reactor(pn_object());
        if (r)
            c = &container_context::get(r);
    }
    if (!c)
        throw proton::error("connection does not have a container");
    return *c;
}

session_range connection::sessions() const {
    return session_range(session_iterator(make_wrapper(pn_session_head(pn_object(), 0))));
}

receiver_range connection::receivers() const {
  pn_link_t *lnk = pn_link_head(pn_object(), 0);
  while (lnk) {
    if (pn_link_is_receiver(lnk))
      break;
    lnk = pn_link_next(lnk, 0);
  }
  return receiver_range(receiver_iterator(make_wrapper<receiver>(lnk)));
}

sender_range connection::senders() const {
  pn_link_t *lnk = pn_link_head(pn_object(), 0);
  while (lnk) {
    if (pn_link_is_sender(lnk))
      break;
    lnk = pn_link_next(lnk, 0);
  }
  return sender_range(sender_iterator(make_wrapper<sender>(lnk)));
}

session connection::open_session() {
    return open_session(session_options());
}

session connection::open_session(const session_options &opts) {
    session s(make_wrapper<session>(pn_session(pn_object())));
    // TODO: error check, too many sessions, no mem...
    if (!!s) s.open(opts);
    return s;
}

session connection::default_session() {
    connection_context& ctx = connection_context::get(pn_object());
    if (!ctx.default_session) {
        // Note we can't use a proton::session here because we don't want to own
        // a session reference. The connection owns the session, owning it here as well
        // would create a circular ownership.
        ctx.default_session = pn_session(pn_object());
        pn_session_open(ctx.default_session);
    }
    return make_wrapper(ctx.default_session);
}

sender connection::open_sender(const std::string &addr) {
    return open_sender(addr, sender_options());
}

sender connection::open_sender(const std::string &addr, const sender_options &opts) {
    return default_session().open_sender(addr, opts);
}

receiver connection::open_receiver(const std::string &addr) {
    return open_receiver(addr, receiver_options());
}

receiver connection::open_receiver(const std::string &addr, const receiver_options &opts)
{
    return default_session().open_receiver(addr, opts);
}

error_condition connection::error() const {
    return make_wrapper(pn_connection_remote_condition(pn_object()));
}

uint32_t connection::max_frame_size() const {
    return pn_transport_get_remote_max_frame(pn_connection_transport(pn_object()));
}

uint16_t connection::max_sessions() const {
    return pn_transport_remote_channel_max(pn_connection_transport(pn_object()));
}

uint32_t connection::idle_timeout() const {
    return pn_transport_get_remote_idle_timeout(pn_connection_transport(pn_object()));
}

void connection::user(const std::string &name) { pn_connection_set_user(pn_object(), name.c_str()); }

void connection::password(const std::string &pass) { pn_connection_set_password(pn_object(), pass.c_str()); }

}
<commit_msg>PROTON-1240: Fill in connection::virtual_host() with remote connection host field<commit_after>/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */

#include "proton_bits.hpp"

#include "proton/connection.hpp"
#include "proton/container.hpp"
#include "proton/error.hpp"
#include "proton/event_loop.hpp"
#include "proton/session.hpp"
#include "proton/transport.hpp"

#include "connector.hpp"
#include "contexts.hpp"
#include "msg.hpp"
#include "proton_bits.hpp"

#include <proton/connection.h>
#include <proton/session.h>
#include <proton/transport.h>
#include <proton/reactor.h>
#include <proton/object.h>

namespace proton {

transport connection::transport() const {
    return make_wrapper(pn_connection_transport(pn_object()));
}

void connection::open() {
    open(connection_options());
}

void connection::open(const connection_options &opts) {
    connector *connector = dynamic_cast<class connector*>(
        connection_context::get(pn_object()).handler.get());
    if (connector)
        // connector has an internal copy of opts
        connector->apply_options();
    else
        opts.apply(*this);
    pn_connection_open(pn_object());
}

void connection::close() { pn_connection_close(pn_object()); }

std::string connection::virtual_host() const {
    return str(pn_connection_remote_hostname(pn_object()));
}

std::string connection::container_id() const {
    return str(pn_connection_get_container(pn_object()));
}

container& connection::container() const {
    class container* c = connection_context::get(pn_object()).container;
    if (!c) {
        pn_reactor_t *r = pn_object_reactor(pn_object());
        if (r)
            c = &container_context::get(r);
    }
    if (!c)
        throw proton::error("connection does not have a container");
    return *c;
}

session_range connection::sessions() const {
    return session_range(session_iterator(make_wrapper(pn_session_head(pn_object(), 0))));
}

receiver_range connection::receivers() const {
  pn_link_t *lnk = pn_link_head(pn_object(), 0);
  while (lnk) {
    if (pn_link_is_receiver(lnk))
      break;
    lnk = pn_link_next(lnk, 0);
  }
  return receiver_range(receiver_iterator(make_wrapper<receiver>(lnk)));
}

sender_range connection::senders() const {
  pn_link_t *lnk = pn_link_head(pn_object(), 0);
  while (lnk) {
    if (pn_link_is_sender(lnk))
      break;
    lnk = pn_link_next(lnk, 0);
  }
  return sender_range(sender_iterator(make_wrapper<sender>(lnk)));
}

session connection::open_session() {
    return open_session(session_options());
}

session connection::open_session(const session_options &opts) {
    session s(make_wrapper<session>(pn_session(pn_object())));
    // TODO: error check, too many sessions, no mem...
    if (!!s) s.open(opts);
    return s;
}

session connection::default_session() {
    connection_context& ctx = connection_context::get(pn_object());
    if (!ctx.default_session) {
        // Note we can't use a proton::session here because we don't want to own
        // a session reference. The connection owns the session, owning it here as well
        // would create a circular ownership.
        ctx.default_session = pn_session(pn_object());
        pn_session_open(ctx.default_session);
    }
    return make_wrapper(ctx.default_session);
}

sender connection::open_sender(const std::string &addr) {
    return open_sender(addr, sender_options());
}

sender connection::open_sender(const std::string &addr, const sender_options &opts) {
    return default_session().open_sender(addr, opts);
}

receiver connection::open_receiver(const std::string &addr) {
    return open_receiver(addr, receiver_options());
}

receiver connection::open_receiver(const std::string &addr, const receiver_options &opts)
{
    return default_session().open_receiver(addr, opts);
}

error_condition connection::error() const {
    return make_wrapper(pn_connection_remote_condition(pn_object()));
}

uint32_t connection::max_frame_size() const {
    return pn_transport_get_remote_max_frame(pn_connection_transport(pn_object()));
}

uint16_t connection::max_sessions() const {
    return pn_transport_remote_channel_max(pn_connection_transport(pn_object()));
}

uint32_t connection::idle_timeout() const {
    return pn_transport_get_remote_idle_timeout(pn_connection_transport(pn_object()));
}

void connection::user(const std::string &name) { pn_connection_set_user(pn_object(), name.c_str()); }

void connection::password(const std::string &pass) { pn_connection_set_password(pn_object(), pass.c_str()); }

}
<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010 Francois Beaune
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// appleseed.foundation headers.
#include "foundation/image/color.h"
#include "foundation/image/drawing.h"
#include "foundation/image/genericimagefilewriter.h"
#include "foundation/image/image.h"
#include "foundation/math/distance.h"
#include "foundation/math/knn.h"
#include "foundation/math/rng.h"
#include "foundation/math/rr.h"
#include "foundation/math/sampling.h"
#include "foundation/math/scalar.h"
#include "foundation/math/vector.h"
#include "foundation/utility/test.h"

// Standard headers.
#include <cassert>
#include <cmath>
#include <cstddef>
#include <sstream>
#include <vector>

using namespace foundation;
using namespace std;

TEST_SUITE(Exploration_PointCloudSampling)
{
    Vector2d sample_disk_non_uniform(const Vector2d& s)
    {
        return (1.0 - s[0]) * sample_circle_uniform(s[1]);
    }

    Vector2d sample_disk_uniform(
        const Vector2d&             center,
        const double                radius,
        const Vector2d&             s)
    {
        return center + radius * sample_disk_uniform_alt(s);
    }

    Vector2d sample_disk_non_uniform(
        const Vector2d&             center,
        const double                radius,
        const Vector2d&             s)
    {
        return center + radius * sample_disk_non_uniform(s);
    }

    void random_barycentric_coordinates(
        MersenneTwister&            rng,
        const size_t                count,
        double                      bary[])
    {
        double sum = 0.0;

        for (size_t i = 0; i < count; ++i)
        {
            const double s = 1.0 - rand_double2(rng);
            bary[i] = s;
            sum += s;
        }

        assert(sum > 0.0);

        const double rcp_sum = 1.0 / sum;

        for (size_t i = 0; i < count; ++i)
            bary[i] *= rcp_sum;
    }

    void generate_random_initial_points(
        MersenneTwister&            rng,
        vector<Vector2d>&           points,
        const size_t                count)
    {
        const Vector2d ArcOrigin(0.25, 0.25);
        const double ArcRadius = 0.5;
        const double DiskRadius = 0.1;
        const size_t ArcSteps = 10;

        for (size_t i = 0; i < ArcSteps; ++i)
        {
            const double alpha = HalfPi * static_cast<double>(i) / (ArcSteps - 1);

            const Vector2d center(
                ArcOrigin.x + ArcRadius * cos(alpha),
                ArcOrigin.y + ArcRadius * sin(alpha));

            for (size_t j = 0; j < count / ArcSteps; ++j)
            {
                Vector2d s;
                s[0] = rand_double2(rng);
                s[1] = rand_double2(rng);
                points.push_back(sample_disk_uniform(center, DiskRadius, s));
            }
        }
    }

    //
    // Method   Algorithm
    //
    //   M1     Non-uniform sampling of fixed-radius disks centered on initial points
    //   M2     Non-uniform sampling of disks extending to the farthest of the K nearest
    //          neighbors around initial points
    //   M3     Uniform sampling of triangles whose vertices are random initial points
    //   M4     Uniform sampling of triangles built from the three closest neighbors around
    //          random query points
    //   M5     Old Particle Porn algorithm: apply M4 around points selected via M1
    //   M6     New Particle Porn algorithm: M1 with probabilistic rejection of new points
    //          that are too far from their neighbors
    //

    void generate_new_random_points(
        MersenneTwister&            rng,
        vector<Vector2d>&           new_points,
        const vector<Vector2d>&     initial_points,
        const size_t                multiplication_rate,
        const size_t                method)
    {
        const double SamplingRadius = 0.1;
        const size_t NeighborCount = 3;

        assert(NeighborCount >= 3);     // in order to build triangles from nearest neighbors

        knn::Tree2d tree;
        knn::Builder2d builder(tree);
        builder.build(&initial_points[0], initial_points.size());

        knn::Answer<double> answer(NeighborCount);
        knn::Query2d query(tree, answer);

        for (size_t i = 0; i < initial_points.size(); ++i)
        {
            for (size_t j = 0; j < multiplication_rate - 1; ++j)
            {
                if (method == 1)
                {
                    Vector2d s;
                    s[0] = rand_double2(rng);
                    s[1] = rand_double2(rng);

                    const Vector2d p =
                        sample_disk_non_uniform(initial_points[i], SamplingRadius, s);

                    new_points.push_back(p);
                }
                else if (method == 2)
                {
                    query.run(initial_points[i]);
                    answer.sort();

                    const double radius =
                        sqrt(
                            square_distance(
                                initial_points[i],
                                initial_points[answer.get(NeighborCount - 1).m_index]));

                    Vector2d s;
                    s[0] = rand_double2(rng);
                    s[1] = rand_double2(rng);

                    const Vector2d p =
                        sample_disk_non_uniform(initial_points[i], radius, s);

                    new_points.push_back(p);
                }
                else if (method == 3)
                {
                    Vector2d v[3];
                    v[0] = initial_points[rand_int1(rng, 0, initial_points.size() - 1)];
                    v[1] = initial_points[rand_int1(rng, 0, initial_points.size() - 1)];
                    v[2] = initial_points[rand_int1(rng, 0, initial_points.size() - 1)];

                    Vector2d s;
                    s[0] = rand_double2(rng);
                    s[1] = rand_double2(rng);

                    const Vector3d knn_bary = sample_triangle_uniform(s);

                    Vector2d new_point(0.0);

                    for (size_t w = 0; w < 3; ++w)
                        new_point += knn_bary[w] * v[w];

                    new_points.push_back(new_point);
                }
                else if (method == 4)
                {
                    Vector2d p;
                    p[0] = rand_double1(rng);
                    p[1] = rand_double1(rng);

                    query.run(p);

                    Vector2d s;
                    s[0] = rand_double2(rng);
                    s[1] = rand_double2(rng);

                    const Vector3d knn_bary = sample_triangle_uniform(s);

                    Vector2d new_point(0.0);

                    for (size_t w = 0; w < 3; ++w)
                    {
                        const size_t neighbor_index = answer.get(w).m_index;
                        new_point += knn_bary[w] * initial_points[neighbor_index];
                    }

                    new_points.push_back(new_point);
                }
                else if (method == 5)
                {
                    Vector2d s;
                    s[0] = rand_double2(rng);
                    s[1] = rand_double2(rng);

                    const Vector2d p =
                        sample_disk_non_uniform(initial_points[i], SamplingRadius, s);

                    query.run(p);

                    double knn_bary[NeighborCount];
                    random_barycentric_coordinates(rng, NeighborCount, knn_bary);

                    Vector2d new_point(0.0);

                    for (size_t w = 0; w < NeighborCount; ++w)
                    {
                        const size_t neighbor_index = answer.get(w).m_index;
                        new_point += knn_bary[w] * initial_points[neighbor_index];
                    }

                    new_points.push_back(new_point);
                }
                else if (method == 6)
                {
                    while (true)
                    {
                        Vector2d s;
                        s[0] = rand_double2(rng);
                        s[1] = rand_double2(rng);

                        const Vector2d p =
                            sample_disk_uniform(initial_points[i], SamplingRadius, s);

                        query.run(p);

                        double avg_dist = 0.0;
                        for (size_t w = 0; w < NeighborCount; ++w)
                            avg_dist += answer.get(w).m_distance;
                        avg_dist /= NeighborCount;

                        const double Tension = 80.0;
                        const double k = avg_dist / SamplingRadius;
                        const double acceptance_prob = exp(-k * Tension);

                        if (pass_rr(acceptance_prob, rand_double2(rng)))
                        {
                            new_points.push_back(p);
                            break;
                        }
                    }
                }
                else
                {
                    assert(!"Unknown method");
                }
            }
        }
    }

    TEST_CASE(Main)
    {
        MersenneTwister rng;

        vector<Vector2d> initial_points;
        generate_random_initial_points(rng, initial_points, 100);

        for (size_t method = 1; method <= 6; ++method)
        {
            vector<Vector2d> new_points;
            generate_new_random_points(rng, new_points, initial_points, 100, method);

            Image image(
                1024,
                1024,
                32,
                32,
                3,
                PixelFormatFloat);

            image.clear(Color3f(0.0f));

            for (size_t i = 0; i < new_points.size(); ++i)
                Drawing::draw_dot(image, new_points[i], Color3f(0.2f));

            for (size_t i = 0; i < initial_points.size(); ++i)
                Drawing::draw_dot(image, initial_points[i], Color3f(1.0f, 1.0f, 0.0f));

            stringstream sstr;
            sstr << "output/test_pointcloudsampling_M" << method << ".png";

            GenericImageFileWriter().write(sstr.str().c_str(), image);
        }
    }
}
<commit_msg>more experiments on point cloud resampling.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010 Francois Beaune
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// appleseed.foundation headers.
#include "foundation/image/color.h"
#include "foundation/image/drawing.h"
#include "foundation/image/genericimagefilewriter.h"
#include "foundation/image/image.h"
#include "foundation/math/area.h"
#include "foundation/math/distance.h"
#include "foundation/math/knn.h"
#include "foundation/math/rng.h"
#include "foundation/math/rr.h"
#include "foundation/math/sampling.h"
#include "foundation/math/scalar.h"
#include "foundation/math/vector.h"
#include "foundation/utility/test.h"

// Standard headers.
#include <cassert>
#include <cmath>
#include <cstddef>
#include <sstream>
#include <vector>

using namespace foundation;
using namespace std;

TEST_SUITE(Exploration_PointCloudSampling)
{
    Vector2d sample_disk_non_uniform(const Vector2d& s)
    {
        return (1.0 - s[0]) * sample_circle_uniform(s[1]);
    }

    Vector2d sample_disk_uniform(
        const Vector2d&             center,
        const double                radius,
        const Vector2d&             s)
    {
        return center + radius * sample_disk_uniform_alt(s);
    }

    Vector2d sample_disk_non_uniform(
        const Vector2d&             center,
        const double                radius,
        const Vector2d&             s)
    {
        return center + radius * sample_disk_non_uniform(s);
    }

    void random_barycentric_coordinates(
        MersenneTwister&            rng,
        const size_t                count,
        double                      bary[])
    {
        double sum = 0.0;

        for (size_t i = 0; i < count; ++i)
        {
            const double s = 1.0 - rand_double2(rng);
            bary[i] = s;
            sum += s;
        }

        assert(sum > 0.0);

        const double rcp_sum = 1.0 / sum;

        for (size_t i = 0; i < count; ++i)
            bary[i] *= rcp_sum;
    }

    void generate_random_initial_points_bean(
        MersenneTwister&            rng,
        vector<Vector2d>&           points,
        const size_t                count)
    {
        const Vector2d ArcOrigin(0.25, 0.25);
        const double ArcRadius = 0.5;
        const double DiskRadius = 0.1;
        const size_t ArcSteps = 10;

        for (size_t i = 0; i < ArcSteps; ++i)
        {
            const double alpha = HalfPi * static_cast<double>(i) / (ArcSteps - 1);

            const Vector2d center(
                ArcOrigin.x + ArcRadius * cos(alpha),
                ArcOrigin.y + ArcRadius * sin(alpha));

            for (size_t j = 0; j < count / ArcSteps; ++j)
            {
                Vector2d s;
                s[0] = rand_double2(rng);
                s[1] = rand_double2(rng);
                points.push_back(sample_disk_uniform(center, DiskRadius, s));
            }
        }
    }

    void generate_random_initial_points_disk(
        MersenneTwister&            rng,
        vector<Vector2d>&           points,
        const size_t                count)
    {
        const Vector2d Center(0.5, 0.5);
        const double Radius = 0.2;

        for (size_t i = 0; i < count; ++i)
        {
            Vector2d s;
            s[0] = rand_double2(rng);
            s[1] = rand_double2(rng);
            points.push_back(sample_disk_uniform(Center, Radius, s));
        }
    }

    void generate_random_initial_points_circle(
        MersenneTwister&            rng,
        vector<Vector2d>&           points,
        const size_t                count)
    {
        const Vector2d Center(0.5, 0.5);
        const double Radius = 0.2;

        for (size_t i = 0; i < count; ++i)
            points.push_back(Center + Radius * sample_circle_uniform(rand_double2(rng)));
    }

    // todo: move to foundation/math/area.h.
    template <typename T>
    T triangle_area(
        const Vector<T, 2>& v0,
        const Vector<T, 2>& v1,
        const Vector<T, 2>& v2)
    {
        const Vector<T, 2> e0 = v1 - v0;
        const Vector<T, 2> e1 = v2 - v0;
        return T(0.5) * abs((v1.x - v0.x) * (v2.y - v0.y) - (v2.x - v0.x) * (v1.y - v0.y));
    }

    //
    // Method   Algorithm
    //
    //   M1     Non-uniform sampling of fixed-radius disks centered on initial points
    //   M2     Non-uniform sampling of disks extending to the farthest of the K nearest
    //          neighbors around initial points
    //   M3     Uniform sampling of triangles whose vertices are random initial points
    //   M4     Uniform sampling of triangles built from the three closest neighbors around
    //          random query points
    //   M5     Old Particle Porn algorithm: apply M4 around points selected via M1
    //   M6     New Particle Porn algorithm: M1 with probabilistic rejection of new points
    //          that are too far from their neighbors
    //   M7     Surface method
    //

    void generate_new_random_points(
        MersenneTwister&            rng,
        vector<Vector2d>&           new_points,
        const vector<Vector2d>&     initial_points,
        const size_t                multiplication_rate,
        const size_t                method)
    {
        const double SamplingRadius = 0.025;
        const size_t NeighborCount = 3;

        assert(NeighborCount >= 3);     // in order to build triangles from nearest neighbors

        knn::Tree2d tree;
        knn::Builder2d builder(tree);
        builder.build(&initial_points[0], initial_points.size());

        knn::Answer<double> answer(NeighborCount);
        knn::Query2d query(tree, answer);

        for (size_t i = 0; i < initial_points.size(); ++i)
        {
            for (size_t j = 0; j < multiplication_rate - 1; ++j)
            {
                if (method == 1)
                {
                    Vector2d s;
                    s[0] = rand_double2(rng);
                    s[1] = rand_double2(rng);

                    const Vector2d p =
                        sample_disk_non_uniform(initial_points[i], SamplingRadius, s);

                    new_points.push_back(p);
                }
                else if (method == 2)
                {
                    query.run(initial_points[i]);
                    answer.sort();

                    const double radius =
                        sqrt(
                            square_distance(
                                initial_points[i],
                                initial_points[answer.get(NeighborCount - 1).m_index]));

                    Vector2d s;
                    s[0] = rand_double2(rng);
                    s[1] = rand_double2(rng);

                    const Vector2d p =
                        sample_disk_non_uniform(initial_points[i], radius, s);

                    new_points.push_back(p);
                }
                else if (method == 3)
                {
                    Vector2d v[3];
                    v[0] = initial_points[rand_int1(rng, 0, initial_points.size() - 1)];
                    v[1] = initial_points[rand_int1(rng, 0, initial_points.size() - 1)];
                    v[2] = initial_points[rand_int1(rng, 0, initial_points.size() - 1)];

                    Vector2d s;
                    s[0] = rand_double2(rng);
                    s[1] = rand_double2(rng);

                    const Vector3d knn_bary = sample_triangle_uniform(s);

                    Vector2d new_point(0.0);

                    for (size_t w = 0; w < 3; ++w)
                        new_point += knn_bary[w] * v[w];

                    new_points.push_back(new_point);
                }
                else if (method == 4)
                {
                    Vector2d p;
                    p[0] = rand_double1(rng);
                    p[1] = rand_double1(rng);

                    query.run(p);

                    Vector2d s;
                    s[0] = rand_double2(rng);
                    s[1] = rand_double2(rng);

                    const Vector3d knn_bary = sample_triangle_uniform(s);

                    Vector2d new_point(0.0);

                    for (size_t w = 0; w < 3; ++w)
                    {
                        const size_t neighbor_index = answer.get(w).m_index;
                        new_point += knn_bary[w] * initial_points[neighbor_index];
                    }

                    new_points.push_back(new_point);
                }
                else if (method == 5)
                {
                    Vector2d s;
                    s[0] = rand_double2(rng);
                    s[1] = rand_double2(rng);

                    const Vector2d p =
                        sample_disk_non_uniform(initial_points[i], SamplingRadius, s);

                    query.run(p);

                    double knn_bary[NeighborCount];
                    random_barycentric_coordinates(rng, NeighborCount, knn_bary);

                    Vector2d new_point(0.0);

                    for (size_t w = 0; w < NeighborCount; ++w)
                    {
                        const size_t neighbor_index = answer.get(w).m_index;
                        new_point += knn_bary[w] * initial_points[neighbor_index];
                    }

                    new_points.push_back(new_point);
                }
                else if (method == 6)
                {
                    while (true)
                    {
                        Vector2d s;
                        s[0] = rand_double2(rng);
                        s[1] = rand_double2(rng);

                        const Vector2d p =
                            sample_disk_uniform(initial_points[i], SamplingRadius, s);

                        query.run(p);

                        double avg_dist = 0.0;
                        for (size_t w = 0; w < NeighborCount; ++w)
                            avg_dist += answer.get(w).m_distance;
                        avg_dist /= NeighborCount;

                        const double Tension = 150.0;
                        const double k = avg_dist / SamplingRadius;
                        const double acceptance_prob = exp(-k * Tension);

                        if (pass_rr(acceptance_prob, rand_double2(rng)))
                        {
                            new_points.push_back(p);
                            break;
                        }
                    }
                }
                else if (method == 7)
                {
                    query.run(initial_points[i]);

                    Vector2d avg_n(0.0);

                    for (size_t w = 0; w < NeighborCount; ++w)
                    {
                        const size_t neighbor_index = answer.get(w).m_index;
                        const Vector2d neighbor_point = initial_points[neighbor_index];
                        const Vector2d d = initial_points[i] - neighbor_point;

                        Vector2d n(-d.y, d.x);

                        if (dot(n, avg_n) < 0.0)
                            n = -n;

                        if (square_norm(n) > 0.0)
                            avg_n += normalize(n);
                    }

                    avg_n = normalize(avg_n);

                    const Vector2d plane(-avg_n.y, avg_n.x);

                    const Vector2d new_point =
                        initial_points[i] + rand_double1(rng, -SamplingRadius, SamplingRadius) * plane;

                    new_points.push_back(new_point);
                }
                else
                {
                    assert(!"Unknown method");
                }
            }
        }
    }

    TEST_CASE(Main)
    {
        MersenneTwister rng;

        vector<Vector2d> initial_points;
//      generate_random_initial_points_bean(rng, initial_points, 100);
        generate_random_initial_points_circle(rng, initial_points, 100);

        for (size_t method = 1; method <= 7; ++method)
        {
            vector<Vector2d> new_points;
            generate_new_random_points(rng, new_points, initial_points, 100, method);

            Image image(
                1024,
                1024,
                32,
                32,
                3,
                PixelFormatFloat);

            image.clear(Color3f(0.0f));

            for (size_t i = 0; i < new_points.size(); ++i)
                Drawing::draw_dot(image, new_points[i], Color3f(0.2f));

            for (size_t i = 0; i < initial_points.size(); ++i)
                Drawing::draw_dot(image, initial_points[i], Color3f(1.0f, 1.0f, 0.0f));

            stringstream sstr;
            sstr << "output/test_pointcloudsampling_M" << method << ".png";

            GenericImageFileWriter().write(sstr.str().c_str(), image);
        }
    }

    void rasterize(const Vector2d& point, Image& image)
    {
        const int Radius = 100;         // in pixels
        const double Scale = 1.0;
        const double Exponent = 2.0;

        const CanvasProperties& props = image.properties();

        const int cx = static_cast<int>(point.x * props.m_canvas_width);
        const int cy = static_cast<int>(point.y * props.m_canvas_height);
        const int max_x = static_cast<int>(props.m_canvas_width);
        const int max_y = static_cast<int>(props.m_canvas_height);

        for (int y = max(cy - Radius, 0); y < min(cy + Radius, max_y); ++y)
        {
            for (int x = max(cx - Radius, 0); x < min(cx + Radius, max_x); ++x)
            {
                const double dx2 = square(x - cx);
                const double dy2 = square(y - cy);
                const double distance = sqrt(dx2 + dy2) / Radius;
                const double intensity =
                    Scale * pow(saturate(1.0 - distance), Exponent);

                Color3f color;

                image.get_pixel(
                    static_cast<size_t>(x),
                    static_cast<size_t>(y),
                    color);

                color += Color3f(static_cast<float>(intensity));
                color = saturate(color);

                image.set_pixel(
                    static_cast<size_t>(x),
                    static_cast<size_t>(y),
                    color);
            }
        }
    }

    void rasterize(const vector<Vector2d>& points, Image& image)
    {
        for (size_t i = 0; i < points.size(); ++i)
            rasterize(points[i], image);
    }

    void apply_threshold(const double threshold, Image& image)
    {
        const CanvasProperties& props = image.properties();

        for (size_t y = 0; y < props.m_canvas_height; ++y)
        {
            for (size_t x = 0; x < props.m_canvas_width; ++x)
            {
                Color3f color;
                image.get_pixel(x, y, color);

                if (color[0] < threshold)
                    color.set(0.0f);
                else color.set(1.0f);

                image.set_pixel(x, y, color);
            }
        }
    }

    TEST_CASE(Thresholding)
    {
        MersenneTwister rng;

        vector<Vector2d> initial_points;
        generate_random_initial_points_bean(rng, initial_points, 100);

        Image image(
            1024,
            1024,
            32,
            32,
            3,
            PixelFormatFloat);

        image.clear(Color3f(0.0f));

        rasterize(initial_points, image);
        apply_threshold(0.99, image);

        for (size_t i = 0; i < initial_points.size(); ++i)
            Drawing::draw_dot(image, initial_points[i], Color3f(1.0f, 1.0f, 0.0f));

        stringstream sstr;
        sstr << "output/test_pointcloudsampling_thresholding.png";

        GenericImageFileWriter().write(sstr.str().c_str(), image);
    }
}
<|endoftext|>