<commit_before>/*
 * Copyright (c) 2012 Aldebaran Robotics. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the COPYING file.
 */

#include <boost/filesystem.hpp>
#include <locale>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/timeb.h>

#include <io.h>       //_wopen
#include <windows.h>  //Sleep
#include <winsock2.h>

#include <qi/error.hpp>
#include <qi/os.hpp>
#include <qi/qi.hpp>
#include "src/filesystem.hpp"

namespace qi {
  namespace os {

    // A global time provider is needed, as the performance counter
    // is relative to system start time, which we get only once
    struct TimeStorage {
      bool                   usePerformanceCounter;
      qi::os::timeval        systemStartTime;
      LARGE_INTEGER          systemStartTicks;
      LARGE_INTEGER          systemTicksPerSecond;
    };

    static TimeStorage *gTimeStorage;

    static void init_timer()
    {
      if (gTimeStorage)
        return;
      gTimeStorage = new TimeStorage;

      // get the system clock frequency
      // in theory this never changes, but advanced
      // power saving modes on laptops may change this
      // TODO investigate if this is a problem for us
      int success = QueryPerformanceFrequency( &gTimeStorage->systemTicksPerSecond );
      gTimeStorage->usePerformanceCounter = false;
      // See http://www.nynaeve.net/?p=108 : colorburst crystal: good. Everything else: bad.
      if (success/* && (systemTicksPerSecond.QuadPart == 1193182 || systemTicksPerSecond.QuadPart == 3579545)*/)
      {
        gTimeStorage->usePerformanceCounter = true;

        // Get the system ticks at startup (test using CPU affinity)
        // Thread affinity coped from an MS example
        DWORD_PTR oldmask = SetThreadAffinityMask(GetCurrentThread(), 0);
        QueryPerformanceCounter(&gTimeStorage->systemStartTicks);
        SetThreadAffinityMask(GetCurrentThread(), oldmask);
      }

      // get the start time
      struct _timeb timebuffer;
      _ftime64_s( &timebuffer );

      // store this in a timeval struct
      gTimeStorage->systemStartTime.tv_sec  = (long)timebuffer.time;
      gTimeStorage->systemStartTime.tv_usec = 1000*timebuffer.millitm;
    }

    /**
     * Special Hack for windows using performance counter
     * to give accurate timing, otherwise the accuracy is only +/- 16ms
     * @return Always zero
     */
    int gettimeofday(qi::os::timeval *t)
    {
      if (!gTimeStorage)
        init_timer();
      if (gTimeStorage->usePerformanceCounter) {
        LARGE_INTEGER lCurrentSystemTicks;

        // gets the elapsed ticks since system startup (test using CPU affinity)
        DWORD_PTR oldmask = SetThreadAffinityMask(GetCurrentThread(), 0);
        QueryPerformanceCounter(&lCurrentSystemTicks);
        SetThreadAffinityMask(GetCurrentThread(), oldmask);

        // remove the initial offset
        lCurrentSystemTicks.QuadPart -= gTimeStorage->systemStartTicks.QuadPart;

        // convert to a double number of seconds, using the ticksPerSecond
        double secondsElapsedDouble = ((double)lCurrentSystemTicks.QuadPart) /
          ((double)gTimeStorage->systemTicksPerSecond.QuadPart);

        // convert to the parts needed for the timeval
        long seconds = long(secondsElapsedDouble);
        long microseconds = long((secondsElapsedDouble - seconds) * 1000000);

        // add this offset to system startup time
        t->tv_sec  = gTimeStorage->systemStartTime.tv_sec  + seconds;
        t->tv_usec = gTimeStorage->systemStartTime.tv_usec + microseconds;
      } else {
        // no good performance counter, so revert to old behaviour
        struct _timeb timebuffer;
        _ftime64_s( &timebuffer );

        // store this in a timeval struct
        t->tv_sec=(long)timebuffer.time;
        t->tv_usec=1000*timebuffer.millitm;
      }
      return 0;
    }

    FILE* fopen(const char *filename, const char *mode) {
      try {
        return ::_wfopen(boost::filesystem::path(filename, qi::unicodeFacet()).wstring(qi::unicodeFacet()).c_str(),
                         boost::filesystem::path(mode, qi::unicodeFacet()).wstring(qi::unicodeFacet()).c_str());
      }
      catch (boost::filesystem::filesystem_error &) {
        return 0;
      }
    }

    int stat(const char *pFilename, struct ::stat* pStat) {
      try {
        struct _stat buffer;
        int result = ::_wstat(boost::filesystem::path(pFilename, qi::unicodeFacet()).wstring(qi::unicodeFacet()).c_str(), &buffer);
        pStat->st_gid   = buffer.st_gid;
        pStat->st_atime = buffer.st_atime;
        pStat->st_ctime = buffer.st_ctime;
        pStat->st_dev   = buffer.st_dev;
        pStat->st_ino   = buffer.st_ino;
        pStat->st_mode  = buffer.st_mode;
        pStat->st_mtime = buffer.st_mtime;
        pStat->st_nlink = buffer.st_nlink;
        pStat->st_rdev  = buffer.st_rdev;
        pStat->st_size  = buffer.st_size;
        pStat->st_uid   = buffer.st_uid;
        return result;
      }
      catch (boost::filesystem::filesystem_error &) {
        return -1;
      }
    }

    std::string getenv(const char *var) {
      size_t       bufSize;
      std::wstring wvar = boost::filesystem::path(var, qi::unicodeFacet()).wstring(qi::unicodeFacet());

     #ifdef _MSC_VER
      wchar_t     *envDir = NULL;
      _wdupenv_s(&envDir, &bufSize, wvar.c_str());
      if (envDir == NULL)
        return "";

      boost::filesystem::path dest(envDir, qi::unicodeFacet());
      std::string ret(dest.string(qi::unicodeFacet()).c_str());
      free(envDir);
      return ret;
    #else
      _wgetenv_s(&bufSize, NULL, 0,  wvar.c_str());

      wchar_t *envDir = (wchar_t *) malloc(bufSize * sizeof(wchar_t));
      _wgetenv_s(&bufSize, envDir, bufSize, wvar.c_str());

      if (envDir == NULL)
        return "";

      boost::filesystem::path dest(envDir, qi::unicodeFacet());
      std::string ret(dest.string(qi::unicodeFacet()).c_str());
      free(envDir);
      return ret;
     #endif
    }

    int setenv(const char *var, const char *value) {
      return _wputenv_s(boost::filesystem::path(var, qi::unicodeFacet()).wstring(qi::unicodeFacet()).c_str(),
                        boost::filesystem::path(value, qi::unicodeFacet()).wstring(qi::unicodeFacet()).c_str());
    }

    void sleep(unsigned int seconds) {
      Sleep(seconds * 1000);
    }

    void msleep(unsigned int milliseconds) {
      Sleep(milliseconds);
    }

    std::string home()
    {
      std::string envHome = qi::os::getenv("HOME");
      if (envHome != "")
      {
        return boost::filesystem::path(envHome, qi::unicodeFacet()).make_preferred().string(qi::unicodeFacet());
      }

      // $HOME environment variable not defined:
      std::string envUserProfile = qi::os::getenv("USERPROFILE");
      if (envUserProfile != "")
      {
        return envUserProfile;
      }

      std::string envHomeDrive = qi::os::getenv("HOMEDRIVE");
      std::string envHomePath  = qi::os::getenv("HOMEPATH");

      if (envHomePath == "" || envHomeDrive == "")
      {
        // Give up:
        return "";
      }
      boost::filesystem::path res(envHomeDrive, qi::unicodeFacet());
      res /= envHomePath;
      return res.make_preferred().string(qi::unicodeFacet());
    }

    std::string tmpdir(const char *prefix)
    {
      boost::filesystem::path path;
      path = qi::os::getenv("TMP");

      std::string filename(prefix);
      filename += path.filename().string();
      path = path.parent_path() / filename;

      try
      {
        if (!boost::filesystem::exists(path))
          boost::filesystem::create_directories(path);
      }
      catch (const boost::filesystem::filesystem_error &e)
      {
        throw qi::os::QiException(e.what());
      }

      return path.string(qi::unicodeFacet());
    }
  }
}
<commit_msg>qi.tmpdir: fix for windows (still no random issues)<commit_after>/*
 * Copyright (c) 2012 Aldebaran Robotics. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the COPYING file.
 */

#include <boost/filesystem.hpp>
#include <locale>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/timeb.h>

#include <io.h>       //_wopen
#include <windows.h>  //Sleep
#include <winsock2.h>

#include <qi/error.hpp>
#include <qi/os.hpp>
#include <qi/qi.hpp>
#include "src/filesystem.hpp"

namespace qi {
  namespace os {

    // A global time provider is needed, as the performance counter
    // is relative to system start time, which we get only once
    struct TimeStorage {
      bool                   usePerformanceCounter;
      qi::os::timeval        systemStartTime;
      LARGE_INTEGER          systemStartTicks;
      LARGE_INTEGER          systemTicksPerSecond;
    };

    static TimeStorage *gTimeStorage;

    static void init_timer()
    {
      if (gTimeStorage)
        return;
      gTimeStorage = new TimeStorage;

      // get the system clock frequency
      // in theory this never changes, but advanced
      // power saving modes on laptops may change this
      // TODO investigate if this is a problem for us
      int success = QueryPerformanceFrequency( &gTimeStorage->systemTicksPerSecond );
      gTimeStorage->usePerformanceCounter = false;
      // See http://www.nynaeve.net/?p=108 : colorburst crystal: good. Everything else: bad.
      if (success/* && (systemTicksPerSecond.QuadPart == 1193182 || systemTicksPerSecond.QuadPart == 3579545)*/)
      {
        gTimeStorage->usePerformanceCounter = true;

        // Get the system ticks at startup (test using CPU affinity)
        // Thread affinity coped from an MS example
        DWORD_PTR oldmask = SetThreadAffinityMask(GetCurrentThread(), 0);
        QueryPerformanceCounter(&gTimeStorage->systemStartTicks);
        SetThreadAffinityMask(GetCurrentThread(), oldmask);
      }

      // get the start time
      struct _timeb timebuffer;
      _ftime64_s( &timebuffer );

      // store this in a timeval struct
      gTimeStorage->systemStartTime.tv_sec  = (long)timebuffer.time;
      gTimeStorage->systemStartTime.tv_usec = 1000*timebuffer.millitm;
    }

    /**
     * Special Hack for windows using performance counter
     * to give accurate timing, otherwise the accuracy is only +/- 16ms
     * @return Always zero
     */
    int gettimeofday(qi::os::timeval *t)
    {
      if (!gTimeStorage)
        init_timer();
      if (gTimeStorage->usePerformanceCounter) {
        LARGE_INTEGER lCurrentSystemTicks;

        // gets the elapsed ticks since system startup (test using CPU affinity)
        DWORD_PTR oldmask = SetThreadAffinityMask(GetCurrentThread(), 0);
        QueryPerformanceCounter(&lCurrentSystemTicks);
        SetThreadAffinityMask(GetCurrentThread(), oldmask);

        // remove the initial offset
        lCurrentSystemTicks.QuadPart -= gTimeStorage->systemStartTicks.QuadPart;

        // convert to a double number of seconds, using the ticksPerSecond
        double secondsElapsedDouble = ((double)lCurrentSystemTicks.QuadPart) /
          ((double)gTimeStorage->systemTicksPerSecond.QuadPart);

        // convert to the parts needed for the timeval
        long seconds = long(secondsElapsedDouble);
        long microseconds = long((secondsElapsedDouble - seconds) * 1000000);

        // add this offset to system startup time
        t->tv_sec  = gTimeStorage->systemStartTime.tv_sec  + seconds;
        t->tv_usec = gTimeStorage->systemStartTime.tv_usec + microseconds;
      } else {
        // no good performance counter, so revert to old behaviour
        struct _timeb timebuffer;
        _ftime64_s( &timebuffer );

        // store this in a timeval struct
        t->tv_sec=(long)timebuffer.time;
        t->tv_usec=1000*timebuffer.millitm;
      }
      return 0;
    }

    FILE* fopen(const char *filename, const char *mode) {
      try {
        return ::_wfopen(boost::filesystem::path(filename, qi::unicodeFacet()).wstring(qi::unicodeFacet()).c_str(),
                         boost::filesystem::path(mode, qi::unicodeFacet()).wstring(qi::unicodeFacet()).c_str());
      }
      catch (boost::filesystem::filesystem_error &) {
        return 0;
      }
    }

    int stat(const char *pFilename, struct ::stat* pStat) {
      try {
        struct _stat buffer;
        int result = ::_wstat(boost::filesystem::path(pFilename, qi::unicodeFacet()).wstring(qi::unicodeFacet()).c_str(), &buffer);
        pStat->st_gid   = buffer.st_gid;
        pStat->st_atime = buffer.st_atime;
        pStat->st_ctime = buffer.st_ctime;
        pStat->st_dev   = buffer.st_dev;
        pStat->st_ino   = buffer.st_ino;
        pStat->st_mode  = buffer.st_mode;
        pStat->st_mtime = buffer.st_mtime;
        pStat->st_nlink = buffer.st_nlink;
        pStat->st_rdev  = buffer.st_rdev;
        pStat->st_size  = buffer.st_size;
        pStat->st_uid   = buffer.st_uid;
        return result;
      }
      catch (boost::filesystem::filesystem_error &) {
        return -1;
      }
    }

    std::string getenv(const char *var) {
      size_t       bufSize;
      std::wstring wvar = boost::filesystem::path(var, qi::unicodeFacet()).wstring(qi::unicodeFacet());

     #ifdef _MSC_VER
      wchar_t     *envDir = NULL;
      _wdupenv_s(&envDir, &bufSize, wvar.c_str());
      if (envDir == NULL)
        return "";

      boost::filesystem::path dest(envDir, qi::unicodeFacet());
      std::string ret(dest.string(qi::unicodeFacet()).c_str());
      free(envDir);
      return ret;
    #else
      _wgetenv_s(&bufSize, NULL, 0,  wvar.c_str());

      wchar_t *envDir = (wchar_t *) malloc(bufSize * sizeof(wchar_t));
      _wgetenv_s(&bufSize, envDir, bufSize, wvar.c_str());

      if (envDir == NULL)
        return "";

      boost::filesystem::path dest(envDir, qi::unicodeFacet());
      std::string ret(dest.string(qi::unicodeFacet()).c_str());
      free(envDir);
      return ret;
     #endif
    }

    int setenv(const char *var, const char *value) {
      return _wputenv_s(boost::filesystem::path(var, qi::unicodeFacet()).wstring(qi::unicodeFacet()).c_str(),
                        boost::filesystem::path(value, qi::unicodeFacet()).wstring(qi::unicodeFacet()).c_str());
    }

    void sleep(unsigned int seconds) {
      Sleep(seconds * 1000);
    }

    void msleep(unsigned int milliseconds) {
      Sleep(milliseconds);
    }

    std::string home()
    {
      std::string envHome = qi::os::getenv("HOME");
      if (envHome != "")
      {
        return boost::filesystem::path(envHome, qi::unicodeFacet()).make_preferred().string(qi::unicodeFacet());
      }

      // $HOME environment variable not defined:
      std::string envUserProfile = qi::os::getenv("USERPROFILE");
      if (envUserProfile != "")
      {
        return envUserProfile;
      }

      std::string envHomeDrive = qi::os::getenv("HOMEDRIVE");
      std::string envHomePath  = qi::os::getenv("HOMEPATH");

      if (envHomePath == "" || envHomeDrive == "")
      {
        // Give up:
        return "";
      }
      boost::filesystem::path res(envHomeDrive, qi::unicodeFacet());
      res /= envHomePath;
      return res.make_preferred().string(qi::unicodeFacet());
    }

    std::string tmpdir(const char *prefix)
    {
      boost::filesystem::path path;
      path = qi::os::getenv("TMP");

      std::string filename(prefix);
      path.append(filename, qi::unicodeFacet());

      try
      {
        if (!boost::filesystem::exists(path))
          boost::filesystem::create_directories(path);
      }
      catch (const boost::filesystem::filesystem_error &e)
      {
        throw qi::os::QiException(e.what());
      }

      return path.string(qi::unicodeFacet());
    }
  }
}
<|endoftext|>


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

#include "WrappedProperty.hxx"

#include <vector>

//.............................................................................
namespace chart
{
namespace wrapper
{

class ReferenceSizePropertyProvider;

class WrappedCharacterHeightProperty_Base : public WrappedProperty
{
public:
    WrappedCharacterHeightProperty_Base( const ::rtl::OUString& rOuterEqualsInnerName, ReferenceSizePropertyProvider* pRefSizePropProvider );
    virtual ~WrappedCharacterHeightProperty_Base();

    virtual void setPropertyValue( const ::com::sun::star::uno::Any& rOuterValue, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& xInnerPropertySet ) const
                        throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);

    virtual ::com::sun::star::uno::Any getPropertyValue( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& xInnerPropertySet ) const
                        throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);

    virtual ::com::sun::star::uno::Any getPropertyDefault( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyState >& xInnerPropertyState ) const
                        throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);

    virtual ::com::sun::star::beans::PropertyState getPropertyState( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyState >& xInnerPropertyState ) const
                        throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException);

protected:
    virtual ::com::sun::star::uno::Any convertInnerToOuterValue( const ::com::sun::star::uno::Any& rInnerValue ) const;
    virtual ::com::sun::star::uno::Any convertOuterToInnerValue( const ::com::sun::star::uno::Any& rOuterValue ) const;

protected:
    ReferenceSizePropertyProvider*  m_pRefSizePropProvider;
};

//-----------------------------------------------------------------------------

class WrappedCharacterHeightProperty : public WrappedCharacterHeightProperty_Base
{
public:
    WrappedCharacterHeightProperty( ReferenceSizePropertyProvider* pRefSizePropProvider );
    virtual ~WrappedCharacterHeightProperty();

    static void addWrappedProperties( std::vector< WrappedProperty* >& rList, ReferenceSizePropertyProvider* pRefSizePropProvider );
};

//-----------------------------------------------------------------------------

class WrappedAsianCharacterHeightProperty : public WrappedCharacterHeightProperty_Base
{
public:
    WrappedAsianCharacterHeightProperty( ReferenceSizePropertyProvider* pRefSizePropProvider );
    virtual ~WrappedAsianCharacterHeightProperty();
};

//-----------------------------------------------------------------------------

class WrappedComplexCharacterHeightProperty : public WrappedCharacterHeightProperty_Base
{
public:
    WrappedComplexCharacterHeightProperty( ReferenceSizePropertyProvider* pRefSizePropProvider );
    virtual ~WrappedComplexCharacterHeightProperty();
};

} //namespace wrapper
} //namespace chart
//.............................................................................

// CHART_WRAPPED_CHARACTERHEIGHT_PROPERTY_HXX
#endif
<commit_msg>INTEGRATION: CWS changefileheader (1.2.126); FILE MERGED 2008/03/28 16:43:16 rt 1.2.126.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: WrappedCharacterHeightProperty.hxx,v $
 * $Revision: 1.3 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef CHART_WRAPPED_CHARACTERHEIGHT_PROPERTY_HXX
#define CHART_WRAPPED_CHARACTERHEIGHT_PROPERTY_HXX

#include "WrappedProperty.hxx"

#include <vector>

//.............................................................................
namespace chart
{
namespace wrapper
{

class ReferenceSizePropertyProvider;

class WrappedCharacterHeightProperty_Base : public WrappedProperty
{
public:
    WrappedCharacterHeightProperty_Base( const ::rtl::OUString& rOuterEqualsInnerName, ReferenceSizePropertyProvider* pRefSizePropProvider );
    virtual ~WrappedCharacterHeightProperty_Base();

    virtual void setPropertyValue( const ::com::sun::star::uno::Any& rOuterValue, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& xInnerPropertySet ) const
                        throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);

    virtual ::com::sun::star::uno::Any getPropertyValue( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& xInnerPropertySet ) const
                        throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);

    virtual ::com::sun::star::uno::Any getPropertyDefault( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyState >& xInnerPropertyState ) const
                        throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);

    virtual ::com::sun::star::beans::PropertyState getPropertyState( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyState >& xInnerPropertyState ) const
                        throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException);

protected:
    virtual ::com::sun::star::uno::Any convertInnerToOuterValue( const ::com::sun::star::uno::Any& rInnerValue ) const;
    virtual ::com::sun::star::uno::Any convertOuterToInnerValue( const ::com::sun::star::uno::Any& rOuterValue ) const;

protected:
    ReferenceSizePropertyProvider*  m_pRefSizePropProvider;
};

//-----------------------------------------------------------------------------

class WrappedCharacterHeightProperty : public WrappedCharacterHeightProperty_Base
{
public:
    WrappedCharacterHeightProperty( ReferenceSizePropertyProvider* pRefSizePropProvider );
    virtual ~WrappedCharacterHeightProperty();

    static void addWrappedProperties( std::vector< WrappedProperty* >& rList, ReferenceSizePropertyProvider* pRefSizePropProvider );
};

//-----------------------------------------------------------------------------

class WrappedAsianCharacterHeightProperty : public WrappedCharacterHeightProperty_Base
{
public:
    WrappedAsianCharacterHeightProperty( ReferenceSizePropertyProvider* pRefSizePropProvider );
    virtual ~WrappedAsianCharacterHeightProperty();
};

//-----------------------------------------------------------------------------

class WrappedComplexCharacterHeightProperty : public WrappedCharacterHeightProperty_Base
{
public:
    WrappedComplexCharacterHeightProperty( ReferenceSizePropertyProvider* pRefSizePropProvider );
    virtual ~WrappedComplexCharacterHeightProperty();
};

} //namespace wrapper
} //namespace chart
//.............................................................................

// CHART_WRAPPED_CHARACTERHEIGHT_PROPERTY_HXX
#endif
<|endoftext|>


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

#include <SNR.hpp>

namespace PulsarSearch {

snrDedispersedConf::snrDedispersedConf() {}

snrDedispersedConf::~snrDedispersedConf() {}

std::string snrDedispersedConf::print() const {
  return isa::utils::toString(nrSamplesPerBlock) + " " + isa::utils::toString(nrSamplesPerThread);
}
std::string * getSNRDedispersedOpenCL(const snrDedispersedConf & conf, const std::string & dataType, const AstroData::Observation & observation) {
  std::string * code = new std::string();

  // Begin kernel's template
  *code = "__kernel void snrDedispersed(__global const " + dataType + " * const restrict dedispersedData, __global float * const restrict snrData) {\n"
    "unsigned int dm = get_group_id(1);\n"
    "__local float reductionCOU[" + isa::utils::toString(isa::utils::pad(conf.getNrSamplesPerBlock(), observation.getPadding())) + "];\n"
    "__local " + dataType + " reductionMAX[" + isa::utils::toString(isa::utils::pad(conf.getNrSamplesPerBlock(), observation.getPadding())) + "];\n"
    "__local float reductionMEA[" + isa::utils::toString(isa::utils::pad(conf.getNrSamplesPerBlock(), observation.getPadding())) + "];\n"
    "__local float reductionVAR[" + isa::utils::toString(isa::utils::pad(conf.getNrSamplesPerBlock(), observation.getPadding())) + "];\n"
    "<%DEF%>"
    "\n"
    "// Compute phase\n"
    "for ( unsigned int sample = get_local_id(0) + " + isa::utils::toString(conf.getNrSamplesPerBlock() * conf.getNrSamplesPerThread()) + "; sample < " + isa::utils::toString(observation.getNrSamplesPerSecond()) + "; sample += " + isa::utils::toString(conf.getNrSamplesPerBlock() * conf.getNrSamplesPerThread()) + " ) {\n"
    + dataType + " item = 0;\n"
    "float delta = 0.0f;\n"
    "<%COMPUTE%>"
    "}\n"
    "// In-thread reduce\n"
    "// Local memory store\n"
    "reductionCOU[get_local_id(0)] = counter;\n"
    "reductionMAX[get_local_id(0)] = max;\n"
    "reductionMEA[get_local_id(0)] = mean;\n"
    "reductionVAR[get_local_id(0)] = variance;\n"
    "barrier(CLK_LOCAL_MEM_FENCE);\n"
    "// Reduce phase\n"
    "unsigned int threshold = " + isa::utils::toString(conf.getNrSamplesPerBlock() / 2) + ";\n"
    "for ( sample = get_local_id(0); threshold > 0; threshold /= 2 ) {\n"
    "if ( sample < threshold ) {\n"
    "float delta = reductionMEA[sample + threshold] - mean;\n"
    "counter += reductionCOU[sample + threshold];\n"
    "max = fmax(max, reductionMAX[sample + threshold]);\n"
    "mean = ((reductionCOU[sample] * mean) + (reductionCOU[sample + threshold] * reductionMEA[sample + threshold])) / counter;\n"
    "variance += reductionVAR[sample + threshold] + ((delta * delta) * ((reductionCOU[sample] * reductionCOU[sample + threshold]) / counter));\n"
    "reductionCOU[get_local_id(0)] = counter;\n"
    "reductionMAX[get_local_id(0)] = max;\n"
    "reductionMEA[get_local_id(0)] = mean;\n"
    "reductionVAR[get_local_id(0)] = variance;\n"
    "}\n"
    "barrier(CLK_LOCAL_MEM_FENCE);\n"
    "}\n"
    "// Store\n"
    "if ( get_local_id(0) == 0 ) {\n"
    "snrData[dm] = (max - mean) / native_sqrt(variance / (counter - 1));\n"
    "}\n"
    "}\n";
  std::string defTemplate = "float counter<%NUM%> = 1.0f;\n"
    + dataType + " max<%NUM%> = dedispersedData[(dm * " + isa::utils::toString(observation.getNrSamplesPerPaddedSecond()) + ") + (get_local_id(0) + <%OFFSET%>)];\n"
    "float variance<%NUM%> = 0.0f;\n"
    "float mean<%NUM%> = max;\n";
  std::string computeTemplate = "item = dedispersedData[(dm * " + isa::utils::toString(observation.getNrSamplesPerPaddedSecond()) + ") + (sample + <%OFFSET%>)];\n"
    "counter<%NUM%> += 1.0f;\n"
    "delta = item - mean<%NUM%>;\n"
    "max<%NUM%> = fmax(max<%NUM%>, item);\n"
    "mean<%NUM%> += delta / counter<%NUM%>;\n"
    "variance<%NUM%> += delta * (item - mean<%NUM%>);\n";
  // End kernel's template

  std::string * def_s = new std::string();
  std::string * compute_s = new std::string();

  for ( unsigned int sample = 0; sample < conf.getNrSamplesPerThread(); sample++ ) {
    std::string sample_s = isa::utils::toString(sample);
    std::string offset_s = isa::utils::toString(conf.getNrSamplesPerBlock() * sample);
    std::string * temp = 0;

    temp = isa::utils::replace(&defTemplate, "<%NUM%>", sample_s);
    if ( sample == 0 ) {
      std::string empty_s("");
      temp = isa::utils::replace(temp, " + <%OFFSET%>", empty_s, true);
    } else {
      temp = isa::utils::replace(temp, "<%OFFSET%>", offset_s, true);
    }
    def_s->append(*temp);
    delete temp;
    temp = isa::utils::replace(&computeTemplate, "<%NUM%>", sample_s);
    if ( sample == 0 ) {
      std::string empty_s("");
      temp = isa::utils::replace(temp, " + <%OFFSET%>", empty_s, true);
    } else {
      temp = isa::utils::replace(temp, "<%OFFSET%>", offset_s, true);
    }
    compute_s->append(*temp);
    delete temp;
  }

  code = isa::utils::replace(code, "<%DEF%>", *def_s, true);
  code = isa::utils::replace(code, "<%COMPUTE%>", *compute_s, true);
  delete def_s;
  delete compute_s;

  return code;
}

void readTunedSNRDedispersedConf(tunedSNRDedispersedConf & tunedSNR, const std::string & snrFilename) {
  std::string temp;
  std::ifstream snrFile(snrFilename);
  while ( ! snrFile.eof() ) {
    unsigned int splitPoint = 0;
    std::getline(snrFile, temp);
    if ( ! std::isalpha(temp[0]) ) {
      continue;
    }
    std::string deviceName;
    unsigned int nrDMs = 0;
    PulsarSearch::snrDedispersedConf parameters;
    splitPoint = temp.find(" ");
    deviceName = temp.substr(0, splitPoint);
    temp = temp.substr(splitPoint + 1);
    splitPoint = temp.find(" ");
    nrDMs = isa::utils::castToType< std::string, unsigned int >(temp.substr(0, splitPoint));
    temp = temp.substr(splitPoint + 1);
    splitPoint = temp.find(" ");
    parameters.setNrSamplesPerBlock(isa::utils::castToType< std::string, unsigned int >(temp.substr(0, splitPoint)));
    temp = temp.substr(splitPoint + 1);
    splitPoint = temp.find(" ");
    parameters.setNrSamplesPerThread(isa::utils::castToType< std::string, unsigned int >(temp.substr(0, splitPoint)));
    if ( tunedSNR.count(deviceName) == 0 ) {
      std::map< unsigned int, PulsarSearch::snrDedispersedConf > container;
      container.insert(std::make_pair(nrDMs, parameters));
      tunedSNR.insert(std::make_pair(deviceName, container));
    } else {
      tunedSNR[deviceName].insert(std::make_pair(nrDMs, parameters));
    }
  }
}

} // PulsarSearch

<commit_msg>More fixes in the OpenCL code.<commit_after>// Copyright 2015 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <SNR.hpp>

namespace PulsarSearch {

snrDedispersedConf::snrDedispersedConf() {}

snrDedispersedConf::~snrDedispersedConf() {}

std::string snrDedispersedConf::print() const {
  return isa::utils::toString(nrSamplesPerBlock) + " " + isa::utils::toString(nrSamplesPerThread);
}
std::string * getSNRDedispersedOpenCL(const snrDedispersedConf & conf, const std::string & dataType, const AstroData::Observation & observation) {
  std::string * code = new std::string();

  // Begin kernel's template
  *code = "__kernel void snrDedispersed(__global const " + dataType + " * const restrict dedispersedData, __global float * const restrict snrData) {\n"
    "unsigned int dm = get_group_id(1);\n"
    "__local float reductionCOU[" + isa::utils::toString(isa::utils::pad(conf.getNrSamplesPerBlock(), observation.getPadding())) + "];\n"
    "__local " + dataType + " reductionMAX[" + isa::utils::toString(isa::utils::pad(conf.getNrSamplesPerBlock(), observation.getPadding())) + "];\n"
    "__local float reductionMEA[" + isa::utils::toString(isa::utils::pad(conf.getNrSamplesPerBlock(), observation.getPadding())) + "];\n"
    "__local float reductionVAR[" + isa::utils::toString(isa::utils::pad(conf.getNrSamplesPerBlock(), observation.getPadding())) + "];\n"
    "<%DEF%>"
    "\n"
    "// Compute phase\n"
    "for ( unsigned int sample = get_local_id(0) + " + isa::utils::toString(conf.getNrSamplesPerBlock() * conf.getNrSamplesPerThread()) + "; sample < " + isa::utils::toString(observation.getNrSamplesPerSecond()) + "; sample += " + isa::utils::toString(conf.getNrSamplesPerBlock() * conf.getNrSamplesPerThread()) + " ) {\n"
    + dataType + " item = 0;\n"
    "float delta = 0.0f;\n"
    "<%COMPUTE%>"
    "}\n"
    "// In-thread reduce\n"
    "// Local memory store\n"
    "reductionCOU[get_local_id(0)] = counter;\n"
    "reductionMAX[get_local_id(0)] = max;\n"
    "reductionMEA[get_local_id(0)] = mean;\n"
    "reductionVAR[get_local_id(0)] = variance;\n"
    "barrier(CLK_LOCAL_MEM_FENCE);\n"
    "// Reduce phase\n"
    "unsigned int threshold = " + isa::utils::toString(conf.getNrSamplesPerBlock() / 2) + ";\n"
    "for ( unsigned int sample = get_local_id(0); threshold > 0; threshold /= 2 ) {\n"
    "if ( sample < threshold ) {\n"
    "float delta = reductionMEA[sample + threshold] - mean0;\n"
    "counter0 += reductionCOU[sample + threshold];\n"
    "max0 = fmax(max0, reductionMAX[sample + threshold]);\n"
    "mean0 = ((reductionCOU[sample] * mean0) + (reductionCOU[sample + threshold] * reductionMEA[sample + threshold])) / counter0;\n"
    "variance0 += reductionVAR[sample + threshold] + ((delta * delta) * ((reductionCOU[sample] * reductionCOU[sample + threshold]) / counter0));\n"
    "reductionCOU[get_local_id(0)] = counter0;\n"
    "reductionMAX[get_local_id(0)] = max0;\n"
    "reductionMEA[get_local_id(0)] = mean0;\n"
    "reductionVAR[get_local_id(0)] = variance0;\n"
    "}\n"
    "barrier(CLK_LOCAL_MEM_FENCE);\n"
    "}\n"
    "// Store\n"
    "if ( get_local_id(0) == 0 ) {\n"
    "snrData[dm] = (max0 - mean0) / native_sqrt(variance0 * " + isa::utils::toString(1.0f / (observation.getNrSamplesPerSecond() - 1)) + "f);\n"
    "}\n"
    "}\n";
  std::string defTemplate = "float counter<%NUM%> = 1.0f;\n"
    + dataType + " max<%NUM%> = dedispersedData[(dm * " + isa::utils::toString(observation.getNrSamplesPerPaddedSecond()) + ") + (get_local_id(0) + <%OFFSET%>)];\n"
    "float variance<%NUM%> = 0.0f;\n"
    "float mean<%NUM%> = max;\n";
  std::string computeTemplate = "item = dedispersedData[(dm * " + isa::utils::toString(observation.getNrSamplesPerPaddedSecond()) + ") + (sample + <%OFFSET%>)];\n"
    "counter<%NUM%> += 1.0f;\n"
    "delta = item - mean<%NUM%>;\n"
    "max<%NUM%> = fmax(max<%NUM%>, item);\n"
    "mean<%NUM%> += delta / counter<%NUM%>;\n"
    "variance<%NUM%> += delta * (item - mean<%NUM%>);\n";
  // End kernel's template

  std::string * def_s = new std::string();
  std::string * compute_s = new std::string();

  for ( unsigned int sample = 0; sample < conf.getNrSamplesPerThread(); sample++ ) {
    std::string sample_s = isa::utils::toString(sample);
    std::string offset_s = isa::utils::toString(conf.getNrSamplesPerBlock() * sample);
    std::string * temp = 0;

    temp = isa::utils::replace(&defTemplate, "<%NUM%>", sample_s);
    if ( sample == 0 ) {
      std::string empty_s("");
      temp = isa::utils::replace(temp, " + <%OFFSET%>", empty_s, true);
    } else {
      temp = isa::utils::replace(temp, "<%OFFSET%>", offset_s, true);
    }
    def_s->append(*temp);
    delete temp;
    temp = isa::utils::replace(&computeTemplate, "<%NUM%>", sample_s);
    if ( sample == 0 ) {
      std::string empty_s("");
      temp = isa::utils::replace(temp, " + <%OFFSET%>", empty_s, true);
    } else {
      temp = isa::utils::replace(temp, "<%OFFSET%>", offset_s, true);
    }
    compute_s->append(*temp);
    delete temp;
  }

  code = isa::utils::replace(code, "<%DEF%>", *def_s, true);
  code = isa::utils::replace(code, "<%COMPUTE%>", *compute_s, true);
  delete def_s;
  delete compute_s;

  return code;
}

void readTunedSNRDedispersedConf(tunedSNRDedispersedConf & tunedSNR, const std::string & snrFilename) {
  std::string temp;
  std::ifstream snrFile(snrFilename);
  while ( ! snrFile.eof() ) {
    unsigned int splitPoint = 0;
    std::getline(snrFile, temp);
    if ( ! std::isalpha(temp[0]) ) {
      continue;
    }
    std::string deviceName;
    unsigned int nrDMs = 0;
    PulsarSearch::snrDedispersedConf parameters;
    splitPoint = temp.find(" ");
    deviceName = temp.substr(0, splitPoint);
    temp = temp.substr(splitPoint + 1);
    splitPoint = temp.find(" ");
    nrDMs = isa::utils::castToType< std::string, unsigned int >(temp.substr(0, splitPoint));
    temp = temp.substr(splitPoint + 1);
    splitPoint = temp.find(" ");
    parameters.setNrSamplesPerBlock(isa::utils::castToType< std::string, unsigned int >(temp.substr(0, splitPoint)));
    temp = temp.substr(splitPoint + 1);
    splitPoint = temp.find(" ");
    parameters.setNrSamplesPerThread(isa::utils::castToType< std::string, unsigned int >(temp.substr(0, splitPoint)));
    if ( tunedSNR.count(deviceName) == 0 ) {
      std::map< unsigned int, PulsarSearch::snrDedispersedConf > container;
      container.insert(std::make_pair(nrDMs, parameters));
      tunedSNR.insert(std::make_pair(deviceName, container));
    } else {
      tunedSNR[deviceName].insert(std::make_pair(nrDMs, parameters));
    }
  }
}

} // PulsarSearch

<|endoftext|>


<commit_before>#include "pomerol/TwoParticleGFPart.h"

#include <cstddef>
#include <mutex>

std::mutex NonResonantTerm_mpi_datatype_mutex;
std::mutex ResonantTerm_mpi_datatype_mutex;

namespace Pomerol{

// Make the lagging index catch up or outrun the leading index.
inline bool chaseIndices(RowMajorMatrixType::InnerIterator& index1_iter,
                         ColMajorMatrixType::InnerIterator& index2_iter)
{
    InnerQuantumState index1 = index1_iter.index();
    InnerQuantumState index2 = index2_iter.index();

    if(index1 == index2) return true;

    if(index1 < index2)
        for(;InnerQuantumState(index1_iter.index())<index2 && index1_iter; ++index1_iter);
    else
        for(;InnerQuantumState(index2_iter.index())<index1 && index2_iter; ++index2_iter);

    return false;
}

//
// TwoParticleGFPart::NonResonantTerm
//
TwoParticleGFPart::NonResonantTerm& TwoParticleGFPart::NonResonantTerm::operator+=(
                    const NonResonantTerm& AnotherTerm)
{
    long combinedWeight=Weight + AnotherTerm.Weight;
    for (unsigned short p=0; p<3; ++p) Poles[p]= (Weight*Poles[p] + AnotherTerm.Weight*AnotherTerm.Poles[p])/combinedWeight;
    Weight=combinedWeight;
    Coeff += AnotherTerm.Coeff;
    return *this;
}

MPI_Datatype TwoParticleGFPart::NonResonantTerm::mpi_datatype() {
    static MPI_Datatype dt;

    // Since we are using static variables here, we have to make sure the code
    // is thread-safe.
    const std::lock_guard<std::mutex> lock(NonResonantTerm_mpi_datatype_mutex);

    // Create and commit datatype only once
    static bool type_committed = false;
    if(!type_committed) {
        int blocklengths[] = {1,3,1,1};
        MPI_Aint displacements[] = {offsetof(NonResonantTerm, Coeff),
                                    offsetof(NonResonantTerm, Poles),
                                    offsetof(NonResonantTerm, isz4),
                                    offsetof(NonResonantTerm, Weight)
                                   };
        MPI_Datatype types[] = {MPI_CXX_DOUBLE_COMPLEX, // ComplexType Coeff
                                MPI_DOUBLE,             // RealType Poles[3]
                                MPI_CXX_BOOL,           // bool isz4
                                MPI_LONG                // long Weight
                               };
        MPI_Type_create_struct(4, blocklengths, displacements, types, &dt);
        MPI_Type_commit(&dt);
        type_committed = true;
    }
    return dt;
}

//
// TwoParticleGFPart::ResonantTerm
//
TwoParticleGFPart::ResonantTerm& TwoParticleGFPart::ResonantTerm::operator+=(
                const ResonantTerm& AnotherTerm)
{
    long combinedWeight=Weight + AnotherTerm.Weight;
    for (unsigned short p=0; p<3; ++p) Poles[p]= (Weight*Poles[p] + AnotherTerm.Weight*AnotherTerm.Poles[p])/combinedWeight;
    Weight=combinedWeight;
    ResCoeff += AnotherTerm.ResCoeff;
    NonResCoeff += AnotherTerm.NonResCoeff;
    return *this;
}

MPI_Datatype TwoParticleGFPart::ResonantTerm::mpi_datatype() {
    static MPI_Datatype dt;

    // Since we are using static variables here, we have to make sure the code
    // is thread-safe.
    const std::lock_guard<std::mutex> lock(ResonantTerm_mpi_datatype_mutex);

    // Create and commit datatype only once
    static bool type_committed = false;
    if(!type_committed) {
        int blocklengths[] = {1,1,3,1,1};
        MPI_Aint displacements[] = {offsetof(ResonantTerm, ResCoeff),
                                    offsetof(ResonantTerm, NonResCoeff),
                                    offsetof(ResonantTerm, Poles),
                                    offsetof(ResonantTerm, isz1z2),
                                    offsetof(ResonantTerm, Weight)
                                   };
        MPI_Datatype types[] = {MPI_CXX_DOUBLE_COMPLEX, // ComplexType ResCoeff
                                MPI_CXX_DOUBLE_COMPLEX, // ComplexType NonResCoeff
                                MPI_DOUBLE,             // RealType Poles[3]
                                MPI_CXX_BOOL,           // bool isz1z2
                                MPI_LONG                // long Weight
                               };
        MPI_Type_create_struct(5, blocklengths, displacements, types, &dt);
        MPI_Type_commit(&dt);
        type_committed = true;
    }
    return dt;
}

//
// TwoParticleGFPart
//
TwoParticleGFPart::TwoParticleGFPart(
                const FieldOperatorPart& O1, const FieldOperatorPart& O2,
                const FieldOperatorPart& O3, const CreationOperatorPart& CX4,
                const HamiltonianPart& Hpart1, const HamiltonianPart& Hpart2,
                const HamiltonianPart& Hpart3, const HamiltonianPart& Hpart4,
                const DensityMatrixPart& DMpart1, const DensityMatrixPart& DMpart2,
                const DensityMatrixPart& DMpart3, const DensityMatrixPart& DMpart4,
                Permutation3 Permutation) :
    Thermal(DMpart1),
    ComputableObject(),
    NonResonantTerms(NonResonantTerm::Compare(1e-8), NonResonantTerm::IsNegligible(1e-16)),
    ResonantTerms(ResonantTerm::Compare(1e-8), ResonantTerm::IsNegligible(1e-16)),
    O1(O1), O2(O2), O3(O3), CX4(CX4),
    Hpart1(Hpart1), Hpart2(Hpart2), Hpart3(Hpart3), Hpart4(Hpart4),
    DMpart1(DMpart1), DMpart2(DMpart2), DMpart3(DMpart3), DMpart4(DMpart4),
    Permutation(Permutation),
    ReduceResonanceTolerance(1e-8),
    CoefficientTolerance (1e-16),
    MultiTermCoefficientTolerance (1e-5)
{}

void TwoParticleGFPart::compute()
{
    NonResonantTerms.clear();
    ResonantTerms.clear();

    RealType beta = DMpart1.beta;
    // I don't have any pen now, so I'm writing here:
    // <1 | O1 | 2> <2 | O2 | 3> <3 | O3 |4> <4| CX4 |1>
    // Iterate over all values of |1><1| and |3><3|
    // Chase indices |2> and <2|, |4> and <4|.
    const RowMajorMatrixType& O1matrix = O1.getRowMajorValue();
    const ColMajorMatrixType& O2matrix = O2.getColMajorValue();
    const RowMajorMatrixType& O3matrix = O3.getRowMajorValue();
    const ColMajorMatrixType& CX4matrix = CX4.getColMajorValue();

    InnerQuantumState index1;
    InnerQuantumState index1Max = CX4matrix.outerSize(); // One can not make a cutoff in external index for evaluating 2PGF

    InnerQuantumState index3;
    InnerQuantumState index3Max = O2matrix.outerSize();

    std::vector<InnerQuantumState> Index4List;
    Index4List.reserve(index1Max*index3Max);

    for(index1=0; index1<index1Max; ++index1)
    for(index3=0; index3<index3Max; ++index3){
        ColMajorMatrixType::InnerIterator index4bra_iter(CX4matrix,index1);
        RowMajorMatrixType::InnerIterator index4ket_iter(O3matrix,index3);
        Index4List.clear();
        while (index4bra_iter && index4ket_iter){
            if(chaseIndices(index4ket_iter,index4bra_iter)){
                Index4List.push_back(index4bra_iter.index());
                ++index4bra_iter;
                ++index4ket_iter;
            }
        };

        if (!Index4List.empty())
        {
            RealType E1 = Hpart1.getEigenValue(index1);
            RealType E3 = Hpart3.getEigenValue(index3);
            RealType weight1 = DMpart1.getWeight(index1);
            RealType weight3 = DMpart3.getWeight(index3);

            ColMajorMatrixType::InnerIterator index2bra_iter(O2matrix,index3);
            RowMajorMatrixType::InnerIterator index2ket_iter(O1matrix,index1);
            while (index2bra_iter && index2ket_iter){
                if (chaseIndices(index2ket_iter,index2bra_iter)){

                    InnerQuantumState index2 = index2ket_iter.index();
                    RealType E2 = Hpart2.getEigenValue(index2);
                    RealType weight2 = DMpart2.getWeight(index2);

                    for (unsigned long p4 = 0; p4 < Index4List.size(); ++p4)
                    {
                        InnerQuantumState index4 = Index4List[p4];//*pIndex4;
                        RealType E4 = Hpart4.getEigenValue(index4);
                        RealType weight4 = DMpart4.getWeight(index4);
                        if (weight1 + weight2 + weight3 + weight4 >= CoefficientTolerance) {
                            ComplexType MatrixElement = index2ket_iter.value()*
                                                        index2bra_iter.value()*
                                                        O3matrix.coeff(index3,index4)*
                                                        CX4matrix.coeff(index4,index1);

                            MatrixElement *= Permutation.sign;

                            addMultiterm(MatrixElement,beta,E1,E2,E3,E4,weight1,weight2,weight3,weight4);
                        }
                    }
                    ++index2bra_iter;
                    ++index2ket_iter;
                };
            }
        };
    }

    std::cout << "Total " << NonResonantTerms.size() << "+" << ResonantTerms.size() << "="
              << NonResonantTerms.size() + ResonantTerms.size() << " terms" << std::endl << std::flush;

    assert(NonResonantTerms.check_terms());
    assert(ResonantTerms.check_terms());

    Status = Computed;
}

inline
void TwoParticleGFPart::addMultiterm(ComplexType Coeff, RealType beta,
                      RealType Ei, RealType Ej, RealType Ek, RealType El,
                      RealType Wi, RealType Wj, RealType Wk, RealType Wl)
{
    RealType P1 = Ej - Ei;
    RealType P2 = Ek - Ej;
    RealType P3 = El - Ek;

    // Non-resonant part of the multiterm
    ComplexType CoeffZ2 = -Coeff*(Wj + Wk);
    if(abs(CoeffZ2) > CoefficientTolerance)
        NonResonantTerms.add_term(
            NonResonantTerm(CoeffZ2,P1,P2,P3,false));
    ComplexType CoeffZ4 = Coeff*(Wi + Wl);
    if(abs(CoeffZ4) > CoefficientTolerance)
        NonResonantTerms.add_term(
            NonResonantTerm(CoeffZ4,P1,P2,P3,true));

    // Resonant part of the multiterm
    ComplexType CoeffZ1Z2Res = Coeff*beta*Wi;
    ComplexType CoeffZ1Z2NonRes = Coeff*(Wk - Wi);
    if(abs(CoeffZ1Z2Res) > CoefficientTolerance || abs(CoeffZ1Z2NonRes) > CoefficientTolerance)
        ResonantTerms.add_term(
            ResonantTerm(CoeffZ1Z2Res,CoeffZ1Z2NonRes,P1,P2,P3,true));
    ComplexType CoeffZ2Z3Res = -Coeff*beta*Wj;
    ComplexType CoeffZ2Z3NonRes = Coeff*(Wj - Wl);
    if(abs(CoeffZ2Z3Res) > CoefficientTolerance || abs(CoeffZ2Z3NonRes) > CoefficientTolerance)
        ResonantTerms.add_term(
            ResonantTerm(CoeffZ2Z3Res,CoeffZ2Z3NonRes,P1,P2,P3,false));
}

size_t TwoParticleGFPart::getNumNonResonantTerms() const
{
    return NonResonantTerms.size();
}

size_t TwoParticleGFPart::getNumResonantTerms() const
{
    return ResonantTerms.size();
}

const Permutation3& TwoParticleGFPart::getPermutation() const
{
    return Permutation;
}

ComplexType TwoParticleGFPart::operator()(long MatsubaraNumber1, long MatsubaraNumber2, long MatsubaraNumber3) const
{
    long MatsubaraNumberOdd1 = 2*MatsubaraNumber1 + 1;
    long MatsubaraNumberOdd2 = 2*MatsubaraNumber2 + 1;
    long MatsubaraNumberOdd3 = 2*MatsubaraNumber3 + 1;
    return (*this)(MatsubaraSpacing * RealType(MatsubaraNumberOdd1),
                   MatsubaraSpacing * RealType(MatsubaraNumberOdd2),
                   MatsubaraSpacing * RealType(MatsubaraNumberOdd3));
}

ComplexType TwoParticleGFPart::operator()(ComplexType z1, ComplexType z2, ComplexType z3) const
{
    ComplexType Frequencies[3] = {  z1, z2, -z3 };

    z1 = Frequencies[Permutation.perm[0]];
    z2 = Frequencies[Permutation.perm[1]];
    z3 = Frequencies[Permutation.perm[2]];

    if (Status != Computed) {
        throw std::logic_error("2PGFPart : Calling operator() on uncomputed container, did you purge all the terms when called compute()");
    }

    return NonResonantTerms(z1, z2, z3) + ResonantTerms(z1, z2, z3, ReduceResonanceTolerance);
}

const TermList<TwoParticleGFPart::ResonantTerm>& TwoParticleGFPart::getResonantTerms() const
{
    return ResonantTerms;
}

const TermList<TwoParticleGFPart::NonResonantTerm>& TwoParticleGFPart::getNonResonantTerms() const
{
    return NonResonantTerms;
}

void TwoParticleGFPart::clear()
{
    NonResonantTerms.clear();
    ResonantTerms.clear();
    Status = Constructed;
}

} // end of namespace Pomerol

<commit_msg>Added extended comments to TwoParticleGFPart::(Non)ResonantTerm::mpi_datatype()<commit_after>#include "pomerol/TwoParticleGFPart.h"

#include <cstddef>
#include <mutex>

std::mutex NonResonantTerm_mpi_datatype_mutex;
std::mutex ResonantTerm_mpi_datatype_mutex;

namespace Pomerol{

// Make the lagging index catch up or outrun the leading index.
inline bool chaseIndices(RowMajorMatrixType::InnerIterator& index1_iter,
                         ColMajorMatrixType::InnerIterator& index2_iter)
{
    InnerQuantumState index1 = index1_iter.index();
    InnerQuantumState index2 = index2_iter.index();

    if(index1 == index2) return true;

    if(index1 < index2)
        for(;InnerQuantumState(index1_iter.index())<index2 && index1_iter; ++index1_iter);
    else
        for(;InnerQuantumState(index2_iter.index())<index1 && index2_iter; ++index2_iter);

    return false;
}

//
// TwoParticleGFPart::NonResonantTerm
//
TwoParticleGFPart::NonResonantTerm& TwoParticleGFPart::NonResonantTerm::operator+=(
                    const NonResonantTerm& AnotherTerm)
{
    long combinedWeight=Weight + AnotherTerm.Weight;
    for (unsigned short p=0; p<3; ++p) Poles[p]= (Weight*Poles[p] + AnotherTerm.Weight*AnotherTerm.Poles[p])/combinedWeight;
    Weight=combinedWeight;
    Coeff += AnotherTerm.Coeff;
    return *this;
}

// When called for the first time, this function creates an MPI structure datatype
// describing TwoParticleGFPart::NonResonantTerm and registers it using MPI_Type_commit().
// The registered datatype is stored in a static variable and is immediately returned
// upon successive calls to mpi_datatype().
//
// About MPI structure datatypes:
// https://pages.tacc.utexas.edu/~eijkhout/pcse/html/mpi-data.html#Structtype
MPI_Datatype TwoParticleGFPart::NonResonantTerm::mpi_datatype() {
    static MPI_Datatype dt;

    // Since we are using static variables here, we have to make sure the code
    // is thread-safe.
    const std::lock_guard<std::mutex> lock(NonResonantTerm_mpi_datatype_mutex);

    // Create and commit datatype only once
    static bool type_committed = false;
    if(!type_committed) {
        int blocklengths[] = {1,3,1,1};
        MPI_Aint displacements[] = {offsetof(NonResonantTerm, Coeff),
                                    offsetof(NonResonantTerm, Poles),
                                    offsetof(NonResonantTerm, isz4),
                                    offsetof(NonResonantTerm, Weight)
                                   };
        MPI_Datatype types[] = {MPI_CXX_DOUBLE_COMPLEX, // ComplexType Coeff
                                MPI_DOUBLE,             // RealType Poles[3]
                                MPI_CXX_BOOL,           // bool isz4
                                MPI_LONG                // long Weight
                               };
        MPI_Type_create_struct(4, blocklengths, displacements, types, &dt);
        MPI_Type_commit(&dt);
        type_committed = true;
    }
    return dt;
}

//
// TwoParticleGFPart::ResonantTerm
//
TwoParticleGFPart::ResonantTerm& TwoParticleGFPart::ResonantTerm::operator+=(
                const ResonantTerm& AnotherTerm)
{
    long combinedWeight=Weight + AnotherTerm.Weight;
    for (unsigned short p=0; p<3; ++p) Poles[p]= (Weight*Poles[p] + AnotherTerm.Weight*AnotherTerm.Poles[p])/combinedWeight;
    Weight=combinedWeight;
    ResCoeff += AnotherTerm.ResCoeff;
    NonResCoeff += AnotherTerm.NonResCoeff;
    return *this;
}

// When called for the first time, this function creates an MPI structure datatype
// describing TwoParticleGFPart::ResonantTerm and registers it using MPI_Type_commit().
// The registered datatype is stored in a static variable and is immediately returned
// upon successive calls to mpi_datatype().
//
// About MPI structure datatypes:
// https://pages.tacc.utexas.edu/~eijkhout/pcse/html/mpi-data.html#Structtype
MPI_Datatype TwoParticleGFPart::ResonantTerm::mpi_datatype() {
    static MPI_Datatype dt;

    // Since we are using static variables here, we have to make sure the code
    // is thread-safe.
    const std::lock_guard<std::mutex> lock(ResonantTerm_mpi_datatype_mutex);

    // Create and commit datatype only once
    static bool type_committed = false;
    if(!type_committed) {
        int blocklengths[] = {1,1,3,1,1};
        MPI_Aint displacements[] = {offsetof(ResonantTerm, ResCoeff),
                                    offsetof(ResonantTerm, NonResCoeff),
                                    offsetof(ResonantTerm, Poles),
                                    offsetof(ResonantTerm, isz1z2),
                                    offsetof(ResonantTerm, Weight)
                                   };
        MPI_Datatype types[] = {MPI_CXX_DOUBLE_COMPLEX, // ComplexType ResCoeff
                                MPI_CXX_DOUBLE_COMPLEX, // ComplexType NonResCoeff
                                MPI_DOUBLE,             // RealType Poles[3]
                                MPI_CXX_BOOL,           // bool isz1z2
                                MPI_LONG                // long Weight
                               };
        MPI_Type_create_struct(5, blocklengths, displacements, types, &dt);
        MPI_Type_commit(&dt);
        type_committed = true;
    }
    return dt;
}

//
// TwoParticleGFPart
//
TwoParticleGFPart::TwoParticleGFPart(
                const FieldOperatorPart& O1, const FieldOperatorPart& O2,
                const FieldOperatorPart& O3, const CreationOperatorPart& CX4,
                const HamiltonianPart& Hpart1, const HamiltonianPart& Hpart2,
                const HamiltonianPart& Hpart3, const HamiltonianPart& Hpart4,
                const DensityMatrixPart& DMpart1, const DensityMatrixPart& DMpart2,
                const DensityMatrixPart& DMpart3, const DensityMatrixPart& DMpart4,
                Permutation3 Permutation) :
    Thermal(DMpart1),
    ComputableObject(),
    NonResonantTerms(NonResonantTerm::Compare(1e-8), NonResonantTerm::IsNegligible(1e-16)),
    ResonantTerms(ResonantTerm::Compare(1e-8), ResonantTerm::IsNegligible(1e-16)),
    O1(O1), O2(O2), O3(O3), CX4(CX4),
    Hpart1(Hpart1), Hpart2(Hpart2), Hpart3(Hpart3), Hpart4(Hpart4),
    DMpart1(DMpart1), DMpart2(DMpart2), DMpart3(DMpart3), DMpart4(DMpart4),
    Permutation(Permutation),
    ReduceResonanceTolerance(1e-8),
    CoefficientTolerance (1e-16),
    MultiTermCoefficientTolerance (1e-5)
{}

void TwoParticleGFPart::compute()
{
    NonResonantTerms.clear();
    ResonantTerms.clear();

    RealType beta = DMpart1.beta;
    // I don't have any pen now, so I'm writing here:
    // <1 | O1 | 2> <2 | O2 | 3> <3 | O3 |4> <4| CX4 |1>
    // Iterate over all values of |1><1| and |3><3|
    // Chase indices |2> and <2|, |4> and <4|.
    const RowMajorMatrixType& O1matrix = O1.getRowMajorValue();
    const ColMajorMatrixType& O2matrix = O2.getColMajorValue();
    const RowMajorMatrixType& O3matrix = O3.getRowMajorValue();
    const ColMajorMatrixType& CX4matrix = CX4.getColMajorValue();

    InnerQuantumState index1;
    InnerQuantumState index1Max = CX4matrix.outerSize(); // One can not make a cutoff in external index for evaluating 2PGF

    InnerQuantumState index3;
    InnerQuantumState index3Max = O2matrix.outerSize();

    std::vector<InnerQuantumState> Index4List;
    Index4List.reserve(index1Max*index3Max);

    for(index1=0; index1<index1Max; ++index1)
    for(index3=0; index3<index3Max; ++index3){
        ColMajorMatrixType::InnerIterator index4bra_iter(CX4matrix,index1);
        RowMajorMatrixType::InnerIterator index4ket_iter(O3matrix,index3);
        Index4List.clear();
        while (index4bra_iter && index4ket_iter){
            if(chaseIndices(index4ket_iter,index4bra_iter)){
                Index4List.push_back(index4bra_iter.index());
                ++index4bra_iter;
                ++index4ket_iter;
            }
        };

        if (!Index4List.empty())
        {
            RealType E1 = Hpart1.getEigenValue(index1);
            RealType E3 = Hpart3.getEigenValue(index3);
            RealType weight1 = DMpart1.getWeight(index1);
            RealType weight3 = DMpart3.getWeight(index3);

            ColMajorMatrixType::InnerIterator index2bra_iter(O2matrix,index3);
            RowMajorMatrixType::InnerIterator index2ket_iter(O1matrix,index1);
            while (index2bra_iter && index2ket_iter){
                if (chaseIndices(index2ket_iter,index2bra_iter)){

                    InnerQuantumState index2 = index2ket_iter.index();
                    RealType E2 = Hpart2.getEigenValue(index2);
                    RealType weight2 = DMpart2.getWeight(index2);

                    for (unsigned long p4 = 0; p4 < Index4List.size(); ++p4)
                    {
                        InnerQuantumState index4 = Index4List[p4];//*pIndex4;
                        RealType E4 = Hpart4.getEigenValue(index4);
                        RealType weight4 = DMpart4.getWeight(index4);
                        if (weight1 + weight2 + weight3 + weight4 >= CoefficientTolerance) {
                            ComplexType MatrixElement = index2ket_iter.value()*
                                                        index2bra_iter.value()*
                                                        O3matrix.coeff(index3,index4)*
                                                        CX4matrix.coeff(index4,index1);

                            MatrixElement *= Permutation.sign;

                            addMultiterm(MatrixElement,beta,E1,E2,E3,E4,weight1,weight2,weight3,weight4);
                        }
                    }
                    ++index2bra_iter;
                    ++index2ket_iter;
                };
            }
        };
    }

    std::cout << "Total " << NonResonantTerms.size() << "+" << ResonantTerms.size() << "="
              << NonResonantTerms.size() + ResonantTerms.size() << " terms" << std::endl << std::flush;

    assert(NonResonantTerms.check_terms());
    assert(ResonantTerms.check_terms());

    Status = Computed;
}

inline
void TwoParticleGFPart::addMultiterm(ComplexType Coeff, RealType beta,
                      RealType Ei, RealType Ej, RealType Ek, RealType El,
                      RealType Wi, RealType Wj, RealType Wk, RealType Wl)
{
    RealType P1 = Ej - Ei;
    RealType P2 = Ek - Ej;
    RealType P3 = El - Ek;

    // Non-resonant part of the multiterm
    ComplexType CoeffZ2 = -Coeff*(Wj + Wk);
    if(abs(CoeffZ2) > CoefficientTolerance)
        NonResonantTerms.add_term(
            NonResonantTerm(CoeffZ2,P1,P2,P3,false));
    ComplexType CoeffZ4 = Coeff*(Wi + Wl);
    if(abs(CoeffZ4) > CoefficientTolerance)
        NonResonantTerms.add_term(
            NonResonantTerm(CoeffZ4,P1,P2,P3,true));

    // Resonant part of the multiterm
    ComplexType CoeffZ1Z2Res = Coeff*beta*Wi;
    ComplexType CoeffZ1Z2NonRes = Coeff*(Wk - Wi);
    if(abs(CoeffZ1Z2Res) > CoefficientTolerance || abs(CoeffZ1Z2NonRes) > CoefficientTolerance)
        ResonantTerms.add_term(
            ResonantTerm(CoeffZ1Z2Res,CoeffZ1Z2NonRes,P1,P2,P3,true));
    ComplexType CoeffZ2Z3Res = -Coeff*beta*Wj;
    ComplexType CoeffZ2Z3NonRes = Coeff*(Wj - Wl);
    if(abs(CoeffZ2Z3Res) > CoefficientTolerance || abs(CoeffZ2Z3NonRes) > CoefficientTolerance)
        ResonantTerms.add_term(
            ResonantTerm(CoeffZ2Z3Res,CoeffZ2Z3NonRes,P1,P2,P3,false));
}

size_t TwoParticleGFPart::getNumNonResonantTerms() const
{
    return NonResonantTerms.size();
}

size_t TwoParticleGFPart::getNumResonantTerms() const
{
    return ResonantTerms.size();
}

const Permutation3& TwoParticleGFPart::getPermutation() const
{
    return Permutation;
}

ComplexType TwoParticleGFPart::operator()(long MatsubaraNumber1, long MatsubaraNumber2, long MatsubaraNumber3) const
{
    long MatsubaraNumberOdd1 = 2*MatsubaraNumber1 + 1;
    long MatsubaraNumberOdd2 = 2*MatsubaraNumber2 + 1;
    long MatsubaraNumberOdd3 = 2*MatsubaraNumber3 + 1;
    return (*this)(MatsubaraSpacing * RealType(MatsubaraNumberOdd1),
                   MatsubaraSpacing * RealType(MatsubaraNumberOdd2),
                   MatsubaraSpacing * RealType(MatsubaraNumberOdd3));
}

ComplexType TwoParticleGFPart::operator()(ComplexType z1, ComplexType z2, ComplexType z3) const
{
    ComplexType Frequencies[3] = {  z1, z2, -z3 };

    z1 = Frequencies[Permutation.perm[0]];
    z2 = Frequencies[Permutation.perm[1]];
    z3 = Frequencies[Permutation.perm[2]];

    if (Status != Computed) {
        throw std::logic_error("2PGFPart : Calling operator() on uncomputed container, did you purge all the terms when called compute()");
    }

    return NonResonantTerms(z1, z2, z3) + ResonantTerms(z1, z2, z3, ReduceResonanceTolerance);
}

const TermList<TwoParticleGFPart::ResonantTerm>& TwoParticleGFPart::getResonantTerms() const
{
    return ResonantTerms;
}

const TermList<TwoParticleGFPart::NonResonantTerm>& TwoParticleGFPart::getNonResonantTerms() const
{
    return NonResonantTerms;
}

void TwoParticleGFPart::clear()
{
    NonResonantTerms.clear();
    ResonantTerms.clear();
    Status = Constructed;
}

} // end of namespace Pomerol

<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2013-2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <vector.hpp>
#include <string.hpp>

#include "net/ip_layer.hpp"
#include "net/ethernet_layer.hpp"
#include "net/icmp_layer.hpp"
#include "net/arp_cache.hpp"

#include "logging.hpp"
#include "kernel_utils.hpp"

namespace {

void compute_checksum(network::ip::header* header){
    auto ihl = header->version_ihl & 0xF;

    header->header_checksum = 0;

    auto sum = std::accumulate(reinterpret_cast<uint16_t*>(header),reinterpret_cast<uint16_t*>(header) + ihl * 2, uint32_t(0));

    logging::logf(logging::log_level::TRACE, "ip: sum:%h\n", size_t(sum));

    uint32_t value = sum & 0xFFFF;
    uint32_t carry = (sum - value) >> 16;

    logging::logf(logging::log_level::TRACE, "ip: value:%h\n", size_t(value));
    logging::logf(logging::log_level::TRACE, "ip: carry:%h\n", size_t(carry));

    while(carry){
        value += carry;
        auto sub = value & 0xFFFF;
        carry = (value - sub) >> 16;
        value = sub;
    }

    header->header_checksum = ~uint16_t(value);
}

} // end of anonymous namespace

network::ip::address network::ip::ip32_to_ip(uint32_t raw){
    return {switch_endian_32(raw)};
}

uint32_t network::ip::ip_to_ip32(address ip){
    return switch_endian_32(ip.raw_address);
}

void network::ip::decode(network::interface_descriptor& interface, network::ethernet::packet& packet){
    header* ip_header = reinterpret_cast<header*>(packet.payload + packet.index);

    logging::logf(logging::log_level::TRACE, "ip: Start IPv4 packet handling\n");

    auto version = ip_header->version_ihl >> 4;

    if(version != 4){
        logging::logf(logging::log_level::ERROR, "ip: IPv6 Packet received instead of IPv4\n");

        return;
    }

    auto ihl = ip_header->version_ihl & 0xF;
    auto length = switch_endian_16(ip_header->total_len);
    auto data_length = length - ihl * 4;

    logging::logf(logging::log_level::TRACE, "ip: Data Length: %u\n", size_t(data_length));
    logging::logf(logging::log_level::TRACE, "ip: Time To Live: %u\n", size_t(ip_header->ttl));

    auto source = ip32_to_ip(ip_header->source_ip);
    auto target = ip32_to_ip(ip_header->target_ip);

    logging::logf(logging::log_level::TRACE, "ip: Source Protocol Address %u.%u.%u.%u \n",
        uint64_t(source(0)), uint64_t(source(1)), uint64_t(source(2)), uint64_t(source(3)));
    logging::logf(logging::log_level::TRACE, "ip: Target Protocol Address %u.%u.%u.%u \n",
        uint64_t(target(0)), uint64_t(target(1)), uint64_t(target(2)), uint64_t(target(3)));

    auto protocol = ip_header->protocol;

    packet.index += sizeof(header);

    if(protocol == 0x01){
        network::icmp::decode(interface, packet);
    } else if(protocol == 0x06){
        logging::logf(logging::log_level::ERROR, "ip: TCP packet detected (unsupported)\n");
    } else if(protocol == 0x11){
        logging::logf(logging::log_level::ERROR, "ip: UDP packet detected (unsupported)\n");
    } else {
        logging::logf(logging::log_level::ERROR, "ip: Packet of unknown protocol detected (%h)\n", size_t(protocol));
    }
}

network::ethernet::packet network::ip::prepare_packet(network::interface_descriptor& interface, size_t size, address& target_ip, size_t protocol){
    auto target_mac = network::arp::get_mac_force(interface, target_ip);

    // Ask the ethernet layer to craft a packet
    auto packet = network::ethernet::prepare_packet(interface, size + sizeof(header), target_mac, ethernet::ether_type::IPV4);

    auto* ip_header = reinterpret_cast<header*>(packet.payload + packet.index);

    ip_header->version_ihl = (4 << 4) + 5;
    ip_header->dscp_ecn = 0;
    ip_header->total_len = switch_endian_16(uint16_t(size) + sizeof(header));
    ip_header->identification = 0;
    ip_header->flags_offset = 0;
    ip_header->flags_offset = switch_endian_16(uint16_t(1) << 14);
    ip_header->ttl = 255;
    ip_header->protocol = protocol;
    ip_header->source_ip = ip_to_ip32(interface.ip_address);
    ip_header->target_ip = ip_to_ip32(target_ip);

    compute_checksum(ip_header);

    packet.index += sizeof(header);

    return packet;
}

void network::ip::finalize_packet(network::interface_descriptor& interface, network::ethernet::packet& p){
    // Send the packet to the ethernet layer
    network::ethernet::finalize_packet(interface, p);
}
<commit_msg>Remove debug messages<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2013-2016.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <vector.hpp>
#include <string.hpp>

#include "net/ip_layer.hpp"
#include "net/ethernet_layer.hpp"
#include "net/icmp_layer.hpp"
#include "net/arp_cache.hpp"

#include "logging.hpp"
#include "kernel_utils.hpp"

namespace {

void compute_checksum(network::ip::header* header){
    auto ihl = header->version_ihl & 0xF;

    header->header_checksum = 0;

    auto sum = std::accumulate(reinterpret_cast<uint16_t*>(header),reinterpret_cast<uint16_t*>(header) + ihl * 2, uint32_t(0));

    uint32_t value = sum & 0xFFFF;
    uint32_t carry = (sum - value) >> 16;

    while(carry){
        value += carry;
        auto sub = value & 0xFFFF;
        carry = (value - sub) >> 16;
        value = sub;
    }

    header->header_checksum = ~uint16_t(value);
}

} // end of anonymous namespace

network::ip::address network::ip::ip32_to_ip(uint32_t raw){
    return {switch_endian_32(raw)};
}

uint32_t network::ip::ip_to_ip32(address ip){
    return switch_endian_32(ip.raw_address);
}

void network::ip::decode(network::interface_descriptor& interface, network::ethernet::packet& packet){
    header* ip_header = reinterpret_cast<header*>(packet.payload + packet.index);

    logging::logf(logging::log_level::TRACE, "ip: Start IPv4 packet handling\n");

    auto version = ip_header->version_ihl >> 4;

    if(version != 4){
        logging::logf(logging::log_level::ERROR, "ip: IPv6 Packet received instead of IPv4\n");

        return;
    }

    auto ihl = ip_header->version_ihl & 0xF;
    auto length = switch_endian_16(ip_header->total_len);
    auto data_length = length - ihl * 4;

    logging::logf(logging::log_level::TRACE, "ip: Data Length: %u\n", size_t(data_length));
    logging::logf(logging::log_level::TRACE, "ip: Time To Live: %u\n", size_t(ip_header->ttl));

    auto source = ip32_to_ip(ip_header->source_ip);
    auto target = ip32_to_ip(ip_header->target_ip);

    logging::logf(logging::log_level::TRACE, "ip: Source Protocol Address %u.%u.%u.%u \n",
        uint64_t(source(0)), uint64_t(source(1)), uint64_t(source(2)), uint64_t(source(3)));
    logging::logf(logging::log_level::TRACE, "ip: Target Protocol Address %u.%u.%u.%u \n",
        uint64_t(target(0)), uint64_t(target(1)), uint64_t(target(2)), uint64_t(target(3)));

    auto protocol = ip_header->protocol;

    packet.index += sizeof(header);

    if(protocol == 0x01){
        network::icmp::decode(interface, packet);
    } else if(protocol == 0x06){
        logging::logf(logging::log_level::ERROR, "ip: TCP packet detected (unsupported)\n");
    } else if(protocol == 0x11){
        logging::logf(logging::log_level::ERROR, "ip: UDP packet detected (unsupported)\n");
    } else {
        logging::logf(logging::log_level::ERROR, "ip: Packet of unknown protocol detected (%h)\n", size_t(protocol));
    }
}

network::ethernet::packet network::ip::prepare_packet(network::interface_descriptor& interface, size_t size, address& target_ip, size_t protocol){
    auto target_mac = network::arp::get_mac_force(interface, target_ip);

    // Ask the ethernet layer to craft a packet
    auto packet = network::ethernet::prepare_packet(interface, size + sizeof(header), target_mac, ethernet::ether_type::IPV4);

    auto* ip_header = reinterpret_cast<header*>(packet.payload + packet.index);

    ip_header->version_ihl = (4 << 4) + 5;
    ip_header->dscp_ecn = 0;
    ip_header->total_len = switch_endian_16(uint16_t(size) + sizeof(header));
    ip_header->identification = 0;
    ip_header->flags_offset = 0;
    ip_header->flags_offset = switch_endian_16(uint16_t(1) << 14);
    ip_header->ttl = 255;
    ip_header->protocol = protocol;
    ip_header->source_ip = ip_to_ip32(interface.ip_address);
    ip_header->target_ip = ip_to_ip32(target_ip);

    compute_checksum(ip_header);

    packet.index += sizeof(header);

    return packet;
}

void network::ip::finalize_packet(network::interface_descriptor& interface, network::ethernet::packet& p){
    // Send the packet to the ethernet layer
    network::ethernet::finalize_packet(interface, p);
}
<|endoftext|>


<commit_before>// Ylikuutio - A 3D game and simulation engine.
//
// Copyright (C) 2015-2020 Antti Nuortimo.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

#ifndef __CONSOLE_COMMAND_OVERLOAD_HPP_INCLUDED
#define __CONSOLE_COMMAND_OVERLOAD_HPP_INCLUDED

#include "generic_console_command_overload.hpp"
#include "console.hpp"
#include "console_command.hpp"
#include "code/ylikuutio/lisp/arg_processing_templates.hpp"
#include "code/ylikuutio/lisp/lisp_templates.hpp"

// Include standard headers
#include <cstddef>    // std::size_t
#include <functional> // std::function, std::invoke
#include <memory>     // std::make_shared, std::shared_ptr
#include <string>     // std::string
#include <tuple>      // std::apply, std::tuple, std::tuple_cat
#include <utility>    // std::pair
#include <vector>     // std::vector

// This is a bit complicated, as the callback may receive different kinds of arguments.
//
// The default context is `Universe`.
//
// 1. If the callback has `yli::ontology::Universe*` as an argument, then the `Universe*` will be provided.
//    This does not consume any parameters. The `Universe` is set as context.
//
// 2. If the callback has `yli::ontology::Console*` as an argument, then this `Console*` will be provided.
//    This does not consume any parameters. In the future other `Console`s will be made reachable as well,
//    with `yli::ontology::SomeConsole*`. The `Console` is set as context.
//
// 3. Otherwise, if the callback has `yli::ontology::Entity*` or some subtype of `Entity` as an argument,
//    then the string will be looked up and converted into that. The `Entity` is set as context.
//
// 4. If the callback has `yli::config::Setting*` as an argument, then the `Setting` with that name
//    will be looked up from the current context.
//
// 5. If the callback has `bool` as an argument, then the string will be converted into that.
//
// 6. If the callback has `float` as an argument, then the string will be converted into that.
//
// 7. If the callback has `double` as an argument, then the string will be converted into that.
//
// 8. If the callback has `int32_t` as an argument, then the string will be converted into that.
//
// 9. If the callback has `uint32_t` as an argument, then the string will be converted into that.
//
// If any lookup or conversion fails, the callback will not be called.
// If `dynamic_cast` from `yli::ontology::Entity*` into its subtype results in `nullptr`, the callback will not be called.
// If there is not enough parameters for all conversions, the callback will not be called.
// If not all parameters are consumed, the callback will not be called.
//
// Therefore, the number of provided parameters must match the following equation:
//
// number-of-provided-parameters = number-of-function-arguments - number-of-Universe-arguments - number-of-Console-arguments

namespace yli::data
{
    class AnyValue;
}

namespace yli::ontology
{
    class Entity;
    class Universe;
    class ParentModule;

    template<class... Types>
        class ConsoleCommandOverload: public yli::ontology::GenericConsoleCommandOverload
    {
        public:
            ConsoleCommandOverload(
                    yli::ontology::Universe* const universe,
                    yli::ontology::ParentModule* const parent_module,
                    std::function<std::shared_ptr<yli::data::AnyValue>(Types... types)> callback)
                : GenericConsoleCommandOverload(universe, parent_module),
                callback(callback)
            {
                // constructor.

                // `yli::ontology::Entity` member variables begin here.
                this->type_string = "yli::ontology::ConsoleCommandOverload*";
            }

            ConsoleCommandOverload(const ConsoleCommandOverload&) = delete;            // Delete copy constructor.
            ConsoleCommandOverload &operator=(const ConsoleCommandOverload&) = delete; // Delete copy assignment.

            // destructor.
            virtual ~ConsoleCommandOverload()
            {
                // destructor.
            }

            std::pair<bool, std::shared_ptr<yli::data::AnyValue>> execute(const std::vector<std::string>& parameter_vector) override
            {
                yli::ontology::Universe* const universe = this->get_universe();

                if (universe == nullptr)
                {
                    std::cerr << "ERROR: `ConsoleCommandOverload::execute`: `universe` is `nullptr`!\n";
                    return std::pair(false, nullptr);
                }

                yli::ontology::Entity* const console_command_entity = this->child_of_console_command.get_parent();

                yli::ontology::ConsoleCommand* const console_command = dynamic_cast<yli::ontology::ConsoleCommand*>(console_command_entity);

                if (console_command == nullptr)
                {
                    std::cerr << "ERROR: `ConsoleCommandOverload::execute`: `console_command` is `nullptr`!\n";
                    return std::pair(false, nullptr);
                }

                yli::ontology::Entity* const console_entity = console_command->get_parent();

                if (console_entity == nullptr)
                {
                    std::cerr << "ERROR: `ConsoleCommandOverload::execute`: `console_entity` is `nullptr`!\n";
                    return std::pair(false, nullptr);
                }

                yli::ontology::Console* const console = dynamic_cast<yli::ontology::Console*>(console_entity);

                if (console == nullptr)
                {
                    std::cerr << "ERROR: `ConsoleCommandOverload::execute`: `console` is `nullptr`!\n";
                    return std::pair(false, nullptr);
                }

                // OK, all preconditions for a successful argument binding are met.
                // Now, process the arguments.
                std::tuple<Types...> arg_tuple;

                if (this->start_process_args(parameter_vector, arg_tuple))
                {

                    // Call the callback function if binding was successful.
                    return std::pair(true, std::apply(this->callback, arg_tuple));
                }

                // std::tuple<bool, std::shared_ptr<yli::data::AnyValue>, std::tuple<Types...>> this->start_process_args(parameter_vector);

                /*
                bool success1 = true;
                bool success2 = true;
                bool success3 = true;
                bool success4 = true;

                std::size_t parameter_i = 0;

                yli::ontology::Entity* context = universe; // `Universe` is the default context.
                T1 value1 = yli::data::convert_string_to_value_and_advance_index<T1>(universe, console, context, parameter_vector, parameter_i, success1);
                T2 value2 = yli::data::convert_string_to_value_and_advance_index<T2>(universe, console, context, parameter_vector, parameter_i, success2);
                T3 value3 = yli::data::convert_string_to_value_and_advance_index<T3>(universe, console, context, parameter_vector, parameter_i, success3);
                T4 value4 = yli::data::convert_string_to_value_and_advance_index<T3>(universe, console, context, parameter_vector, parameter_i, success3);

                if (success1 && success2 && success3 && success4 && parameter_i == parameter_vector.size())
                {
                    // Call the callback function if binding was successful.
                    std::tuple parameter_tuple = std::make_tuple(value1, value2, value3, value4);
                    return std::pair(true, std::apply(this->callback, parameter_tuple));
                }
                */

                return std::pair(false, nullptr);
            }

        private:
            bool start_process_args(const std::vector<std::string>& parameter_vector, std::tuple<Types...>& arg_tuple)
            {
                // Start processing the arguments.

                if (this->universe == nullptr)
                {
                    return false;
                }

                yli::ontology::ConsoleCommand* const console_command = static_cast<yli::ontology::ConsoleCommand*>(this->get_parent());

                if (console_command == nullptr)
                {
                    return false;
                }

                yli::ontology::Console* const console = static_cast<yli::ontology::Console*>(console_command->get_parent());

                if (console == nullptr)
                {
                    return false;
                }

                std::size_t parameter_i = 0;                     // Start from the first parameter.
                yli::ontology::Entity* context = this->universe; // `Universe` is the default context.

                return yli::lisp::process_args<Types...>(this->universe, console, context, parameter_vector, parameter_i, arg_tuple);
            }

            // The callback may receive different kinds of arguments.
            const std::function<std::shared_ptr<yli::data::AnyValue>(Types...)> callback;
    };
}

#endif
<commit_msg>Remove obsolete commented out code.<commit_after>// Ylikuutio - A 3D game and simulation engine.
//
// Copyright (C) 2015-2020 Antti Nuortimo.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

#ifndef __CONSOLE_COMMAND_OVERLOAD_HPP_INCLUDED
#define __CONSOLE_COMMAND_OVERLOAD_HPP_INCLUDED

#include "generic_console_command_overload.hpp"
#include "console.hpp"
#include "console_command.hpp"
#include "code/ylikuutio/lisp/arg_processing_templates.hpp"
#include "code/ylikuutio/lisp/lisp_templates.hpp"

// Include standard headers
#include <cstddef>    // std::size_t
#include <functional> // std::function, std::invoke
#include <memory>     // std::make_shared, std::shared_ptr
#include <string>     // std::string
#include <tuple>      // std::apply, std::tuple, std::tuple_cat
#include <utility>    // std::pair
#include <vector>     // std::vector

// This is a bit complicated, as the callback may receive different kinds of arguments.
//
// The default context is `Universe`.
//
// 1. If the callback has `yli::ontology::Universe*` as an argument, then the `Universe*` will be provided.
//    This does not consume any parameters. The `Universe` is set as context.
//
// 2. If the callback has `yli::ontology::Console*` as an argument, then this `Console*` will be provided.
//    This does not consume any parameters. In the future other `Console`s will be made reachable as well,
//    with `yli::ontology::SomeConsole*`. The `Console` is set as context.
//
// 3. Otherwise, if the callback has `yli::ontology::Entity*` or some subtype of `Entity` as an argument,
//    then the string will be looked up and converted into that. The `Entity` is set as context.
//
// 4. If the callback has `yli::config::Setting*` as an argument, then the `Setting` with that name
//    will be looked up from the current context.
//
// 5. If the callback has `bool` as an argument, then the string will be converted into that.
//
// 6. If the callback has `float` as an argument, then the string will be converted into that.
//
// 7. If the callback has `double` as an argument, then the string will be converted into that.
//
// 8. If the callback has `int32_t` as an argument, then the string will be converted into that.
//
// 9. If the callback has `uint32_t` as an argument, then the string will be converted into that.
//
// If any lookup or conversion fails, the callback will not be called.
// If `dynamic_cast` from `yli::ontology::Entity*` into its subtype results in `nullptr`, the callback will not be called.
// If there is not enough parameters for all conversions, the callback will not be called.
// If not all parameters are consumed, the callback will not be called.
//
// Therefore, the number of provided parameters must match the following equation:
//
// number-of-provided-parameters = number-of-function-arguments - number-of-Universe-arguments - number-of-Console-arguments

namespace yli::data
{
    class AnyValue;
}

namespace yli::ontology
{
    class Entity;
    class Universe;
    class ParentModule;

    template<class... Types>
        class ConsoleCommandOverload: public yli::ontology::GenericConsoleCommandOverload
    {
        public:
            ConsoleCommandOverload(
                    yli::ontology::Universe* const universe,
                    yli::ontology::ParentModule* const parent_module,
                    std::function<std::shared_ptr<yli::data::AnyValue>(Types... types)> callback)
                : GenericConsoleCommandOverload(universe, parent_module),
                callback(callback)
            {
                // constructor.

                // `yli::ontology::Entity` member variables begin here.
                this->type_string = "yli::ontology::ConsoleCommandOverload*";
            }

            ConsoleCommandOverload(const ConsoleCommandOverload&) = delete;            // Delete copy constructor.
            ConsoleCommandOverload &operator=(const ConsoleCommandOverload&) = delete; // Delete copy assignment.

            // destructor.
            virtual ~ConsoleCommandOverload()
            {
                // destructor.
            }

            std::pair<bool, std::shared_ptr<yli::data::AnyValue>> execute(const std::vector<std::string>& parameter_vector) override
            {
                yli::ontology::Universe* const universe = this->get_universe();

                if (universe == nullptr)
                {
                    std::cerr << "ERROR: `ConsoleCommandOverload::execute`: `universe` is `nullptr`!\n";
                    return std::pair(false, nullptr);
                }

                yli::ontology::Entity* const console_command_entity = this->child_of_console_command.get_parent();

                yli::ontology::ConsoleCommand* const console_command = dynamic_cast<yli::ontology::ConsoleCommand*>(console_command_entity);

                if (console_command == nullptr)
                {
                    std::cerr << "ERROR: `ConsoleCommandOverload::execute`: `console_command` is `nullptr`!\n";
                    return std::pair(false, nullptr);
                }

                yli::ontology::Entity* const console_entity = console_command->get_parent();

                if (console_entity == nullptr)
                {
                    std::cerr << "ERROR: `ConsoleCommandOverload::execute`: `console_entity` is `nullptr`!\n";
                    return std::pair(false, nullptr);
                }

                yli::ontology::Console* const console = dynamic_cast<yli::ontology::Console*>(console_entity);

                if (console == nullptr)
                {
                    std::cerr << "ERROR: `ConsoleCommandOverload::execute`: `console` is `nullptr`!\n";
                    return std::pair(false, nullptr);
                }

                // OK, all preconditions for a successful argument binding are met.
                // Now, process the arguments.
                std::tuple<Types...> arg_tuple;

                if (this->start_process_args(parameter_vector, arg_tuple))
                {

                    // Call the callback function if binding was successful.
                    return std::pair(true, std::apply(this->callback, arg_tuple));
                }

                return std::pair(false, nullptr);
            }

        private:
            bool start_process_args(const std::vector<std::string>& parameter_vector, std::tuple<Types...>& arg_tuple)
            {
                // Start processing the arguments.

                if (this->universe == nullptr)
                {
                    return false;
                }

                yli::ontology::ConsoleCommand* const console_command = static_cast<yli::ontology::ConsoleCommand*>(this->get_parent());

                if (console_command == nullptr)
                {
                    return false;
                }

                yli::ontology::Console* const console = static_cast<yli::ontology::Console*>(console_command->get_parent());

                if (console == nullptr)
                {
                    return false;
                }

                std::size_t parameter_i = 0;                     // Start from the first parameter.
                yli::ontology::Entity* context = this->universe; // `Universe` is the default context.

                return yli::lisp::process_args<Types...>(this->universe, console, context, parameter_vector, parameter_i, arg_tuple);
            }

            // The callback may receive different kinds of arguments.
            const std::function<std::shared_ptr<yli::data::AnyValue>(Types...)> callback;
    };
}

#endif
<|endoftext|>


<commit_before><commit_msg>warning C4189: local variable is initialized but not referenced<commit_after><|endoftext|>