<commit_before>#include "Hzzws/SystematicsManager.h"
#include <fstream>
using namespace std;

SystematicsManager::SystematicsManager(){
    all_nps = new std::vector<TString>();
}

SystematicsManager::~SystematicsManager(){
    delete all_nps;
}

SystematicsManager::SystematicsManager(const char* fileName){
    all_nps = new std::vector<TString>();
    cout << "Systematic list: " << fileName << endl;
    this->readNPs(fileName);
}

void SystematicsManager::readNPs(const char* fileName){
    if(all_nps && all_nps->size() > 1){
        std::cout<<"SystematicsManager HAVE a set of NPs!"<< std::endl;
        return;
    }
    ifstream ifile(fileName, ifstream::in);
    while (!ifile.eof()){
        TString np_name;
        ifile >> np_name;
        if (ifile.good() && np_name[0] != '#') {
            all_nps ->push_back(np_name);
        }
    }
    cout << "SystematicsManager reads in "<< all_nps->size() <<" NPs" << endl;

}

vector<TString>* SystematicsManager::add_sys(Sample* sample){
    if (all_nps->size() < 1) return NULL;
    auto* nps_vec = new vector<TString>();
    for(unsigned int i=0; i < all_nps->size(); i++){
        TString& np = all_nps->at(i);
        bool has_shape = sample -> addShapeSys( np );
        bool has_norm = sample -> addNormSys(  np );
        if(has_shape || has_norm){
            nps_vec ->push_back( np );
        }
    }
    return nps_vec;
}

<commit_msg>add normalization sys first<commit_after>#include "Hzzws/SystematicsManager.h"
#include <fstream>
using namespace std;

SystematicsManager::SystematicsManager(){
    all_nps = new std::vector<TString>();
}

SystematicsManager::~SystematicsManager(){
    delete all_nps;
}

SystematicsManager::SystematicsManager(const char* fileName){
    all_nps = new std::vector<TString>();
    cout << "Systematic list: " << fileName << endl;
    this->readNPs(fileName);
}

void SystematicsManager::readNPs(const char* fileName){
    if(all_nps && all_nps->size() > 1){
        std::cout<<"SystematicsManager HAVE a set of NPs!"<< std::endl;
        return;
    }
    ifstream ifile(fileName, ifstream::in);
    while (!ifile.eof()){
        TString np_name;
        ifile >> np_name;
        if (ifile.good() && np_name[0] != '#') {
            all_nps ->push_back(np_name);
        }
    }
    cout << "SystematicsManager reads in "<< all_nps->size() <<" NPs" << endl;

}

vector<TString>* SystematicsManager::add_sys(Sample* sample){
    if (all_nps->size() < 1) return NULL;
    auto* nps_vec = new vector<TString>();
    for(unsigned int i=0; i < all_nps->size(); i++){
        TString& np = all_nps->at(i);
        bool has_norm = sample -> addNormSys(  np );
        bool has_shape = sample -> addShapeSys( np );
        if(has_shape || has_norm){
            nps_vec ->push_back( np );
        }
    }
    return nps_vec;
}

<|endoftext|>


<commit_before>/*
   This file is part of INDDGO.

   Copyright (C) 2012, Oak Ridge National Laboratory

   This product includes software produced by UT-Battelle, LLC under Contract No.
   DE-AC05-00OR22725 with the Department of Energy.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the New BSD 3-clause software license (LICENSE).

   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
   LICENSE for more details.

   For more information please contact the INDDGO developers at:
   inddgo-info@googlegroups.com

 */

#include "GraphReader.h"
#include "GraphProperties.h"
#include <ctime>

using namespace std;

void usage(const char *s){
    fprintf(stderr, "Usage: %s filename\n", s);
}

int main(int argc, char **argv){
    //usage check
    if((argc == 1) ||
       ((argc == 2) && (strcmp(argv[1],"-h") == 0)) ||
       ((argc == 2) && (strcmp(argv[1], "--help") == 0))){
        usage(argv[0]);
        exit(-1);
    }

    Graph::Graph *g;

    clock_t begin, end;

    Graph::GraphProperties prop;
    Graph::GraphReader ngr;

    //create the graph object
    g = new Graph::Graph();

    //read the graph from the filename, assume it is an edgelist
    ngr.read_graph(g, argv[1], "Edge", false);
    //ngr.read_graph(g, argv[1], "ADJLIST", false);
    printf("Read %d vertices and %d edges\n", g->get_num_nodes(), g->get_num_edges());

    printf("Simplifying graph\n");
    begin = clock();
    prop.make_simple(g);    //remove self loops and duplicate edges
    end = clock();
    printf("Time: %f\n", double(end - begin) / CLOCKS_PER_SEC);

    //compute all pairs shortest paths
    begin = clock();
    vector<int> ecc;
    prop.eccentricity(g,ecc);
    end = clock();
    printf("Alg Time (eccentricity): %f\n", double(end - begin) / CLOCKS_PER_SEC);

    begin = clock();
    vector<float> ecc_dist;
    prop.eccentricity_dist(g,ecc, ecc_dist);
    end = clock();
    printf("Alg Time (freq dist eccentricity): %f\n", double(end - begin) / CLOCKS_PER_SEC);
} // main

<commit_msg>fixing comments in file<commit_after>/*
   This file is part of INDDGO.

   Copyright (C) 2012, Oak Ridge National Laboratory

   This product includes software produced by UT-Battelle, LLC under Contract No.
   DE-AC05-00OR22725 with the Department of Energy.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the New BSD 3-clause software license (LICENSE).

   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
   LICENSE for more details.

   For more information please contact the INDDGO developers at:
   inddgo-info@googlegroups.com

 */

#include "GraphReader.h"
#include "GraphProperties.h"
#include <ctime>

using namespace std;

void usage(const char *s){
    fprintf(stderr, "Usage: %s filename\n", s);
}

int main(int argc, char **argv){
    //usage check
    if((argc == 1) ||
       ((argc == 2) && (strcmp(argv[1],"-h") == 0)) ||
       ((argc == 2) && (strcmp(argv[1], "--help") == 0))){
        usage(argv[0]);
        exit(-1);
    }

    Graph::Graph *g;

    clock_t begin, end;

    Graph::GraphProperties prop;
    Graph::GraphReader ngr;

    //create the graph object
    g = new Graph::Graph();

    //read the graph from the filename, assume it is an edgelist
    ngr.read_graph(g, argv[1], "Edge", false);
    //ngr.read_graph(g, argv[1], "ADJLIST", false);
    printf("Read %d vertices and %d edges\n", g->get_num_nodes(), g->get_num_edges());

    printf("Simplifying graph\n");
    begin = clock();
    prop.make_simple(g);    //remove self loops and duplicate edges
    end = clock();
    printf("Time: %f\n", double(end - begin) / CLOCKS_PER_SEC);

    //compute eccentricity
    begin = clock();
    vector<int> ecc;
    prop.eccentricity(g,ecc);
    end = clock();
    printf("Alg Time (eccentricity): %f\n", double(end - begin) / CLOCKS_PER_SEC);

    //compute eccentricity distribution
    begin = clock();
    vector<float> ecc_dist;
    prop.eccentricity_dist(g,ecc, ecc_dist);
    end = clock();
    printf("Alg Time (freq dist eccentricity): %f\n", double(end - begin) / CLOCKS_PER_SEC);
} // main

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: gtkinst.cxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: kz $ $Date: 2005-11-02 13:32:37 $
 *
 *  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
 *
 ************************************************************************/

#include <osl/module.h>
#include <plugins/gtk/gtkdata.hxx>
#include <plugins/gtk/gtkinst.hxx>
#include <salframe.h>
#include <salobj.h>
#include <plugins/gtk/gtkframe.hxx>
#include <plugins/gtk/gtkobject.hxx>

#include <rtl/strbuf.hxx>

#if OSL_DEBUG_LEVEL > 1
#include <stdio.h>
#endif

GtkHookedYieldMutex::GtkHookedYieldMutex()
{
}

/*
 * These methods always occur in pairs
 * A ThreadsEnter is followed by a ThreadsLeave
 * We need to queue up the recursive lock count
 * for each pair, so we can accurately restore
 * it later.
 */
void GtkHookedYieldMutex::ThreadsEnter()
{
    acquire();
    if( !aYieldStack.empty() )
    { /* Previously called ThreadsLeave() */
        ULONG nCount = aYieldStack.front();
        aYieldStack.pop_front();
        while( nCount-- > 1 )
            acquire();
    }
}

void GtkHookedYieldMutex::ThreadsLeave()
{
    aYieldStack.push_front( mnCount );

#if OSL_DEBUG_LEVEL > 1
    if( mnThreadId &&
        mnThreadId != NAMESPACE_VOS(OThread)::getCurrentIdentifier())
        fprintf( stderr, "\n\n--- A different thread owns the mutex ...---\n\n\n");
#endif

    while( mnCount > 1 )
        release();
    release();
}

void GtkHookedYieldMutex::acquire()
{
    SalYieldMutex::acquire();
}

void GtkHookedYieldMutex::release()
{
    SalYieldMutex::release();
}

extern "C"
{
    #define GET_YIELD_MUTEX() static_cast<GtkHookedYieldMutex*>(GetSalData()->pInstance_->GetYieldMutex())
    static void GdkThreadsEnter( void )
    {
        GtkHookedYieldMutex *pYieldMutex = GET_YIELD_MUTEX();
        pYieldMutex->ThreadsEnter();
    }
    static void GdkThreadsLeave( void )
    {
        GtkHookedYieldMutex *pYieldMutex = GET_YIELD_MUTEX();
        pYieldMutex->ThreadsLeave();
    }
    static bool hookLocks( oslModule pModule )
    {
        typedef void (*GdkLockFn) (GCallback enter_fn, GCallback leave_fn);
        rtl::OUString aSymbolName( RTL_CONSTASCII_USTRINGPARAM( "gdk_threads_set_lock_functions") );

        GdkLockFn gdk_threads_set_lock_functions =
                (GdkLockFn) osl_getSymbol( pModule, aSymbolName.pData );
        if ( !gdk_threads_set_lock_functions )
        {
#if OSL_DEBUG_LEVEL > 1
            fprintf( stderr, "Failed to hook gdk threads locks\n" );
#endif
            return false;
        }

        gdk_threads_set_lock_functions (GdkThreadsEnter, GdkThreadsLeave);
#if OSL_DEBUG_LEVEL > 1
        fprintf( stderr, "Hooked gdk threads locks\n" );
#endif
        return true;
    }

    VCL_DLLPUBLIC SalInstance* create_SalInstance( oslModule pModule )
    {
        const gchar* pVersion = gtk_check_version( 2, 2, 0 );
        if( pVersion )
        {
#if OSL_DEBUG_LEVEL > 1
            fprintf( stderr, "gtk version conflict: %s\n", pVersion );
#endif
            return NULL;
        }
        /*  #i47797# as long as we do not have a working atk bridge
         *  prevent atk from interfering with the java accessibility bridge
         */
        #if ! defined HAVE_ATK_ACCESSIBILITY_BRIDGE
        const char* pGtkModules = getenv( "GTK_MODULES" );
        if( pGtkModules )
        {
            rtl::OString aModules( pGtkModules );
            rtl::OStringBuffer aModulesOut( aModules.getLength() + 11 );
            aModulesOut.append( "GTK_MODULES=" );
            sal_Int32 nIndex = 0;
            while( nIndex >= 0 )
            {
                rtl::OString aToken = aModules.getToken( 0, ':', nIndex );
                if( aToken.equals( "gail" ) ||
                    aToken.equals( "atk-bridge" ) )
                    continue;
                aModulesOut.append( ':' );
                aModulesOut.append( aToken );
            }
            putenv( strdup( aModulesOut.getStr() ) );
        }
        #endif

        GtkYieldMutex *pYieldMutex;

        // init gdk thread protection
        if ( !g_thread_supported() )
            g_thread_init( NULL );

        if ( hookLocks( pModule ) )
            pYieldMutex = new GtkHookedYieldMutex();
        else
            pYieldMutex = new GtkYieldMutex();

        gdk_threads_init();

        GtkInstance* pInstance = new GtkInstance( pYieldMutex );
#if OSL_DEBUG_LEVEL > 1
        fprintf( stderr, "creating GtkSalInstance 0x%p\n", pInstance );
#endif

        // initialize SalData
        SalData *pSalData = new GtkData();
        SetSalData( pSalData );
        pSalData->pInstance_ = pInstance;
        pSalData->Init();
        pSalData->initNWF();

        return pInstance;
    }
}

GtkInstance::~GtkInstance()
{
}

SalFrame* GtkInstance::CreateFrame( SalFrame* pParent, ULONG nStyle )
{
    return new GtkSalFrame( pParent, nStyle );
}

SalFrame* GtkInstance::CreateChildFrame( SystemParentData* pParentData, ULONG nStyle )
{
    SalFrame* pFrame = new GtkSalFrame( pParentData );

    return pFrame;
}

SalObject* GtkInstance::CreateObject( SalFrame* pParent, SystemWindowData* pWindowData )
{
    // there is no method to set a visual for a GtkWidget
    // so we need the X11SalObject in that case
    if( pWindowData )
        return X11SalObject::CreateObject( pParent, pWindowData );

    return new GtkSalObject( static_cast<GtkSalFrame*>(pParent) );
}

GtkYieldMutex::GtkYieldMutex()
{
}

void GtkYieldMutex::acquire()
{
    vos::OThread::TThreadIdentifier aCurrentThread = vos::OThread::getCurrentIdentifier();
    // protect member manipulation
    OMutex::acquire();
    if( mnCount > 0 && mnThreadId == aCurrentThread )
    {
        mnCount++;
        OMutex::release();
        return;
    }
    OMutex::release();

    // obtain gdk mutex
    gdk_threads_enter();

    // obtained gdk mutex, now lock count is one by definition
    OMutex::acquire();
    mnCount = 1;
    mnThreadId = aCurrentThread;
    OMutex::release();
}

void GtkYieldMutex::release()
{
    vos::OThread::TThreadIdentifier aCurrentThread = vos::OThread::getCurrentIdentifier();
    // protect member manipulation
    OMutex::acquire();
    // strange things happen, do nothing if we don't own the mutex
    if( mnThreadId == aCurrentThread )
    {
        mnCount--;
        if( mnCount == 0 )
        {
            gdk_threads_leave();
            mnThreadId = 0;
        }
    }
    OMutex::release();
}

sal_Bool GtkYieldMutex::tryToAcquire()
{
    vos::OThread::TThreadIdentifier aCurrentThread = vos::OThread::getCurrentIdentifier();
    // protect member manipulation
    OMutex::acquire();
    if( mnCount > 0 )
    {
        if( mnThreadId == aCurrentThread )
        {
            mnCount++;
            OMutex::release();
            return sal_True;
        }
        else
        {
            OMutex::release();
            return sal_False;
        }
    }
    OMutex::release();

    // HACK: gdk_threads_mutex is private, we shouldn't use it.
    // how to we do a try_lock without having a gdk_threads_try_enter ?
    if( ! g_mutex_trylock( gdk_threads_mutex ) )
        return sal_False;

    // obtained gdk mutex, now lock count is one by definition
    OMutex::acquire();
    mnCount = 1;
    mnThreadId = aCurrentThread;
    OMutex::release();

    return sal_True;
}

int GtkYieldMutex::Grab()
{
    // this MUST only be called by gdk/gtk callbacks:
    // they are entered with gdk mutex locked; the mutex
    // was unlocked by GtkYieldMutex befor yielding which
    // is now locked again by gtk implicitly

    // obtained gdk mutex, now lock count is one by definition
    OMutex::acquire();
    int nRet = mnCount;
    if( mnCount == 0 ) // recursive else
        mnThreadId = vos::OThread::getCurrentIdentifier();
#if OSL_DEBUG_LEVEL > 1
    else if( mnThreadId != vos::OThread::getCurrentIdentifier() )
    {
        fprintf( stderr, "Yield mutex grabbed in different thread !\n" );
        abort();
    }
#endif
    mnCount = 1;
    OMutex::release();
    return nRet;
}

void GtkYieldMutex::Ungrab( int nGrabs )
{
    // this MUST only be called when leaving the callback
    // that locked the mutex with Grab()
    OMutex::acquire();
    mnCount = nGrabs;
    if( mnCount == 0 )
        mnThreadId = 0;
    OMutex::release();
}
<commit_msg>INTEGRATION: CWS atkbridge (1.9.6); FILE MERGED 2006/02/16 11:08:15 obr 1.9.6.9: #i47890# removed build conditionals (EXPERIMENTAL_ATKBRIDGE) 2006/01/05 14:06:35 obr 1.9.6.8: #i47890# override toolkit name and version and reworked bridge initialization 2005/12/01 10:46:29 obr 1.9.6.7: RESYNC: (1.10-1.11); FILE MERGED 2005/11/16 09:09:21 obr 1.9.6.6: gail rev. 1.8.6 fixes the things we needed gsignalhook for 2005/11/04 21:00:35 mmeeks 1.9.6.5: i#47890# re-instate some compat stuff. 2005/11/04 14:56:28 mmeeks 1.9.6.4: i#47890#<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: gtkinst.cxx,v $
 *
 *  $Revision: 1.12 $
 *
 *  last change: $Author: rt $ $Date: 2006-05-05 10:59:46 $
 *
 *  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
 *
 ************************************************************************/

#include <osl/module.h>
#include <plugins/gtk/gtkdata.hxx>
#include <plugins/gtk/gtkinst.hxx>
#include <salframe.h>
#include <salobj.h>
#include <plugins/gtk/gtkframe.hxx>
#include <plugins/gtk/gtkobject.hxx>
#include <plugins/gtk/atkbridge.hxx>

#include <rtl/strbuf.hxx>

#if OSL_DEBUG_LEVEL > 1
#include <stdio.h>
#endif

#include <dlfcn.h>

GtkHookedYieldMutex::GtkHookedYieldMutex()
{
}

/*
 * These methods always occur in pairs
 * A ThreadsEnter is followed by a ThreadsLeave
 * We need to queue up the recursive lock count
 * for each pair, so we can accurately restore
 * it later.
 */
void GtkHookedYieldMutex::ThreadsEnter()
{
    acquire();
    if( !aYieldStack.empty() )
    { /* Previously called ThreadsLeave() */
        ULONG nCount = aYieldStack.front();
        aYieldStack.pop_front();
        while( nCount-- > 1 )
            acquire();
    }
}

void GtkHookedYieldMutex::ThreadsLeave()
{
    aYieldStack.push_front( mnCount );

#if OSL_DEBUG_LEVEL > 1
    if( mnThreadId &&
        mnThreadId != NAMESPACE_VOS(OThread)::getCurrentIdentifier())
        fprintf( stderr, "\n\n--- A different thread owns the mutex ...---\n\n\n");
#endif

    while( mnCount > 1 )
        release();
    release();
}

void GtkHookedYieldMutex::acquire()
{
    SalYieldMutex::acquire();
}

void GtkHookedYieldMutex::release()
{
    SalYieldMutex::release();
}

extern "C"
{
    #define GET_YIELD_MUTEX() static_cast<GtkHookedYieldMutex*>(GetSalData()->pInstance_->GetYieldMutex())
    static void GdkThreadsEnter( void )
    {
        GtkHookedYieldMutex *pYieldMutex = GET_YIELD_MUTEX();
        pYieldMutex->ThreadsEnter();
    }
    static void GdkThreadsLeave( void )
    {
        GtkHookedYieldMutex *pYieldMutex = GET_YIELD_MUTEX();
        pYieldMutex->ThreadsLeave();
    }
    static bool hookLocks( oslModule pModule )
    {
        typedef void (*GdkLockFn) (GCallback enter_fn, GCallback leave_fn);
        rtl::OUString aSymbolName( RTL_CONSTASCII_USTRINGPARAM( "gdk_threads_set_lock_functions") );

        GdkLockFn gdk_threads_set_lock_functions =
                (GdkLockFn) osl_getSymbol( pModule, aSymbolName.pData );
        if ( !gdk_threads_set_lock_functions )
        {
#if OSL_DEBUG_LEVEL > 1
            fprintf( stderr, "Failed to hook gdk threads locks\n" );
#endif
            return false;
        }

        gdk_threads_set_lock_functions (GdkThreadsEnter, GdkThreadsLeave);
#if OSL_DEBUG_LEVEL > 1
        fprintf( stderr, "Hooked gdk threads locks\n" );
#endif
        return true;
    }

    VCL_DLLPUBLIC SalInstance* create_SalInstance( oslModule pModule )
    {
        const gchar* pVersion = gtk_check_version( 2, 2, 0 );
        if( pVersion )
        {
#if OSL_DEBUG_LEVEL > 1
            fprintf( stderr, "gtk version conflict: %s\n", pVersion );
#endif
            return NULL;
        }

        GtkYieldMutex *pYieldMutex;

        // init gdk thread protection
        if ( !g_thread_supported() )
            g_thread_init( NULL );

        if ( hookLocks( pModule ) )
            pYieldMutex = new GtkHookedYieldMutex();
        else
            pYieldMutex = new GtkYieldMutex();

        gdk_threads_init();

        GtkInstance* pInstance = new GtkInstance( pYieldMutex );
#if OSL_DEBUG_LEVEL > 1
        fprintf( stderr, "creating GtkSalInstance 0x%p\n", pInstance );
#endif

        // initialize SalData
        SalData *pSalData = new GtkData();
        SetSalData( pSalData );
        pSalData->pInstance_ = pInstance;
        pSalData->Init();
        pSalData->initNWF();

        const char* pGtkModules = getenv( "GTK_MODULES" );
        if( pGtkModules )
        {
            rtl::OString aModules( pGtkModules );
            sal_Int32 nIndex = 0;
            while( nIndex >= 0 )
            {
                rtl::OString aToken = aModules.getToken( 0, ':', nIndex );
                if( aToken.equals( "gail" ) || aToken.equals( "atk-bridge" ) )
                {
                    InitAtkBridge();
                    break;
                }
            }
        }

        return pInstance;
    }
}

GtkInstance::~GtkInstance()
{
}

SalFrame* GtkInstance::CreateFrame( SalFrame* pParent, ULONG nStyle )
{
    return new GtkSalFrame( pParent, nStyle );
}

SalFrame* GtkInstance::CreateChildFrame( SystemParentData* pParentData, ULONG nStyle )
{
    SalFrame* pFrame = new GtkSalFrame( pParentData );

    return pFrame;
}

SalObject* GtkInstance::CreateObject( SalFrame* pParent, SystemWindowData* pWindowData )
{
    // there is no method to set a visual for a GtkWidget
    // so we need the X11SalObject in that case
    if( pWindowData )
        return X11SalObject::CreateObject( pParent, pWindowData );

    return new GtkSalObject( static_cast<GtkSalFrame*>(pParent) );
}

GtkYieldMutex::GtkYieldMutex()
{
}

void GtkYieldMutex::acquire()
{
    vos::OThread::TThreadIdentifier aCurrentThread = vos::OThread::getCurrentIdentifier();
    // protect member manipulation
    OMutex::acquire();
    if( mnCount > 0 && mnThreadId == aCurrentThread )
    {
        mnCount++;
        OMutex::release();
        return;
    }
    OMutex::release();

    // obtain gdk mutex
    gdk_threads_enter();

    // obtained gdk mutex, now lock count is one by definition
    OMutex::acquire();
    mnCount = 1;
    mnThreadId = aCurrentThread;
    OMutex::release();
}

void GtkYieldMutex::release()
{
    vos::OThread::TThreadIdentifier aCurrentThread = vos::OThread::getCurrentIdentifier();
    // protect member manipulation
    OMutex::acquire();
    // strange things happen, do nothing if we don't own the mutex
    if( mnThreadId == aCurrentThread )
    {
        mnCount--;
        if( mnCount == 0 )
        {
            gdk_threads_leave();
            mnThreadId = 0;
        }
    }
    OMutex::release();
}

sal_Bool GtkYieldMutex::tryToAcquire()
{
    vos::OThread::TThreadIdentifier aCurrentThread = vos::OThread::getCurrentIdentifier();
    // protect member manipulation
    OMutex::acquire();
    if( mnCount > 0 )
    {
        if( mnThreadId == aCurrentThread )
        {
            mnCount++;
            OMutex::release();
            return sal_True;
        }
        else
        {
            OMutex::release();
            return sal_False;
        }
    }
    OMutex::release();

    // HACK: gdk_threads_mutex is private, we shouldn't use it.
    // how to we do a try_lock without having a gdk_threads_try_enter ?
    if( ! g_mutex_trylock( gdk_threads_mutex ) )
        return sal_False;

    // obtained gdk mutex, now lock count is one by definition
    OMutex::acquire();
    mnCount = 1;
    mnThreadId = aCurrentThread;
    OMutex::release();

    return sal_True;
}

int GtkYieldMutex::Grab()
{
    // this MUST only be called by gdk/gtk callbacks:
    // they are entered with gdk mutex locked; the mutex
    // was unlocked by GtkYieldMutex befor yielding which
    // is now locked again by gtk implicitly

    // obtained gdk mutex, now lock count is one by definition
    OMutex::acquire();
    int nRet = mnCount;
    if( mnCount == 0 ) // recursive else
        mnThreadId = vos::OThread::getCurrentIdentifier();
#if OSL_DEBUG_LEVEL > 1
    else if( mnThreadId != vos::OThread::getCurrentIdentifier() )
    {
        fprintf( stderr, "Yield mutex grabbed in different thread !\n" );
        abort();
    }
#endif
    mnCount = 1;
    OMutex::release();
    return nRet;
}

void GtkYieldMutex::Ungrab( int nGrabs )
{
    // this MUST only be called when leaving the callback
    // that locked the mutex with Grab()
    OMutex::acquire();
    mnCount = nGrabs;
    if( mnCount == 0 )
        mnThreadId = 0;
    OMutex::release();
}
<|endoftext|>


<commit_before>/*
 * Copyright 2011 Mads R. B. Kristensen <madsbk@gmail.com>
 *
 * This file is part of cphVB.
 *
 * cphVB is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * cphVB 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 cphVB. If not, see <http://www.gnu.org/licenses/>.
 */

#include <cassert>
#include <cstring>
#include <iostream>
#include <cphvb.h>

#include "cphvb_vem_node.h"
#include "ArrayManager.hpp"

//Function pointers to the VE.
static cphvb_init ve_init;
static cphvb_execute ve_execute;
static cphvb_shutdown ve_shutdown;
static cphvb_reg_func ve_reg_func;

//The VE components
static cphvb_com **coms;

//Our self
static cphvb_com *myself;

//Number of user-defined functions registered.
static cphvb_intp userfunc_count = 0;

#define PLAININST (1)
#define REDUCEINST (2)

ArrayManager* arrayManager;

/* Initialize the VEM
 *
 * @return Error codes (CPHVB_SUCCESS)
 */
cphvb_error cphvb_vem_node_init(cphvb_com *self)
{
    cphvb_intp children_count;
    cphvb_error err;
    myself = self;

    cphvb_com_children(self, &children_count, &coms);
    ve_init = coms[0]->init;
    ve_execute = coms[0]->execute;
    ve_shutdown = coms[0]->shutdown;
    ve_reg_func = coms[0]->reg_func;

    //Let us initiate the simple VE and register what it supports.
    err = ve_init(coms[0]);
    if(err)
        return err;

    try
    {
        arrayManager = new ArrayManager();
    }
    catch (std::exception& e)
    {
        std::cerr << e.what() << std::endl;
        return CPHVB_ERROR;
    }

    return CPHVB_SUCCESS;
}

/* Shutdown the VEM, which include a instruction flush
 *
 * @return Error codes (CPHVB_SUCCESS)
 */
cphvb_error cphvb_vem_node_shutdown(void)
{
    cphvb_error err;
    err = ve_shutdown();
    cphvb_com_free(coms[0]);//Only got one child.
    free(coms);
    delete arrayManager;
    return err;
}

/* Create an array, which are handled by the VEM.
 *
 * @base Pointer to the base array. If NULL this is a base array
 * @type The type of data in the array
 * @ndim Number of dimensions
 * @start Index of the start element (always 0 for base-array)
 * @shape[CPHVB_MAXDIM] Number of elements in each dimention
 * @stride[CPHVB_MAXDIM] The stride for each dimention
 * @new_array The handler for the newly created array
 * @return Error code (CPHVB_SUCCESS, CPHVB_OUT_OF_MEMORY)
 */
cphvb_error cphvb_vem_node_create_array(cphvb_array*   base,
                                        cphvb_type     type,
                                        cphvb_intp     ndim,
                                        cphvb_index    start,
                                        cphvb_index    shape[CPHVB_MAXDIM],
                                        cphvb_index    stride[CPHVB_MAXDIM],
                                        cphvb_array**  new_array)
{

    try
    {
        *new_array = arrayManager->create(base, type, ndim, start, shape, stride);
    }
    catch(std::exception& e)
    {
        return CPHVB_OUT_OF_MEMORY;
    }
    #ifdef CPHVB_TRACE
        cphvb_com_trace_array(myself, *new_array);
    #endif

    return CPHVB_SUCCESS;
}

/* Registre a new user-defined function.
 *
 * @lib Name of the shared library e.g. libmyfunc.so
 *      When NULL the default library is used.
 * @fun Name of the function e.g. myfunc
 * @id Identifier for the new function. The bridge should set the
 *     initial value to Zero. (in/out-put)
 * @return Error codes (CPHVB_SUCCESS)
 */
cphvb_error cphvb_vem_node_reg_func(char *lib, char *fun, cphvb_intp *id)
{
	cphvb_error e;
	cphvb_intp tmpid;

    if(*id == 0)//Only if parent didn't set the ID.
        tmpid = userfunc_count + 1;

    e = ve_reg_func(lib, fun, &tmpid);

    //If the call succeeded, register the id as taken and return it
    if (e == CPHVB_SUCCESS)
    {
    	userfunc_count = tmpid;
    	*id = tmpid;
    }

    return e;
}

/* Execute a list of instructions (blocking, for the time being).
 * It is required that the VEM supports all instructions in the list.
 *
 * @instruction A list of instructions to execute
 * @return Error codes (CPHVB_SUCCESS)
 */
cphvb_error cphvb_vem_node_execute(cphvb_intp count,
                                   cphvb_instruction inst_list[])
{
    cphvb_intp i;
    cphvb_intp valid_instruction_count = count;
    for(i=0; i<count; ++i)
    {
        cphvb_instruction* inst = &inst_list[i];
        #ifdef CPHVB_TRACE
            cphvb_com_trace_inst(myself, inst);
        #endif
        switch(inst->opcode)
        {
        case CPHVB_DESTROY:
        {
            cphvb_array* base = cphvb_base_array(inst->operand[0]);
            if (inst->operand[0]->base != NULL)
            {   // It's a view and we can mark it for deletion
                arrayManager->erasePending(inst->operand[0]);
            }
            --base->ref_count; //decrease refcount
            if(base->ref_count <= 0)
            {
                // Mark the Base for deletion
                arrayManager->erasePending(base);
                if (base->owner != CPHVB_PARENT)
                {
                    //Tell the VE to discard the base array.
                    inst->operand[0] = base;
                    inst->opcode = CPHVB_DISCARD;
                }
                else
                {
                    inst->opcode = CPHVB_NONE;
                    --valid_instruction_count;
                }
            }
            else
            {   //Tell the VE to do nothing
                inst->opcode = CPHVB_NONE;
                --valid_instruction_count;
            }
            break;
        }
        case CPHVB_SYNC:
        {
            cphvb_array* base = cphvb_base_array(inst->operand[0]);
            switch (base->owner)
            {
            case CPHVB_PARENT:
            case CPHVB_SELF:
                //The owner is not down stream so we do nothing
                inst->opcode = CPHVB_NONE;
                --valid_instruction_count;
                break;
            default:
                //The owner is downstream so send the sync down
                //and take ownership
                inst->operand[0] = base;
                arrayManager->changeOwnerPending(base,CPHVB_SELF);
            }
            break;
        }
        case CPHVB_USERFUNC:
        {
            cphvb_userfunc *uf = inst->userfunc;
            //The children should own the output arrays.
            for(int j = 0; j < uf->nout; ++j)
            {
                cphvb_array* base = cphvb_base_array(uf->operand[j]);
                base->owner = CPHVB_CHILD;
            }
            //We should own the input arrays.
            for(int j = uf->nout; j < uf->nout + uf->nin; ++j)
            {
                cphvb_array* base = cphvb_base_array(uf->operand[j]);
                if(base->owner == CPHVB_PARENT)
                {
                    base->owner = CPHVB_SELF;
                }
            }
            break;
        }
        default:
        {
            cphvb_array* base = cphvb_base_array(inst->operand[0]);
            // "Regular" operation: set ownership and send down stream
            base->owner = CPHVB_CHILD;//The child owns the output ary.
            for (int j = 1; j < cphvb_operands(inst->opcode); ++j)
            {
                if(!cphvb_is_constant(inst->operand[j]) &&
                   cphvb_base_array(inst->operand[j])->owner == CPHVB_PARENT)
                {
                    cphvb_base_array(inst->operand[j])->owner = CPHVB_SELF;
                }
            }
        }
        }
    }
    if (valid_instruction_count > 0)
    {
        cphvb_error e = ve_execute(count, inst_list);
        arrayManager->flush();
        return e;
    }
    else
    {
        // No valid instructions in batch
        return CPHVB_SUCCESS;
    }
}
<commit_msg>Improved robustness of handling re-registration of functions<commit_after>/*
 * Copyright 2011 Mads R. B. Kristensen <madsbk@gmail.com>
 *
 * This file is part of cphVB.
 *
 * cphVB is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * cphVB 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 cphVB. If not, see <http://www.gnu.org/licenses/>.
 */

#include <cassert>
#include <cstring>
#include <iostream>
#include <cphvb.h>

#include "cphvb_vem_node.h"
#include "ArrayManager.hpp"

//Function pointers to the VE.
static cphvb_init ve_init;
static cphvb_execute ve_execute;
static cphvb_shutdown ve_shutdown;
static cphvb_reg_func ve_reg_func;

//The VE components
static cphvb_com **coms;

//Our self
static cphvb_com *myself;

//Number of user-defined functions registered.
static cphvb_intp userfunc_count = 0;

#define PLAININST (1)
#define REDUCEINST (2)

ArrayManager* arrayManager;

/* Initialize the VEM
 *
 * @return Error codes (CPHVB_SUCCESS)
 */
cphvb_error cphvb_vem_node_init(cphvb_com *self)
{
    cphvb_intp children_count;
    cphvb_error err;
    myself = self;

    cphvb_com_children(self, &children_count, &coms);
    ve_init = coms[0]->init;
    ve_execute = coms[0]->execute;
    ve_shutdown = coms[0]->shutdown;
    ve_reg_func = coms[0]->reg_func;

    //Let us initiate the simple VE and register what it supports.
    err = ve_init(coms[0]);
    if(err)
        return err;

    try
    {
        arrayManager = new ArrayManager();
    }
    catch (std::exception& e)
    {
        std::cerr << e.what() << std::endl;
        return CPHVB_ERROR;
    }

    return CPHVB_SUCCESS;
}

/* Shutdown the VEM, which include a instruction flush
 *
 * @return Error codes (CPHVB_SUCCESS)
 */
cphvb_error cphvb_vem_node_shutdown(void)
{
    cphvb_error err;
    err = ve_shutdown();
    cphvb_com_free(coms[0]);//Only got one child.
    free(coms);
    delete arrayManager;
    return err;
}

/* Create an array, which are handled by the VEM.
 *
 * @base Pointer to the base array. If NULL this is a base array
 * @type The type of data in the array
 * @ndim Number of dimensions
 * @start Index of the start element (always 0 for base-array)
 * @shape[CPHVB_MAXDIM] Number of elements in each dimention
 * @stride[CPHVB_MAXDIM] The stride for each dimention
 * @new_array The handler for the newly created array
 * @return Error code (CPHVB_SUCCESS, CPHVB_OUT_OF_MEMORY)
 */
cphvb_error cphvb_vem_node_create_array(cphvb_array*   base,
                                        cphvb_type     type,
                                        cphvb_intp     ndim,
                                        cphvb_index    start,
                                        cphvb_index    shape[CPHVB_MAXDIM],
                                        cphvb_index    stride[CPHVB_MAXDIM],
                                        cphvb_array**  new_array)
{

    try
    {
        *new_array = arrayManager->create(base, type, ndim, start, shape, stride);
    }
    catch(std::exception& e)
    {
        return CPHVB_OUT_OF_MEMORY;
    }
    #ifdef CPHVB_TRACE
        cphvb_com_trace_array(myself, *new_array);
    #endif

    return CPHVB_SUCCESS;
}

/* Registre a new user-defined function.
 *
 * @lib Name of the shared library e.g. libmyfunc.so
 *      When NULL the default library is used.
 * @fun Name of the function e.g. myfunc
 * @id Identifier for the new function. The bridge should set the
 *     initial value to Zero. (in/out-put)
 * @return Error codes (CPHVB_SUCCESS)
 */
cphvb_error cphvb_vem_node_reg_func(char *lib, char *fun, cphvb_intp *id)
{
	cphvb_error e;
	cphvb_intp tmpid;

    if(*id == 0)//Only if parent didn't set the ID.
        tmpid = userfunc_count + 1;

    e = ve_reg_func(lib, fun, &tmpid);

    //If the call succeeded, register the id as taken and return it
    if (e == CPHVB_SUCCESS)
    {
	    if (tmpid > userfunc_count)
	    	userfunc_count = tmpid;
    	*id = tmpid;
    }

    return e;
}

/* Execute a list of instructions (blocking, for the time being).
 * It is required that the VEM supports all instructions in the list.
 *
 * @instruction A list of instructions to execute
 * @return Error codes (CPHVB_SUCCESS)
 */
cphvb_error cphvb_vem_node_execute(cphvb_intp count,
                                   cphvb_instruction inst_list[])
{
    cphvb_intp i;
    cphvb_intp valid_instruction_count = count;
    for(i=0; i<count; ++i)
    {
        cphvb_instruction* inst = &inst_list[i];
        #ifdef CPHVB_TRACE
            cphvb_com_trace_inst(myself, inst);
        #endif
        switch(inst->opcode)
        {
        case CPHVB_DESTROY:
        {
            cphvb_array* base = cphvb_base_array(inst->operand[0]);
            if (inst->operand[0]->base != NULL)
            {   // It's a view and we can mark it for deletion
                arrayManager->erasePending(inst->operand[0]);
            }
            --base->ref_count; //decrease refcount
            if(base->ref_count <= 0)
            {
                // Mark the Base for deletion
                arrayManager->erasePending(base);
                if (base->owner != CPHVB_PARENT)
                {
                    //Tell the VE to discard the base array.
                    inst->operand[0] = base;
                    inst->opcode = CPHVB_DISCARD;
                }
                else
                {
                    inst->opcode = CPHVB_NONE;
                    --valid_instruction_count;
                }
            }
            else
            {   //Tell the VE to do nothing
                inst->opcode = CPHVB_NONE;
                --valid_instruction_count;
            }
            break;
        }
        case CPHVB_SYNC:
        {
            cphvb_array* base = cphvb_base_array(inst->operand[0]);
            switch (base->owner)
            {
            case CPHVB_PARENT:
            case CPHVB_SELF:
                //The owner is not down stream so we do nothing
                inst->opcode = CPHVB_NONE;
                --valid_instruction_count;
                break;
            default:
                //The owner is downstream so send the sync down
                //and take ownership
                inst->operand[0] = base;
                arrayManager->changeOwnerPending(base,CPHVB_SELF);
            }
            break;
        }
        case CPHVB_USERFUNC:
        {
            cphvb_userfunc *uf = inst->userfunc;
            //The children should own the output arrays.
            for(int j = 0; j < uf->nout; ++j)
            {
                cphvb_array* base = cphvb_base_array(uf->operand[j]);
                base->owner = CPHVB_CHILD;
            }
            //We should own the input arrays.
            for(int j = uf->nout; j < uf->nout + uf->nin; ++j)
            {
                cphvb_array* base = cphvb_base_array(uf->operand[j]);
                if(base->owner == CPHVB_PARENT)
                {
                    base->owner = CPHVB_SELF;
                }
            }
            break;
        }
        default:
        {
            cphvb_array* base = cphvb_base_array(inst->operand[0]);
            // "Regular" operation: set ownership and send down stream
            base->owner = CPHVB_CHILD;//The child owns the output ary.
            for (int j = 1; j < cphvb_operands(inst->opcode); ++j)
            {
                if(!cphvb_is_constant(inst->operand[j]) &&
                   cphvb_base_array(inst->operand[j])->owner == CPHVB_PARENT)
                {
                    cphvb_base_array(inst->operand[j])->owner = CPHVB_SELF;
                }
            }
        }
        }
    }
    if (valid_instruction_count > 0)
    {
        cphvb_error e = ve_execute(count, inst_list);
        arrayManager->flush();
        return e;
    }
    else
    {
        // No valid instructions in batch
        return CPHVB_SUCCESS;
    }
}
<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

#include "AliAODCluster.h"

/// \cond CLASSIMP
ClassImp(AliAODCluster) ;
/// \endcond

///
/// Default constructor.
///
//______________________________________________________________________________
AliAODCluster::AliAODCluster() :
  AliVCluster(),
  fEnergy(0),
  fChi2(-999.),
  fID(-999),
  fNLabel(0),
  fLabel(0x0),
  fFilterMap(0),
  fType(kUndef),
  fMCEnergyFraction(0.),
  fClusterMCEdepFraction(0x0)
{

  SetPosition(NULL);
  SetPID(NULL);
}

///
/// Constructor.
///
//______________________________________________________________________________
AliAODCluster::AliAODCluster(Int_t id,
			     UInt_t nLabel,
			     Int_t *label,
			     Double_t energy,
			     Double_t x[3],
			     Double_t pid[13],
			     Char_t ttype,
			     UInt_t selectInfo) :
  AliVCluster(),
  fEnergy(energy),
  fChi2(-999.),
  fID(id),
  fNLabel(0),
  fLabel(0x0),
  fFilterMap(selectInfo),
  fType(ttype),
  fMCEnergyFraction(0.),
  fClusterMCEdepFraction(0x0)
{
  for (Int_t i = 0; i <  3; i++) fPosition[i] = 0.;
  for (Int_t i = 0; i < 13; i++) fPID[i]      = 0;

  if(x)   {for (Int_t i = 0; i < 3  ; i++) SetPositionAt(x[i]  ,i);}
  if(pid) {for (Int_t i = 0; i < 13 ; i++) SetPIDAt     (pid[i],i);}
  SetLabel(label, nLabel);
}

///
/// Constructor.
///
//______________________________________________________________________________
AliAODCluster::AliAODCluster(Int_t id,
			     UInt_t nLabel,
			     Int_t *label,
			     Float_t energy,
			     Float_t x[3],
			     Float_t pid[13],
			     Char_t ttype,
			     UInt_t selectInfo) :
  AliVCluster(),
  fEnergy(energy),
  fChi2(-999.),
  fID(id),
  fNLabel(0),
  fLabel(0x0),
  fFilterMap(selectInfo),
  fType(ttype),
  fMCEnergyFraction(0.),
  fClusterMCEdepFraction(0x0)
{
  for (Int_t i = 0; i <  3; i++) fPosition[i] = 0.;
  for (Int_t i = 0; i < 13; i++) fPID[i]      = 0;

  if(x)   {for (Int_t i = 0; i < 3  ; i++) SetPositionAt(x[i]  ,i);}
  if(pid) {for (Int_t i = 0; i < 13 ; i++) SetPIDAt     (pid[i],i);}
  SetLabel(label, nLabel);
}

///
/// Destructor
///
//______________________________________________________________________________
AliAODCluster::~AliAODCluster()
{
  RemoveLabel();
}

///
/// Clear
///
//______________________________________________________________________________
void AliAODCluster::Clear(const Option_t*)
{
  RemoveLabel();
}

///
/// Copy constructor.
///
//______________________________________________________________________________
AliAODCluster::AliAODCluster(const AliAODCluster& clus) :
  AliVCluster(clus),
  fEnergy(clus.fEnergy),
  fChi2(clus.fChi2),
  fID(clus.fID),
  fNLabel(0),
  fLabel(0x0),
  fFilterMap(clus.fFilterMap),
  fType(clus.fType),
  fMCEnergyFraction(clus.fMCEnergyFraction),
  fClusterMCEdepFraction(0x0)
{
  for(Int_t i = 0; i < 3  ; i++) fPosition[i]  = clus.fPosition[i];
  for(Int_t i = 0; i < 13 ; i++) fPID[i]       = clus.fPID[i];

  SetLabel(clus.fLabel, clus.fNLabel);
  SetClusterMCEdepFraction(clus.fClusterMCEdepFraction);
}

///
/// Assignment operator.
///
//______________________________________________________________________________
AliAODCluster& AliAODCluster::operator=(const AliAODCluster& clus)
{
  if(this!=&clus) {

	for(Int_t i = 0; i < 3 ;  i++) fPosition[i] = clus.fPosition[i];
	for(Int_t i = 0; i < 13 ; i++) fPID[i]      = clus.fPID[i];

    fEnergy = clus.fEnergy;
    fChi2 = clus.fChi2;

    fID = clus.fID;

    SetLabel(clus.fLabel, clus.fNLabel);
    SetClusterMCEdepFraction(clus.fClusterMCEdepFraction);

    fFilterMap = clus.fFilterMap;

    fType = clus.fType;

    fMCEnergyFraction = clus.fMCEnergyFraction;
  }

  return *this;
}

///
/// Set cluster global position.
///
//______________________________________________________________________________
void AliAODCluster::SetPosition(Float_t *x)
{
  if (x) {
    fPosition[0] = x[0];
    fPosition[1] = x[1];
    fPosition[2] = x[2];
  } else {
    fPosition[0] = -999.;
    fPosition[1] = -999.;
    fPosition[2] = -999.;
  }
}

///
/// \return The most probable PID array element.
///
//______________________________________________________________________________
UShort_t AliAODCluster::GetMostProbablePID() const
{
  Int_t nPID = 13;
  UShort_t unknown = AliVCluster::kUnknown;

  UShort_t loc = unknown;
  Double_t max = 0.;
  Bool_t allTheSame = kTRUE;

  for (Int_t iPID = 0; iPID < nPID; iPID++) {
    if (fPID[iPID] >= max) {
      if (fPID[iPID] > max) {
	allTheSame = kFALSE;
	max = fPID[iPID];
	loc = (UShort_t)iPID;
      } else {
	allTheSame = kTRUE;
      }
    }
  }
  return allTheSame ? unknown : loc;
}

///
/// Set the array with MC particle labels and number of labels.
///
//______________________________________________________________________________
void AliAODCluster::SetLabel(Int_t *label, UInt_t size)
{
  if (label && size>0) {
    if (size != (UInt_t)fNLabel) {
      RemoveLabel();
      fNLabel = size;
      fLabel = new Int_t[fNLabel];
    }

    for (Int_t i = 0; i < fNLabel; i++) {
      fLabel[i] = label[i];
    }
  } else {
    RemoveLabel();
  }

  return;
}

///
/// Get the label i of the possible fNLabel in the array fLabel
///
//______________________________________________________________________________
Int_t AliAODCluster::GetLabelAt(UInt_t i) const
{
  if (fLabel && i < (UInt_t)fNLabel) {
    return fLabel[i];
  } else {
    return -999;
  }
}

///
/// Delete MC arrays, used in destructor and Clear() and SetLabel() methods
///
//______________________________________________________________________________
void AliAODCluster::RemoveLabel()
{
  delete[] fLabel;
  fLabel = 0x0;
  fNLabel = 0;

  if(fClusterMCEdepFraction)
    delete[] fClusterMCEdepFraction;
  fClusterMCEdepFraction  = 0 ;

  return;
}

///
/// Prints information about AliAODCluster.
///
//______________________________________________________________________________
void AliAODCluster::Print(Option_t* /* option */) const
{
  printf("Cluster type: %d\n", GetType());
  printf("     energy = %f\n", E());
  printf("       chi2 = %f\n", Chi2());
  const Double_t *pid = GetPID();
  printf("PID weights: photon %0.2f, pi0 %0.2f, electron %0.2f, conversion electron %0.2f\n, hadrons: pion %0.2f, kaon %0.2f, proton %0.2f , neutron %0.2f, kaon %0.2f \n",
	 pid[AliVCluster::kPhoton],   pid[AliVCluster::kPi0],
	 pid[AliVCluster::kElectron], pid[AliVCluster::kEleCon],
	 pid[AliVCluster::kPion],     pid[AliVCluster::kKaon],   pid[AliVCluster::kProton],
	 pid[AliVCluster::kNeutron],  pid[AliVCluster::kKaon0]);
}

///
/// \return Fraction of deposited energy by the one of the particles in array fLable
///
/// \param mcIndex: position of MC particle in array GetLabels()
///
/// The parameter is stored as %, return the corresponding float.
//______________________________________________________________________________
Float_t  AliAODCluster::GetClusterMCEdepFraction(Int_t mcIndex) const
{
  if ( mcIndex < 0 ||  mcIndex >= fNLabel ||  !fClusterMCEdepFraction ) return 0. ;

  return  fClusterMCEdepFraction[mcIndex]/100. ;
}

///
/// Set the array with the fraction of deposited energy in cluster by a given primary
/// particle. Each entry of the array corresponds to the same entry in GetLabels().
/// Set the fraction in % with respect the cluster energy, store a value between 0 and 100
///
/// Not sure this method is usable for AODs
///
/// \param array: energy deposition array
//______________________________________________________________________________
void  AliAODCluster::SetClusterMCEdepFractionFromEdepArray(Float_t *array)
{
  if ( fNLabel <= 0 || !array ) return ;

  fClusterMCEdepFraction = new  UShort_t[fNLabel];

  // Get total deposited energy (can be different from reconstructed energy)
  Float_t totalE = 0;
  for (Int_t i = 0; i < fNLabel; i++) totalE+=array[i];

  // Set the fraction of energy per MC contributor in %
  for (Int_t i = 0; i < fNLabel; i++)
    fClusterMCEdepFraction[i] = TMath::Nint(array[i]/totalE*100.);
}

///
/// Set the array with the fraction of deposited energy in cluster by a given primary
/// particle. Each entry of the array corresponds to the same entry in GetLabels().
///
/// The fraction must already be in % with respect the cluster energy, store a value between 0 and 100
///
/// Execute after setting of fLable and fNLabel
///
/// \param array: array of fraction of energy deposition / cluster energy
//______________________________________________________________________________
void  AliAODCluster::SetClusterMCEdepFraction(UShort_t *array)
{
  if ( fNLabel <= 0 || !array )
    return ;

  fClusterMCEdepFraction = new  UShort_t[fNLabel];

  for (Int_t i = 0; i < fNLabel; i++)
    fClusterMCEdepFraction[i] = array[i];
}

<commit_msg>protection against 0 division in old MC prods<commit_after>/**************************************************************************
 * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

#include "AliAODCluster.h"

/// \cond CLASSIMP
ClassImp(AliAODCluster) ;
/// \endcond

///
/// Default constructor.
///
//______________________________________________________________________________
AliAODCluster::AliAODCluster() :
  AliVCluster(),
  fEnergy(0),
  fChi2(-999.),
  fID(-999),
  fNLabel(0),
  fLabel(0x0),
  fFilterMap(0),
  fType(kUndef),
  fMCEnergyFraction(0.),
  fClusterMCEdepFraction(0x0)
{

  SetPosition(NULL);
  SetPID(NULL);
}

///
/// Constructor.
///
//______________________________________________________________________________
AliAODCluster::AliAODCluster(Int_t id,
			     UInt_t nLabel,
			     Int_t *label,
			     Double_t energy,
			     Double_t x[3],
			     Double_t pid[13],
			     Char_t ttype,
			     UInt_t selectInfo) :
  AliVCluster(),
  fEnergy(energy),
  fChi2(-999.),
  fID(id),
  fNLabel(0),
  fLabel(0x0),
  fFilterMap(selectInfo),
  fType(ttype),
  fMCEnergyFraction(0.),
  fClusterMCEdepFraction(0x0)
{
  for (Int_t i = 0; i <  3; i++) fPosition[i] = 0.;
  for (Int_t i = 0; i < 13; i++) fPID[i]      = 0;

  if(x)   {for (Int_t i = 0; i < 3  ; i++) SetPositionAt(x[i]  ,i);}
  if(pid) {for (Int_t i = 0; i < 13 ; i++) SetPIDAt     (pid[i],i);}
  SetLabel(label, nLabel);
}

///
/// Constructor.
///
//______________________________________________________________________________
AliAODCluster::AliAODCluster(Int_t id,
			     UInt_t nLabel,
			     Int_t *label,
			     Float_t energy,
			     Float_t x[3],
			     Float_t pid[13],
			     Char_t ttype,
			     UInt_t selectInfo) :
  AliVCluster(),
  fEnergy(energy),
  fChi2(-999.),
  fID(id),
  fNLabel(0),
  fLabel(0x0),
  fFilterMap(selectInfo),
  fType(ttype),
  fMCEnergyFraction(0.),
  fClusterMCEdepFraction(0x0)
{
  for (Int_t i = 0; i <  3; i++) fPosition[i] = 0.;
  for (Int_t i = 0; i < 13; i++) fPID[i]      = 0;

  if(x)   {for (Int_t i = 0; i < 3  ; i++) SetPositionAt(x[i]  ,i);}
  if(pid) {for (Int_t i = 0; i < 13 ; i++) SetPIDAt     (pid[i],i);}
  SetLabel(label, nLabel);
}

///
/// Destructor
///
//______________________________________________________________________________
AliAODCluster::~AliAODCluster()
{
  RemoveLabel();
}

///
/// Clear
///
//______________________________________________________________________________
void AliAODCluster::Clear(const Option_t*)
{
  RemoveLabel();
}

///
/// Copy constructor.
///
//______________________________________________________________________________
AliAODCluster::AliAODCluster(const AliAODCluster& clus) :
  AliVCluster(clus),
  fEnergy(clus.fEnergy),
  fChi2(clus.fChi2),
  fID(clus.fID),
  fNLabel(0),
  fLabel(0x0),
  fFilterMap(clus.fFilterMap),
  fType(clus.fType),
  fMCEnergyFraction(clus.fMCEnergyFraction),
  fClusterMCEdepFraction(0x0)
{
  for(Int_t i = 0; i < 3  ; i++) fPosition[i]  = clus.fPosition[i];
  for(Int_t i = 0; i < 13 ; i++) fPID[i]       = clus.fPID[i];

  SetLabel(clus.fLabel, clus.fNLabel);
  SetClusterMCEdepFraction(clus.fClusterMCEdepFraction);
}

///
/// Assignment operator.
///
//______________________________________________________________________________
AliAODCluster& AliAODCluster::operator=(const AliAODCluster& clus)
{
  if(this!=&clus) {

	for(Int_t i = 0; i < 3 ;  i++) fPosition[i] = clus.fPosition[i];
	for(Int_t i = 0; i < 13 ; i++) fPID[i]      = clus.fPID[i];

    fEnergy = clus.fEnergy;
    fChi2 = clus.fChi2;

    fID = clus.fID;

    SetLabel(clus.fLabel, clus.fNLabel);
    SetClusterMCEdepFraction(clus.fClusterMCEdepFraction);

    fFilterMap = clus.fFilterMap;

    fType = clus.fType;

    fMCEnergyFraction = clus.fMCEnergyFraction;
  }

  return *this;
}

///
/// Set cluster global position.
///
//______________________________________________________________________________
void AliAODCluster::SetPosition(Float_t *x)
{
  if (x) {
    fPosition[0] = x[0];
    fPosition[1] = x[1];
    fPosition[2] = x[2];
  } else {
    fPosition[0] = -999.;
    fPosition[1] = -999.;
    fPosition[2] = -999.;
  }
}

///
/// \return The most probable PID array element.
///
//______________________________________________________________________________
UShort_t AliAODCluster::GetMostProbablePID() const
{
  Int_t nPID = 13;
  UShort_t unknown = AliVCluster::kUnknown;

  UShort_t loc = unknown;
  Double_t max = 0.;
  Bool_t allTheSame = kTRUE;

  for (Int_t iPID = 0; iPID < nPID; iPID++) {
    if (fPID[iPID] >= max) {
      if (fPID[iPID] > max) {
	allTheSame = kFALSE;
	max = fPID[iPID];
	loc = (UShort_t)iPID;
      } else {
	allTheSame = kTRUE;
      }
    }
  }
  return allTheSame ? unknown : loc;
}

///
/// Set the array with MC particle labels and number of labels.
///
//______________________________________________________________________________
void AliAODCluster::SetLabel(Int_t *label, UInt_t size)
{
  if (label && size>0) {
    if (size != (UInt_t)fNLabel) {
      RemoveLabel();
      fNLabel = size;
      fLabel = new Int_t[fNLabel];
    }

    for (Int_t i = 0; i < fNLabel; i++) {
      fLabel[i] = label[i];
    }
  } else {
    RemoveLabel();
  }

  return;
}

///
/// Get the label i of the possible fNLabel in the array fLabel
///
//______________________________________________________________________________
Int_t AliAODCluster::GetLabelAt(UInt_t i) const
{
  if (fLabel && i < (UInt_t)fNLabel) {
    return fLabel[i];
  } else {
    return -999;
  }
}

///
/// Delete MC arrays, used in destructor and Clear() and SetLabel() methods
///
//______________________________________________________________________________
void AliAODCluster::RemoveLabel()
{
  delete[] fLabel;
  fLabel = 0x0;
  fNLabel = 0;

  if(fClusterMCEdepFraction)
    delete[] fClusterMCEdepFraction;
  fClusterMCEdepFraction  = 0 ;

  return;
}

///
/// Prints information about AliAODCluster.
///
//______________________________________________________________________________
void AliAODCluster::Print(Option_t* /* option */) const
{
  printf("Cluster type: %d\n", GetType());
  printf("     energy = %f\n", E());
  printf("       chi2 = %f\n", Chi2());
  const Double_t *pid = GetPID();
  printf("PID weights: photon %0.2f, pi0 %0.2f, electron %0.2f, conversion electron %0.2f\n, hadrons: pion %0.2f, kaon %0.2f, proton %0.2f , neutron %0.2f, kaon %0.2f \n",
	 pid[AliVCluster::kPhoton],   pid[AliVCluster::kPi0],
	 pid[AliVCluster::kElectron], pid[AliVCluster::kEleCon],
	 pid[AliVCluster::kPion],     pid[AliVCluster::kKaon],   pid[AliVCluster::kProton],
	 pid[AliVCluster::kNeutron],  pid[AliVCluster::kKaon0]);
}

///
/// \return Fraction of deposited energy by the one of the particles in array fLable
///
/// \param mcIndex: position of MC particle in array GetLabels()
///
/// The parameter is stored as %, return the corresponding float.
//______________________________________________________________________________
Float_t  AliAODCluster::GetClusterMCEdepFraction(Int_t mcIndex) const
{
  if ( mcIndex < 0 ||  mcIndex >= fNLabel ||  !fClusterMCEdepFraction ) return 0. ;

  return  fClusterMCEdepFraction[mcIndex]/100. ;
}

///
/// Set the array with the fraction of deposited energy in cluster by a given primary
/// particle. Each entry of the array corresponds to the same entry in GetLabels().
/// Set the fraction in % with respect the cluster energy, store a value between 0 and 100
///
/// Not sure this method is usable for AODs
///
/// \param array: energy deposition array
//______________________________________________________________________________
void  AliAODCluster::SetClusterMCEdepFractionFromEdepArray(Float_t *array)
{
  if ( fNLabel <= 0 || !array ) return ;

  fClusterMCEdepFraction = new  UShort_t[fNLabel];

  // Get total deposited energy (can be different from reconstructed energy)
  Float_t totalE = 0;
  for (Int_t i = 0; i < fNLabel; i++) totalE+=array[i];

  if ( totalE < 1.e-3 ) return ; // avoid 0 division in old MC prods.

  // Set the fraction of energy per MC contributor in %
  for (Int_t i = 0; i < fNLabel; i++)
    fClusterMCEdepFraction[i] = TMath::Nint(array[i]/totalE*100.);
}

///
/// Set the array with the fraction of deposited energy in cluster by a given primary
/// particle. Each entry of the array corresponds to the same entry in GetLabels().
///
/// The fraction must already be in % with respect the cluster energy, store a value between 0 and 100
///
/// Execute after setting of fLable and fNLabel
///
/// \param array: array of fraction of energy deposition / cluster energy
//______________________________________________________________________________
void  AliAODCluster::SetClusterMCEdepFraction(UShort_t *array)
{
  if ( fNLabel <= 0 || !array )
    return ;

  fClusterMCEdepFraction = new  UShort_t[fNLabel];

  for (Int_t i = 0; i < fNLabel; i++)
    fClusterMCEdepFraction[i] = array[i];
}

<|endoftext|>


<commit_before>#ifdef HAVE_CMAKE_CONFIG
  #include "cmake_config.h"
#elif defined (HAVE_CONFIG_H)
  #include "config.h"
#endif // ifdef HAVE_CMAKE_CONFIG

#include <boost/filesystem.hpp>

#include <dune/common/exceptions.hh>
#include <dune/common/mpihelper.hh>
#include <dune/common/timer.hh>

#include <dune/fem/misc/mpimanager.hh>
#include <dune/fem/misc/gridwidth.hh>

#include <dune/grid/part/leaf.hh>

#include <dune/stuff/common/parameter/tree.hh>
#include <dune/stuff/common/logging.hh>
#include <dune/stuff/grid/provider/cube.hh>
#if HAVE_ALUGRID
  #include <dune/stuff/grid/provider/gmsh.hh>
#endif // HAVE_ALUGRID
#include <dune/stuff/grid/boundaryinfo.hh>
#include <dune/stuff/function/expression.hh>
#include <dune/stuff/discretefunction/norm.hh>

#include <dune/detailed/solvers/stationary/linear/elliptic/model/default.hh>
#include <dune/detailed/solvers/stationary/linear/elliptic/model/thermalblock.hh>
#include <dune/detailed/solvers/stationary/linear/elliptic/continuousgalerkin/dune-detailed-discretizations.hh>

#ifdef POLORDER
  const int polOrder = POLORDER;
#else
  const int polOrder = 1;
#endif

const std::string id = "stationary.linear.elliptic.cg.ddd";

/**
  \brief      Creates a parameter file if it does not exist.

              Nothing is done if the file already exists. If not, a parameter file will be created with all neccessary
              keys and values.
  \param[in]  filename
              (Relative) path to the file.
  **/
void ensureParamFile(std::string filename)
{
  // only write param file if there is none
  if (!boost::filesystem::exists(filename)) {
    std::ofstream file;
    file.open(filename);
    file << "[" << id << "]" << std::endl;
    file << "grid = stuff.grid.provider.cube" << std::endl;
    file << "model = detailed.solvers.stationary.linear.elliptic.model.default" << std::endl;
    file << "exact_solution.order = 2" << std::endl;
    file << "exact_solution.variable = x" << std::endl;
    file << "exact_solution.expression = [-0.5*x[0]*x[0] + 0.5*x[0]]" << std::endl;
    file << "[stuff.grid.provider.cube]" << std::endl;
    file << "lowerLeft = [0.0; 0.0; 0.0]" << std::endl;
    file << "upperRight = [1.0; 1.0; 1.0]" << std::endl;
    file << "numElements = 4" << std::endl;
    file << "filename = " << id << ".grid" << std::endl;
    file << "[detailed.solvers.stationary.linear.elliptic.model.default]" << std::endl;
    file << "diffusion.order = 0"  << std::endl;
    file << "diffusion.variable = x" << std::endl;
    file << "diffusion.expression = [1.0; 1.0; 1.0]"  << std::endl;
    file << "force.order = 0"  << std::endl;
    file << "force.variable = x" << std::endl;
    file << "force.expression = [1.0; 1.0; 1.0]"  << std::endl;
    file << "dirichlet.order = 0"  << std::endl;
    file << "dirichlet.variable = x" << std::endl;
    file << "dirichlet.expression = [1.0; 1.0; 1.0]"  << std::endl;
    file << "neumann.order = 0"  << std::endl;
    file << "neumann.variable = x" << std::endl;
    file << "neumann.expression = [1.0; 1.0; 1.0]"  << std::endl;
    file << "[detailed.solvers.stationary.linear.elliptic.model.thermalblock]" << std::endl;
    file << "diffusion.order = 0"  << std::endl;
    file << "diffusion.lowerLeft = [0.0; 0.0; 0.0]" << std::endl; // should coincide with the grid
    file << "diffusion.upperRight = [1.0; 1.0; 1.0]" << std::endl; // should coincide with the grid
    file << "diffusion.numElements = [2; 2; 2]"  << std::endl;
    file << "diffusion.components = [1.0; 10.0; 3.0; 2.1]"  << std::endl;
    file << "force.order = 0"  << std::endl;
    file << "force.variable = x" << std::endl;
    file << "force.expression = [1.0; 1.0; 1.0]"  << std::endl;
    file << "dirichlet.order = 0"  << std::endl;
    file << "dirichlet.variable = x" << std::endl;
    file << "dirichlet.expression = [1.0; 1.0; 1.0]"  << std::endl;
    file << "neumann.order = 0"  << std::endl;
    file << "neumann.variable = x" << std::endl;
    file << "neumann.expression = [1.0; 1.0; 1.0]"  << std::endl;
    file << "[detailed.solvers.stationary.linear.elliptic.continuousgalerkin]" << std::endl;
    file << "solve.type = eigen.bicgstab.incompletelut" << std::endl;
    file << "solve.maxIter = 5000"  << std::endl;
    file << "solve.precision = 1e-12"  << std::endl;
    file << "visualize.filename = " << id << ".solution"  << std::endl;
    file << "visualize.name = solution"  << std::endl;
    file.close();
  } // only write param file if there is none
} // void ensureParamFile()

template< class DiscreteFunctionType,
          class OutStreamType >
void compute_errors(const Dune::ParameterTree& paramTree,
                    const DiscreteFunctionType& discreteFunction,
                    OutStreamType& out,
                    std::string prefix = "")
{
  // preparations
  typedef typename DiscreteFunctionType::RangeFieldType RangeFieldType;
  typedef Dune::Stuff::Function::Expression<
      typename DiscreteFunctionType::DomainFieldType,
      DiscreteFunctionType::dimDomain,
      RangeFieldType,
      DiscreteFunctionType::dimRange >
    FunctionType;
  const FunctionType function = FunctionType::createFromParamTree(paramTree);
  const unsigned int functionOrder = paramTree.get("order", 100);
  // compute norms
  out << prefix << " norm | exact solution | discrete solution | error (abs) | error (rel)" << std::endl;
  out << prefix << "------+----------------+-------------------+-------------+-------------" << std::endl;
  const RangeFieldType L2_reference_norm = Dune::Stuff::DiscreteFunction::Norm::L2(discreteFunction.space().gridPart(),
                                                                                function,
                                                                                functionOrder);
  out.precision(2);
  out << prefix << "   L2 | " << std::setw(14) << std::scientific << L2_reference_norm
                                      << " | " << std::flush;
  const RangeFieldType L2_discrete_norm = Dune::Stuff::DiscreteFunction::Norm::L2(discreteFunction);
  out << std::setw(17) << std::scientific << L2_discrete_norm << " | " << std::flush;
  const RangeFieldType L2_difference = Dune::Stuff::DiscreteFunction::Norm::L2_difference(function, functionOrder, discreteFunction);
  out << std::setw(11) << std::scientific << L2_difference << " | " << std::flush;
  out << std::setw(11) << std::scientific << L2_difference/L2_reference_norm << std::endl;
  out << prefix << "------+----------------+-------------------+-------------+-------------" << std::endl;
} // void compute_norms(...)

Dune::Stuff::Grid::Provider::Interface<>* createProvider(const Dune::Stuff::Common::ExtendedParameterTree& paramTree)
{
  // prepare
  const std::string providerId = paramTree.get< std::string >(id + ".grid");
  // choose provider
  if (providerId == "stuff.grid.provider.cube") {
    typedef Dune::Stuff::Grid::Provider::Cube<> CubeProviderType;
    CubeProviderType* cubeProvider = new CubeProviderType(CubeProviderType::createFromParamTree(paramTree));
    return cubeProvider;
#if HAVE_ALUGRID
  } else if (providerId == "stuff.grid.provider.gmsh") {
    typedef Dune::Stuff::Grid::Provider::Gmsh<> GmshProviderType;
    GmshProviderType* gmshProvider = new GmshProviderType(GmshProviderType::createFromParamTree(paramTree));
    return gmshProvider;
#endif // HAVE_ALUGRID
  } else
    DUNE_THROW(Dune::RangeError,
               "\nError: unknown grid provider ('" << providerId << "') given in the following Dune::Parametertree:\n" << paramTree.reportString("  "));
} // ... createProvider(...)

template< class DomainFieldType, int dimDomain, class RangeFieldType, int dimRange >
Dune::Detailed::Solvers::Stationary::Linear::Elliptic::Model::Interface< DomainFieldType, dimDomain, RangeFieldType, dimRange >*
createModel(const Dune::Stuff::Common::ExtendedParameterTree& paramTree)
{
  // prepare
  const std::string modelId = paramTree.sub(id).get< std::string >("model");
  // choose model
  if (modelId == "detailed.solvers.stationary.linear.elliptic.model.default") {
    typedef Dune::Detailed::Solvers
        ::Stationary
        ::Linear
        ::Elliptic
        ::Model
        ::Default< DomainFieldType, dimDomain, RangeFieldType, dimRange >
      DefaultModelType;
    return new DefaultModelType(DefaultModelType::createFromParamTree(paramTree));
  } else if (modelId == "detailed.solvers.stationary.linear.elliptic.model.thermalblock") {
    typedef Dune::Detailed::Solvers
        ::Stationary
        ::Linear
        ::Elliptic
        ::Model
        ::Thermalblock< DomainFieldType, dimDomain, RangeFieldType, dimRange >
      ThermalblockModelType;
    return new ThermalblockModelType(ThermalblockModelType::createFromParamTree(paramTree));
  } else
    DUNE_THROW(Dune::RangeError,
               "\nError: unknown model ('" << modelId << "') given in the following Dune::Parametertree:\n" << paramTree.reportString("  "));
} // ... createModel(...)

int main(int argc, char** argv)
{
  try {
    // mpi
    Dune::MPIManager::initialize(argc, argv);

    // parameter
    const std::string filename = id + ".param";
    ensureParamFile(filename);
    Dune::Stuff::Common::ExtendedParameterTree paramTree(argc, argv, filename);
    paramTree.assertSub(id);

    // logger
    Dune::Stuff::Common::Logger().create(Dune::Stuff::Common::LOG_INFO |
                                         Dune::Stuff::Common::LOG_CONSOLE |
                                         Dune::Stuff::Common::LOG_DEBUG);
    Dune::Stuff::Common::LogStream& info = Dune::Stuff::Common::Logger().info();
    Dune::Stuff::Common::LogStream& debug = Dune::Stuff::Common::Logger().debug();

    // timer
    Dune::Timer timer;

    // grid
    info << "setting up grid: " << std::endl;
    debug.suspend();
    typedef Dune::Stuff::Grid::Provider::Interface<> GridProviderType;
    const GridProviderType* gridProvider = createProvider(paramTree);
    typedef GridProviderType::GridType GridType;
    const Dune::shared_ptr< const GridType > grid = gridProvider->grid();
    typedef Dune::grid::Part::Leaf::Const< GridType > GridPartType;
    const Dune::shared_ptr< const GridPartType > gridPart(new GridPartType(*grid));
    info << "  done (took " << timer.elapsed()
         << " sec, has " << grid->size(0) << " element";
    if (grid->size(0) > 1)
      info << "s";
    info << " and a width of "
         << Dune::GridWidth::calcGridWidth(*gridPart) << ")" << std::endl;
    info << "visualizing grid... " << std::flush;
    timer.reset();
    gridProvider->visualize(id + ".grid");
    info << " done (took " << timer.elapsed() << " sek)" << std::endl;
    debug.resume();

    // model
    info << "setting up model... " << std::flush;
    timer.reset();
    const unsigned int DUNE_UNUSED(dimDomain) = GridProviderType::dim;
    const unsigned int DUNE_UNUSED(dimRange) = 1;
    typedef GridProviderType::CoordinateType::value_type DomainFieldType;
    typedef DomainFieldType RangeFieldType;
    typedef Dune::Detailed::Solvers
        ::Stationary
        ::Linear
        ::Elliptic
        ::Model
        ::Interface< DomainFieldType, dimDomain, RangeFieldType, dimRange >
      ModelType;
    const Dune::shared_ptr< const ModelType > model(createModel< DomainFieldType, dimDomain, RangeFieldType, dimRange >(paramTree));
    typedef Dune::Stuff::Grid::BoundaryInfo::AllDirichlet BoundaryInfoType;
    const Dune::shared_ptr< const BoundaryInfoType > boundaryInfo(new BoundaryInfoType());
    info << "done (took " << timer.elapsed() << " sec)" << std::endl;

    // solver
    info << "initializing solver... " << std::flush;
    debug.suspend();
    timer.reset();
    typedef Dune::Detailed::Solvers
        ::Stationary
        ::Linear
        ::Elliptic
        ::ContinuousGalerkin::DuneDetailedDiscretizations< ModelType, GridPartType, BoundaryInfoType, polOrder >
        SolverType;
    SolverType solver(model, gridPart, boundaryInfo);
    solver.init("  ", debug);
    info << "done (took " << timer.elapsed() << " sec)" << std::endl;
    debug.resume();

    info << "solving... " << std::flush;
    debug.suspend();
    timer.reset();
    const Dune::Stuff::Common::ExtendedParameterTree solveTree = paramTree.sub(solver.id()).sub("solve");
    typedef SolverType::VectorBackendType DofVectorType;
    Dune::shared_ptr< DofVectorType > solution = solver.createVector();
    solver.solve(*solution,
                 solveTree.get< std::string >("type"),
                 solveTree.get< int >("maxIter"),
                 solveTree.get< double >("precision"),
                 "  ",
                 debug);
    info << "done (took " << timer.elapsed() << " sec)" << std::endl;
    debug.resume();

    info << "postprocessing:" << std::endl;
    const Dune::Stuff::Common::ExtendedParameterTree visualizeTree = paramTree.sub(solver.id()).sub("visualize");
    solver.visualize(*solution,
                     visualizeTree.get< std::string >("filename"),
                     visualizeTree.get< std::string >("name"),
                     "  ",
                     info);

    if (dimDomain == 1) {
      info << "computing errors:" << std::endl;
      const Dune::shared_ptr< const SolverType::DiscreteFunctionType > discreteFunction = solver.createDiscreteFunction(*solution, "discrete_solution");
      compute_errors(paramTree.sub(id).sub("exact_solution"), *discreteFunction, info, "  ");
    }

    // if we came that far we can as well be happy about it
    return 0;
  } catch(Dune::Exception& e) {
    std::cerr << "Dune reported error: " << e.what() << std::endl;
  } catch(std::exception& e) {
    std::cerr << e.what() << std::endl;
  } catch( ... ) {
    std::cerr << "Unknown exception thrown!" << std::endl;
  } // try
} // main
<commit_msg>[examples...elliptic.cg...] update<commit_after>#ifdef HAVE_CMAKE_CONFIG
  #include "cmake_config.h"
#elif defined (HAVE_CONFIG_H)
  #include "config.h"
#endif // ifdef HAVE_CMAKE_CONFIG

#include <boost/filesystem.hpp>

#include <dune/common/exceptions.hh>
#include <dune/common/mpihelper.hh>
#include <dune/common/timer.hh>

#include <dune/fem/misc/mpimanager.hh>
#include <dune/fem/misc/gridwidth.hh>

#include <dune/grid/part/leaf.hh>

#include <dune/stuff/common/parameter/tree.hh>
#include <dune/stuff/common/logging.hh>
#include <dune/stuff/grid/provider.hh>
#include <dune/stuff/grid/boundaryinfo.hh>
#include <dune/stuff/function/expression.hh>
#include <dune/stuff/discretefunction/norm.hh>

#include <dune/detailed/solvers/stationary/linear/elliptic/model.hh>
#include <dune/detailed/solvers/stationary/linear/elliptic/continuousgalerkin/dune-detailed-discretizations.hh>

#ifdef POLORDER
  const int polOrder = POLORDER;
#else
  const int polOrder = 1;
#endif

const std::string id = "stationary.linear.elliptic.cg.ddd";

using namespace Dune;
using namespace Dune::Detailed::Solvers;

/**
  \brief      Creates a parameter file if it does not exist.

              Nothing is done if the file already exists. If not, a parameter file will be created with all neccessary
              keys and values.
  \param[in]  filename
              (Relative) path to the file.
  **/
void ensureParamFile(std::string filename)
{
  // only write param file if there is none
  if (!boost::filesystem::exists(filename)) {
    std::ofstream file;
    file.open(filename);
    file << "[" << id << "]" << std::endl;
    file << "grid = stuff.grid.provider.cube" << std::endl;
    file << "model = detailed.solvers.stationary.linear.elliptic.model.default" << std::endl;
    file << "filename = " << id << std::endl;
    file << "exact_solution.order = 2" << std::endl;
    file << "exact_solution.variable = x" << std::endl;
    file << "exact_solution.expression = [-0.5*x[0]*x[0] + 0.5*x[0]]" << std::endl;
    file << "[stuff.grid.provider.cube]" << std::endl;
    file << "lowerLeft = [0.0; 0.0; 0.0]" << std::endl;
    file << "upperRight = [1.0; 1.0; 1.0]" << std::endl;
    file << "numElements = 4" << std::endl;
    file << "[detailed.solvers.stationary.linear.elliptic.model.default]" << std::endl;
    file << "diffusion.order = 0"  << std::endl;
    file << "diffusion.variable = x" << std::endl;
    file << "diffusion.expression = [1.0; 1.0; 1.0]"  << std::endl;
    file << "force.order = 0"  << std::endl;
    file << "force.variable = x" << std::endl;
    file << "force.expression = [1.0; 1.0; 1.0]"  << std::endl;
    file << "dirichlet.order = 0"  << std::endl;
    file << "dirichlet.variable = x" << std::endl;
    file << "dirichlet.expression = [0.0; 0.0; 0.0]"  << std::endl;
    file << "neumann.order = 0"  << std::endl;
    file << "neumann.variable = x" << std::endl;
    file << "neumann.expression = [0.0; 0.0; 0.0]"  << std::endl;
    file << "[detailed.solvers.stationary.linear.elliptic.model.thermalblock]" << std::endl;
    file << "diffusion.order = 0"  << std::endl;
    file << "diffusion.lowerLeft = [0.0; 0.0; 0.0]" << std::endl; // should coincide with the grid
    file << "diffusion.upperRight = [1.0; 1.0; 1.0]" << std::endl; // should coincide with the grid
    file << "diffusion.numElements = [2; 2; 2]"  << std::endl;
    file << "diffusion.components = [1.0; 10.0; 3.0; 2.1]"  << std::endl;
    file << "force.order = 0"  << std::endl;
    file << "force.variable = x" << std::endl;
    file << "force.expression = [1.0; 1.0; 1.0]"  << std::endl;
    file << "dirichlet.order = 0"  << std::endl;
    file << "dirichlet.variable = x" << std::endl;
    file << "dirichlet.expression = [1.0; 1.0; 1.0]"  << std::endl;
    file << "neumann.order = 0"  << std::endl;
    file << "neumann.variable = x" << std::endl;
    file << "neumann.expression = [1.0; 1.0; 1.0]"  << std::endl;
    file << "[detailed.solvers.stationary.linear.elliptic.continuousgalerkin]" << std::endl;
    file << "solve.type = eigen.bicgstab.incompletelut" << std::endl;
    file << "solve.maxIter = 5000"  << std::endl;
    file << "solve.precision = 1e-12"  << std::endl;
    file << "visualize.name = solution"  << std::endl;
    file.close();
  } // only write param file if there is none
} // void ensureParamFile()

template< class DiscreteFunctionType,
          class OutStreamType >
void compute_errors(const Dune::ParameterTree& paramTree,
                    const DiscreteFunctionType& discreteFunction,
                    OutStreamType& out,
                    std::string prefix = "")
{
  // preparations
  typedef typename DiscreteFunctionType::RangeFieldType RangeFieldType;
  typedef Dune::Stuff::Function::Expression<
      typename DiscreteFunctionType::DomainFieldType,
      DiscreteFunctionType::dimDomain,
      RangeFieldType,
      DiscreteFunctionType::dimRange >
    FunctionType;
  const FunctionType function = FunctionType::createFromParamTree(paramTree);
  const unsigned int functionOrder = paramTree.get("order", 100);
  // compute norms
  out << prefix << " norm | exact solution | discrete solution | error (abs) | error (rel)" << std::endl;
  out << prefix << "------+----------------+-------------------+-------------+-------------" << std::endl;
  const RangeFieldType L2_reference_norm = Dune::Stuff::DiscreteFunction::Norm::L2(discreteFunction.space().gridPart(),
                                                                                function,
                                                                                functionOrder);
  out.precision(2);
  out << prefix << "   L2 | " << std::setw(14) << std::scientific << L2_reference_norm
                                      << " | " << std::flush;
  const RangeFieldType L2_discrete_norm = Dune::Stuff::DiscreteFunction::Norm::L2(discreteFunction);
  out << std::setw(17) << std::scientific << L2_discrete_norm << " | " << std::flush;
  const RangeFieldType L2_difference = Dune::Stuff::DiscreteFunction::Norm::L2_difference(function, functionOrder, discreteFunction);
  out << std::setw(11) << std::scientific << L2_difference << " | " << std::flush;
  out << std::setw(11) << std::scientific << L2_difference/L2_reference_norm << std::endl;
  out << prefix << "------+----------------+-------------------+-------------+-------------" << std::endl;
} // void compute_norms(...)

int main(int argc, char** argv)
{
  try {
    // mpi
    MPIManager::initialize(argc, argv);

    // parameter
    const std::string filename = id + ".param";
    ensureParamFile(filename);
    Stuff::Common::ExtendedParameterTree paramTree(argc, argv, filename);
    paramTree.assertSub(id);

    // logger
    Stuff::Common::Logger().create(Stuff::Common::LOG_INFO |
                                   Stuff::Common::LOG_CONSOLE |
                                   Stuff::Common::LOG_DEBUG);
    Stuff::Common::LogStream& info = Stuff::Common::Logger().info();
    Stuff::Common::LogStream& debug = Stuff::Common::Logger().debug();

    // timer
    Dune::Timer timer;

    // grid
    info << "setting up grid: " << std::endl;
    debug.suspend();
    typedef Dune::Stuff::Grid::Provider::Interface<> GridProviderType;
    const std::string gridType = paramTree.get< std::string >(id + ".grid", "stuff.grid.provider.cube");
    const GridProviderType* gridProvider = Stuff::Grid::Provider::create(gridType,
                                                                         paramTree);
    typedef GridProviderType::GridType GridType;
    const Dune::shared_ptr< const GridType > grid = gridProvider->grid();
    typedef Dune::grid::Part::Leaf::Const< GridType > GridPartType;
    const Dune::shared_ptr< const GridPartType > gridPart(new GridPartType(*grid));
    info << "  done (took " << timer.elapsed()
         << " sec, has " << grid->size(0) << " element";
    if (grid->size(0) > 1)
      info << "s";
    info << " and a width of "
         << Dune::GridWidth::calcGridWidth(*gridPart) << ")" << std::endl;
    info << "visualizing grid... " << std::flush;
    timer.reset();
    gridProvider->visualize(paramTree.get(id + ".filename", id) + ".grid");
    info << " done (took " << timer.elapsed() << " sek)" << std::endl;
    debug.resume();

    // model
    info << "setting up model... " << std::flush;
    timer.reset();
    const unsigned int DUNE_UNUSED(dimDomain) = GridProviderType::dim;
    const unsigned int DUNE_UNUSED(dimRange) = 1;
    typedef GridProviderType::CoordinateType::value_type DomainFieldType;
    typedef DomainFieldType RangeFieldType;
    typedef Stationary::Linear::Elliptic::Model::Interface< DomainFieldType, dimDomain,
                                                            RangeFieldType, dimRange >
        ModelType;
    const std::string modelType = paramTree.get< std::string >(id + ".model");
    const shared_ptr< const ModelType > model(
          Stationary::Linear::Elliptic::Model::create< DomainFieldType, dimDomain, RangeFieldType, dimRange >(modelType,
                                                                                paramTree));
    typedef Dune::Stuff::Grid::BoundaryInfo::AllDirichlet BoundaryInfoType;
    const Dune::shared_ptr< const BoundaryInfoType > boundaryInfo(new BoundaryInfoType());
    info << "done (took " << timer.elapsed() << " sec)" << std::endl;
    info << "visualizing model... " << std::flush;
    timer.reset();
    model->visualize(gridPart->gridView(), paramTree.get(id + ".filename", id) + ".model");
    info << "done (took " << timer.elapsed() << " sec)" << std::endl;

    // solver
    info << "initializing solver... " << std::flush;
    debug.suspend();
    timer.reset();
    typedef Stationary::Linear::Elliptic::ContinuousGalerkin::DuneDetailedDiscretizations<  ModelType,
                                                                                GridPartType,
                                                                                BoundaryInfoType,
                                                                                polOrder >
        SolverType;
    SolverType solver(model, gridPart, boundaryInfo);
    solver.init("  ", debug);
    info << "done (took " << timer.elapsed() << " sec)" << std::endl;
    debug.resume();

    info << "solving... " << std::flush;
    debug.suspend();
    timer.reset();
    const Dune::Stuff::Common::ExtendedParameterTree solverTree = paramTree.sub(solver.id());
    typedef SolverType::VectorBackendType DofVectorType;
    Dune::shared_ptr< DofVectorType > solution = solver.createVector();
    solver.solve(*solution,
                 solverTree.get("solve.type", "eigen.bicgstab.diagonal"),
                 solverTree.get("solve.maxIter", 1000),
                 solverTree.get("solve.precision", 1e-12),
                 "  ",
                 debug);
    info << "done (took " << timer.elapsed() << " sec)" << std::endl;
    debug.resume();

    info << "postprocessing:" << std::endl;
    solver.visualize(*solution,
                     paramTree.get< std::string >(id + ".filename") + ".solution",
                     solverTree.get< std::string >("visualize.name"),
                     "  ",
                     info);

    if (dimDomain == 1) {
      info << "computing errors:" << std::endl;
      const Dune::shared_ptr< const SolverType::DiscreteFunctionType > discreteFunction = solver.createDiscreteFunction(*solution, "discrete_solution");
      compute_errors(paramTree.sub(id).sub("exact_solution"), *discreteFunction, info, "  ");
    }

    // if we came that far we can as well be happy about it
    return 0;
  } catch(Dune::Exception& e) {
    std::cerr << "Dune reported error: " << e.what() << std::endl;
  } catch(std::exception& e) {
    std::cerr << e.what() << std::endl;
  } catch( ... ) {
    std::cerr << "Unknown exception thrown!" << std::endl;
  } // try
} // main
<|endoftext|>


<commit_before>#include "RecorderCallbackH264.h"

#include <Windows.h>

#include <mfapi.h>

#include <mfidl.h>

#include <Mfreadwrite.h>

#include <mferror.h>

#include <string>
#include <vector>

#pragma comment(lib, "mfreadwrite")
#pragma comment(lib, "mfplat")
#pragma comment(lib, "mfuuid")

namespace Effekseer
{
namespace Tool
{

class VideoWriter
{
private:
	IMFSinkWriter* sinkWriter_ = nullptr;
	DWORD streamIndex_ = 0;
	int32_t width_ = 0;
	int32_t height_ = 0;
	int32_t framerate_ = 0;
	uint64_t timestamp_ = 0;
	bool isValid_ = false;

public:
	VideoWriter()
	{
		HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
		if (SUCCEEDED(hr))
		{
			hr = MFStartup(MF_VERSION);
			if (SUCCEEDED(hr))
			{
				isValid_ = true;
			}
		}
	}

	int32_t GetBufferSize() const
	{
		return width_ * height_ * 4;
	}

	bool Start(const std::u16string& path, int width, int height, int framerate, int frameCount)
	{
		if (!isValid_)
		{
			return false;
		}

		IMFMediaType* pMediaTypeOut = nullptr;
		IMFMediaType* pMediaTypeIn = nullptr;
		int bitrate = 8000000;

		HRESULT hr = MFCreateSinkWriterFromURL(reinterpret_cast<const wchar_t*>(path.c_str()), NULL, NULL, &sinkWriter_);

		if (SUCCEEDED(hr))
		{
			hr = MFCreateMediaType(&pMediaTypeOut);
		}
		if (SUCCEEDED(hr))
		{
			hr = pMediaTypeOut->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
		}
		if (SUCCEEDED(hr))
		{
			hr = pMediaTypeOut->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264);
		}
		if (SUCCEEDED(hr))
		{
			hr = pMediaTypeOut->SetUINT32(MF_MT_AVG_BITRATE, bitrate);
		}
		if (SUCCEEDED(hr))
		{
			hr = pMediaTypeOut->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
		}
		if (SUCCEEDED(hr))
		{
			hr = MFSetAttributeSize(pMediaTypeOut, MF_MT_FRAME_SIZE, width, height);
		}
		if (SUCCEEDED(hr))
		{
			hr = MFSetAttributeRatio(pMediaTypeOut, MF_MT_FRAME_RATE, framerate, 1);
		}
		if (SUCCEEDED(hr))
		{
			hr = MFSetAttributeRatio(pMediaTypeOut, MF_MT_PIXEL_ASPECT_RATIO, 1, 1);
		}
		if (SUCCEEDED(hr))
		{
			hr = sinkWriter_->AddStream(pMediaTypeOut, &streamIndex_);
		}

		if (SUCCEEDED(hr))
		{
			hr = MFCreateMediaType(&pMediaTypeIn);
		}
		if (SUCCEEDED(hr))
		{
			hr = pMediaTypeIn->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
		}
		if (SUCCEEDED(hr))
		{
			hr = pMediaTypeIn->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32);
		}
		if (SUCCEEDED(hr))
		{
			hr = pMediaTypeIn->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
		}
		if (SUCCEEDED(hr))
		{
			hr = MFSetAttributeSize(pMediaTypeIn, MF_MT_FRAME_SIZE, width, height);
		}
		if (SUCCEEDED(hr))
		{
			hr = MFSetAttributeRatio(pMediaTypeIn, MF_MT_FRAME_RATE, framerate, 1);
		}
		if (SUCCEEDED(hr))
		{
			hr = MFSetAttributeRatio(pMediaTypeIn, MF_MT_PIXEL_ASPECT_RATIO, 1, 1);
		}
		if (SUCCEEDED(hr))
		{
			hr = sinkWriter_->SetInputMediaType(streamIndex_, pMediaTypeIn, NULL);
		}

		if (SUCCEEDED(hr))
		{
			hr = sinkWriter_->BeginWriting();
		}

		SafeRelease(pMediaTypeOut);
		SafeRelease(pMediaTypeIn);

		if (SUCCEEDED(hr))
		{
			width_ = width;
			height_ = height;
			framerate_ = framerate;
			timestamp_ = 0;
			return true;
		}
		else
		{
			SafeRelease(sinkWriter_);
			streamIndex_ = 0;
			return false;
		}
	}

	bool Write(const std::vector<uint8_t> buffer)
	{
		if (sinkWriter_ == nullptr)
		{
			return false;
		}

		if (buffer.size() != GetBufferSize())
		{
			return false;
		}

		IMFSample* sample = NULL;
		IMFMediaBuffer* videoBuffer = NULL;

		const LONG widthSize = 4 * width_;
		const DWORD bufferSize = widthSize * height_;

		BYTE* internalData = NULL;

		HRESULT hr = MFCreateMemoryBuffer(bufferSize, &videoBuffer);

		if (SUCCEEDED(hr))
		{
			hr = videoBuffer->Lock(&internalData, NULL, NULL);
		}
		if (SUCCEEDED(hr))
		{
			hr = MFCopyImage(
				internalData,
				widthSize,
				(BYTE*)buffer.data(),
				widthSize,
				widthSize,
				height_);
		}
		if (videoBuffer)
		{
			videoBuffer->Unlock();
		}

		if (SUCCEEDED(hr))
		{
			hr = videoBuffer->SetCurrentLength(bufferSize);
		}

		if (SUCCEEDED(hr))
		{
			hr = MFCreateSample(&sample);
		}
		if (SUCCEEDED(hr))
		{
			hr = sample->AddBuffer(videoBuffer);
		}

		if (SUCCEEDED(hr))
		{
			hr = sample->SetSampleTime(timestamp_);
		}
		if (SUCCEEDED(hr))
		{
			hr = sample->SetSampleDuration(10 * 1000 * 1000 / framerate_);
		}

		if (SUCCEEDED(hr))
		{
			hr = sinkWriter_->WriteSample(streamIndex_, sample);
		}

		timestamp_ += 10 * 1000 * 1000 / framerate_;

		SafeRelease(sample);
		SafeRelease(videoBuffer);
		return SUCCEEDED(hr);
	}

	void End()
	{
		if (sinkWriter_ != nullptr)
		{
			sinkWriter_->Finalize();
			SafeRelease(sinkWriter_);
		}
	}

	~VideoWriter()
	{
		End();

		if (isValid_)
		{
			MFShutdown();
			CoUninitialize();
		}
	}
};

bool RecorderCallbackH264::OnBeginRecord()
{
	auto path = std::u16string(recordingParameter_.GetPath()) + std::u16string(recordingParameter_.GetExt());
	videoWriter_ = std::make_shared<VideoWriter>();
	if (!videoWriter_->Start(path, imageSize_.X, imageSize_.Y, (int32_t)(60.0f / (float)recordingParameter_.Freq), recordingParameter_.Count))
	{
		return false;
	}

	buffer_.resize(videoWriter_->GetBufferSize());

	return true;
}

void RecorderCallbackH264::OnEndRecord()
{
	videoWriter_.reset();
}

void RecorderCallbackH264::OnEndFrameRecord(int index, std::vector<Effekseer::Color>& pixels)
{
	for (int y = 0; y < imageSize_.Y; y++)
	{
		for (int x = 0; x < imageSize_.X; x++)
		{
			const auto pixel = pixels[x + y * imageSize_.X];

			auto p = reinterpret_cast<Effekseer::Color*>(buffer_.data());
			p[x + (imageSize_.Y - 1 - y) * imageSize_.X + 0] = pixels[x + y * imageSize_.X];
		}
	}

	videoWriter_->Write(buffer_);
}

} // namespace Tool
} // namespace Effekseer<commit_msg>Fix a bug where a R and B recorded h264 are flipped<commit_after>#include "RecorderCallbackH264.h"

#include <Windows.h>

#include <mfapi.h>

#include <mfidl.h>

#include <Mfreadwrite.h>

#include <mferror.h>

#include <string>
#include <vector>

#pragma comment(lib, "mfreadwrite")
#pragma comment(lib, "mfplat")
#pragma comment(lib, "mfuuid")

namespace Effekseer
{
namespace Tool
{

class VideoWriter
{
private:
	IMFSinkWriter* sinkWriter_ = nullptr;
	DWORD streamIndex_ = 0;
	int32_t width_ = 0;
	int32_t height_ = 0;
	int32_t framerate_ = 0;
	uint64_t timestamp_ = 0;
	bool isValid_ = false;

public:
	VideoWriter()
	{
		HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
		if (SUCCEEDED(hr))
		{
			hr = MFStartup(MF_VERSION);
			if (SUCCEEDED(hr))
			{
				isValid_ = true;
			}
		}
	}

	int32_t GetBufferSize() const
	{
		return width_ * height_ * 4;
	}

	bool Start(const std::u16string& path, int width, int height, int framerate, int frameCount)
	{
		if (!isValid_)
		{
			return false;
		}

		IMFMediaType* pMediaTypeOut = nullptr;
		IMFMediaType* pMediaTypeIn = nullptr;
		int bitrate = 8000000;

		HRESULT hr = MFCreateSinkWriterFromURL(reinterpret_cast<const wchar_t*>(path.c_str()), NULL, NULL, &sinkWriter_);

		if (SUCCEEDED(hr))
		{
			hr = MFCreateMediaType(&pMediaTypeOut);
		}
		if (SUCCEEDED(hr))
		{
			hr = pMediaTypeOut->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
		}
		if (SUCCEEDED(hr))
		{
			hr = pMediaTypeOut->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264);
		}
		if (SUCCEEDED(hr))
		{
			hr = pMediaTypeOut->SetUINT32(MF_MT_AVG_BITRATE, bitrate);
		}
		if (SUCCEEDED(hr))
		{
			hr = pMediaTypeOut->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
		}
		if (SUCCEEDED(hr))
		{
			hr = MFSetAttributeSize(pMediaTypeOut, MF_MT_FRAME_SIZE, width, height);
		}
		if (SUCCEEDED(hr))
		{
			hr = MFSetAttributeRatio(pMediaTypeOut, MF_MT_FRAME_RATE, framerate, 1);
		}
		if (SUCCEEDED(hr))
		{
			hr = MFSetAttributeRatio(pMediaTypeOut, MF_MT_PIXEL_ASPECT_RATIO, 1, 1);
		}
		if (SUCCEEDED(hr))
		{
			hr = sinkWriter_->AddStream(pMediaTypeOut, &streamIndex_);
		}

		if (SUCCEEDED(hr))
		{
			hr = MFCreateMediaType(&pMediaTypeIn);
		}
		if (SUCCEEDED(hr))
		{
			hr = pMediaTypeIn->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
		}
		if (SUCCEEDED(hr))
		{
			hr = pMediaTypeIn->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32);
		}
		if (SUCCEEDED(hr))
		{
			hr = pMediaTypeIn->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
		}
		if (SUCCEEDED(hr))
		{
			hr = MFSetAttributeSize(pMediaTypeIn, MF_MT_FRAME_SIZE, width, height);
		}
		if (SUCCEEDED(hr))
		{
			hr = MFSetAttributeRatio(pMediaTypeIn, MF_MT_FRAME_RATE, framerate, 1);
		}
		if (SUCCEEDED(hr))
		{
			hr = MFSetAttributeRatio(pMediaTypeIn, MF_MT_PIXEL_ASPECT_RATIO, 1, 1);
		}
		if (SUCCEEDED(hr))
		{
			hr = sinkWriter_->SetInputMediaType(streamIndex_, pMediaTypeIn, NULL);
		}

		if (SUCCEEDED(hr))
		{
			hr = sinkWriter_->BeginWriting();
		}

		SafeRelease(pMediaTypeOut);
		SafeRelease(pMediaTypeIn);

		if (SUCCEEDED(hr))
		{
			width_ = width;
			height_ = height;
			framerate_ = framerate;
			timestamp_ = 0;
			return true;
		}
		else
		{
			SafeRelease(sinkWriter_);
			streamIndex_ = 0;
			return false;
		}
	}

	bool Write(const std::vector<uint8_t> buffer)
	{
		if (sinkWriter_ == nullptr)
		{
			return false;
		}

		if (buffer.size() != GetBufferSize())
		{
			return false;
		}

		IMFSample* sample = NULL;
		IMFMediaBuffer* videoBuffer = NULL;

		const LONG widthSize = 4 * width_;
		const DWORD bufferSize = widthSize * height_;

		BYTE* internalData = NULL;

		HRESULT hr = MFCreateMemoryBuffer(bufferSize, &videoBuffer);

		if (SUCCEEDED(hr))
		{
			hr = videoBuffer->Lock(&internalData, NULL, NULL);
		}
		if (SUCCEEDED(hr))
		{
			hr = MFCopyImage(
				internalData,
				widthSize,
				(BYTE*)buffer.data(),
				widthSize,
				widthSize,
				height_);
		}
		if (videoBuffer)
		{
			videoBuffer->Unlock();
		}

		if (SUCCEEDED(hr))
		{
			hr = videoBuffer->SetCurrentLength(bufferSize);
		}

		if (SUCCEEDED(hr))
		{
			hr = MFCreateSample(&sample);
		}
		if (SUCCEEDED(hr))
		{
			hr = sample->AddBuffer(videoBuffer);
		}

		if (SUCCEEDED(hr))
		{
			hr = sample->SetSampleTime(timestamp_);
		}
		if (SUCCEEDED(hr))
		{
			hr = sample->SetSampleDuration(10 * 1000 * 1000 / framerate_);
		}

		if (SUCCEEDED(hr))
		{
			hr = sinkWriter_->WriteSample(streamIndex_, sample);
		}

		timestamp_ += 10 * 1000 * 1000 / framerate_;

		SafeRelease(sample);
		SafeRelease(videoBuffer);
		return SUCCEEDED(hr);
	}

	void End()
	{
		if (sinkWriter_ != nullptr)
		{
			sinkWriter_->Finalize();
			SafeRelease(sinkWriter_);
		}
	}

	~VideoWriter()
	{
		End();

		if (isValid_)
		{
			MFShutdown();
			CoUninitialize();
		}
	}
};

bool RecorderCallbackH264::OnBeginRecord()
{
	auto path = std::u16string(recordingParameter_.GetPath()) + std::u16string(recordingParameter_.GetExt());
	videoWriter_ = std::make_shared<VideoWriter>();
	if (!videoWriter_->Start(path, imageSize_.X, imageSize_.Y, (int32_t)(60.0f / (float)recordingParameter_.Freq), recordingParameter_.Count))
	{
		return false;
	}

	buffer_.resize(videoWriter_->GetBufferSize());

	return true;
}

void RecorderCallbackH264::OnEndRecord()
{
	videoWriter_.reset();
}

void RecorderCallbackH264::OnEndFrameRecord(int index, std::vector<Effekseer::Color>& pixels)
{
	for (int y = 0; y < imageSize_.Y; y++)
	{
		for (int x = 0; x < imageSize_.X; x++)
		{
			const auto pixel = pixels[x + y * imageSize_.X];

			auto p = reinterpret_cast<Effekseer::Color*>(buffer_.data());
			auto c = pixels[x + y * imageSize_.X];
			std::swap(c.R, c.B);
			p[x + (imageSize_.Y - 1 - y) * imageSize_.X + 0] = c;
		}
	}

	videoWriter_->Write(buffer_);
}

} // namespace Tool
} // namespace Effekseer<|endoftext|>