<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

 /*
  * $Log$
  * Revision 1.1  2003/09/16 14:33:36  neilg
  * PSVI/schema component model classes, with Makefile/configuration changes necessary to build them
  *
  */

#if !defined(PSVIHANDLER_HPP)
#define PSVIHANDLER_HPP

#include <xercesc/framework/psvi/PSVIElement.hpp>
#include <xercesc/framework/psvi/PSVIAttribute.hpp>

XERCES_CPP_NAMESPACE_BEGIN

/**
  * This abstract class provides the interface for the scanner to return
  * PSVI information to the application.
  *
  */
class XMLPARSER_EXPORT PSVIHandler
{
public:
    // -----------------------------------------------------------------------
    //  Constructors are hidden, just the virtual destructor is exposed
    // -----------------------------------------------------------------------
    /** @name Destructor */
    //@{
    virtual ~PSVIHandler()
    {
    }
    //@}

    /** @name The PSVI handler interface */
    //@{
    /** Receive notification of the PSVI properties of an element.
      * The scanner will issue this call after the XMLDocumentHandler
      * endElement call.  Since the scanner will issue the psviAttributes
      * call immediately after reading the start tag of an element, all element
      * content will be effectively bracketed by these two calls.
      * @param  localName The name of the element whose end tag was just
      *                     parsed.
      * @param  uri       The namespace to which the element is bound
      * @param  prefix  The string representing the prefix name
      * @param  elementInfo    Object containing the element's PSVI properties
      */
    virtual void handleElementPSVI
    (
        const   XMLElementDecl *        localName
        , const XMLCh* const            uri
        , const XMLCh* const            prefix
        , const PSVIElement *           elementInfo
    ) = 0;

    /**
      * Enables PSVI information about attributes to be passed back to the
      * application.  This callback will be made on *all*
      * elements; on elements with no attributes, the final parameter will
      * be null.
      * @param  localName The name of the element upon which start tag
      *          these attributes were encountered.
      * @param  uri       The namespace to which the element is bound
      * @param  prefix  The string representing the prefix name
      * @param  psviAttributes   Object containing the attributes' PSVI properties
      *          with information to identify them.
      */
    virtual void handleAttributesPSVI
    (
        const   XMLElementDecl *        localName
        , const XMLCh* const            uri
        , const XMLCh* const            prefix
        , const PSVIAttributeList *     psviAttributes
    ) = 0;

    //@}

protected :
    // -----------------------------------------------------------------------
    //  Hidden Constructors
    // -----------------------------------------------------------------------
    PSVIHandler()
    {
    }

private:
    // -----------------------------------------------------------------------
    //  Unimplemented constructors and operators
    // -----------------------------------------------------------------------
    PSVIHandler(const PSVIHandler&);
    PSVIHandler& operator=(const PSVIHandler&);
};

XERCES_CPP_NAMESPACE_END

#endif
<commit_msg>clearly the local name of an element should be a string, not an XMLElementDecl...<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

 /*
  * $Log$
  * Revision 1.2  2003/09/22 15:03:06  neilg
  * clearly the local name of an element should be a string, not an XMLElementDecl...
  *
  * Revision 1.1  2003/09/16 14:33:36  neilg
  * PSVI/schema component model classes, with Makefile/configuration changes necessary to build them
  *
  */

#if !defined(PSVIHANDLER_HPP)
#define PSVIHANDLER_HPP

#include <xercesc/framework/psvi/PSVIElement.hpp>
#include <xercesc/framework/psvi/PSVIAttribute.hpp>

XERCES_CPP_NAMESPACE_BEGIN

/**
  * This abstract class provides the interface for the scanner to return
  * PSVI information to the application.
  *
  */
class XMLPARSER_EXPORT PSVIHandler
{
public:
    // -----------------------------------------------------------------------
    //  Constructors are hidden, just the virtual destructor is exposed
    // -----------------------------------------------------------------------
    /** @name Destructor */
    //@{
    virtual ~PSVIHandler()
    {
    }
    //@}

    /** @name The PSVI handler interface */
    //@{
    /** Receive notification of the PSVI properties of an element.
      * The scanner will issue this call after the XMLDocumentHandler
      * endElement call.  Since the scanner will issue the psviAttributes
      * call immediately after reading the start tag of an element, all element
      * content will be effectively bracketed by these two calls.
      * @param  localName The name of the element whose end tag was just
      *                     parsed.
      * @param  uri       The namespace to which the element is bound
      * @param  prefix  The string representing the prefix name
      * @param  elementInfo    Object containing the element's PSVI properties
      */
    virtual void handleElementPSVI
    (
        const   XMLCh *                 localName
        , const XMLCh* const            uri
        , const XMLCh* const            prefix
        , const PSVIElement *           elementInfo
    ) = 0;

    /**
      * Enables PSVI information about attributes to be passed back to the
      * application.  This callback will be made on *all*
      * elements; on elements with no attributes, the final parameter will
      * be null.
      * @param  localName The name of the element upon which start tag
      *          these attributes were encountered.
      * @param  uri       The namespace to which the element is bound
      * @param  prefix  The string representing the prefix name
      * @param  psviAttributes   Object containing the attributes' PSVI properties
      *          with information to identify them.
      */
    virtual void handleAttributesPSVI
    (
        const   XMLCh *                 localName
        , const XMLCh* const            uri
        , const XMLCh* const            prefix
        , const PSVIAttributeList *     psviAttributes
    ) = 0;

    //@}

protected :
    // -----------------------------------------------------------------------
    //  Hidden Constructors
    // -----------------------------------------------------------------------
    PSVIHandler()
    {
    }

private:
    // -----------------------------------------------------------------------
    //  Unimplemented constructors and operators
    // -----------------------------------------------------------------------
    PSVIHandler(const PSVIHandler&);
    PSVIHandler& operator=(const PSVIHandler&);
};

XERCES_CPP_NAMESPACE_END

#endif
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qwaylandglcontext.h"

#include "qwaylanddisplay.h"
#include "qwaylandwindow.h"
#include "qwaylandeglwindow.h"

#include <QtPlatformSupport/private/qeglconvenience_p.h>

#include <QtGui/QPlatformOpenGLContext>
#include <QtGui/QSurfaceFormat>
#include <QtCore/QMutex>

QWaylandGLContext::QWaylandGLContext(EGLDisplay eglDisplay, const QSurfaceFormat &format, QPlatformOpenGLContext *share)
    : QPlatformOpenGLContext()
    , m_eglDisplay(eglDisplay)
    , m_config(q_configFromGLFormat(m_eglDisplay, format, true))
    , m_format(q_glFormatFromConfig(m_eglDisplay, m_config))
{
    EGLContext shareEGLContext = share ? static_cast<QWaylandGLContext *>(share)->eglContext() : EGL_NO_CONTEXT;

    eglBindAPI(EGL_OPENGL_ES_API);

    QVector<EGLint> eglContextAttrs;
    eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION);
    eglContextAttrs.append(2);
    eglContextAttrs.append(EGL_NONE);

    m_context = eglCreateContext(m_eglDisplay, m_config, shareEGLContext, eglContextAttrs.constData());
}

QWaylandGLContext::~QWaylandGLContext()
{
    eglDestroyContext(m_eglDisplay, m_context);
}

bool QWaylandGLContext::makeCurrent(QPlatformSurface *surface)
{
    EGLSurface eglSurface = static_cast<QWaylandEglWindow *>(surface)->eglSurface();
    return eglMakeCurrent(m_eglDisplay, eglSurface, eglSurface, m_context);
}

void QWaylandGLContext::doneCurrent()
{
    eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
}

// lock to sync with QWaylandDisplay event loop ( defined in qwaylanddisplay.cpp )
extern QMutex g_waylandLock;

void QWaylandGLContext::swapBuffers(QPlatformSurface *surface)
{
    QMutexLocker l(&g_waylandLock);

    EGLSurface eglSurface = static_cast<QWaylandEglWindow *>(surface)->eglSurface();
    eglSwapBuffers(m_eglDisplay, eglSurface);
}

void (*QWaylandGLContext::getProcAddress(const QByteArray &procName)) ()
{
    return eglGetProcAddress(procName.constData());
}

EGLConfig QWaylandGLContext::eglConfig() const
{
    return m_config;
}

<commit_msg>pick the right gl version<commit_after>/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qwaylandglcontext.h"

#include "qwaylanddisplay.h"
#include "qwaylandwindow.h"
#include "qwaylandeglwindow.h"

#include <QtPlatformSupport/private/qeglconvenience_p.h>

#include <QtGui/QPlatformOpenGLContext>
#include <QtGui/QSurfaceFormat>
#include <QtCore/QMutex>

QWaylandGLContext::QWaylandGLContext(EGLDisplay eglDisplay, const QSurfaceFormat &format, QPlatformOpenGLContext *share)
    : QPlatformOpenGLContext()
    , m_eglDisplay(eglDisplay)
    , m_config(q_configFromGLFormat(m_eglDisplay, format, true))
    , m_format(q_glFormatFromConfig(m_eglDisplay, m_config))
{
    EGLContext shareEGLContext = share ? static_cast<QWaylandGLContext *>(share)->eglContext() : EGL_NO_CONTEXT;

    eglBindAPI(EGL_OPENGL_ES_API);

    QVector<EGLint> eglContextAttrs;
    eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION);
    eglContextAttrs.append(format.majorVersion() == 1 ? 1 : 2);
    eglContextAttrs.append(EGL_NONE);

    m_context = eglCreateContext(m_eglDisplay, m_config, shareEGLContext, eglContextAttrs.constData());
}

QWaylandGLContext::~QWaylandGLContext()
{
    eglDestroyContext(m_eglDisplay, m_context);
}

bool QWaylandGLContext::makeCurrent(QPlatformSurface *surface)
{
    EGLSurface eglSurface = static_cast<QWaylandEglWindow *>(surface)->eglSurface();
    return eglMakeCurrent(m_eglDisplay, eglSurface, eglSurface, m_context);
}

void QWaylandGLContext::doneCurrent()
{
    eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
}

// lock to sync with QWaylandDisplay event loop ( defined in qwaylanddisplay.cpp )
extern QMutex g_waylandLock;

void QWaylandGLContext::swapBuffers(QPlatformSurface *surface)
{
    QMutexLocker l(&g_waylandLock);

    EGLSurface eglSurface = static_cast<QWaylandEglWindow *>(surface)->eglSurface();
    eglSwapBuffers(m_eglDisplay, eglSurface);
}

void (*QWaylandGLContext::getProcAddress(const QByteArray &procName)) ()
{
    return eglGetProcAddress(procName.constData());
}

EGLConfig QWaylandGLContext::eglConfig() const
{
    return m_config;
}

<|endoftext|>


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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

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

#include <mitkTestingMacros.h>
#include <mitkTestFixture.h>
#include "mitkIOUtil.h"
#include <cmath>

#include <mitkGIFImageDescriptionFeatures.h>

class mitkGIFImageDescriptionFeaturesTestSuite : public mitk::TestFixture
{
  CPPUNIT_TEST_SUITE(mitkGIFImageDescriptionFeaturesTestSuite );

  MITK_TEST(ImageDescription_PhantomTest);

  CPPUNIT_TEST_SUITE_END();

private:
	mitk::Image::Pointer m_IBSI_Phantom_Image_Small;
	mitk::Image::Pointer m_IBSI_Phantom_Image_Large;
	mitk::Image::Pointer m_IBSI_Phantom_Mask_Small;
	mitk::Image::Pointer m_IBSI_Phantom_Mask_Large;

public:

  void setUp(void) override
  {
    m_IBSI_Phantom_Image_Small = mitk::IOUtil::LoadImage(GetTestDataFilePath("Radiomics/IBSI_Phantom_Image_Small.nrrd"));
    m_IBSI_Phantom_Image_Large = mitk::IOUtil::LoadImage(GetTestDataFilePath("Radiomics/IBSI_Phantom_Image_Large.nrrd"));
    m_IBSI_Phantom_Mask_Small = mitk::IOUtil::LoadImage(GetTestDataFilePath("Radiomics/IBSI_Phantom_Mask_Small.nrrd"));
    m_IBSI_Phantom_Mask_Large = mitk::IOUtil::LoadImage(GetTestDataFilePath("Radiomics/IBSI_Phantom_Mask_Large.nrrd"));
  }

  void ImageDescription_PhantomTest()
  {
    mitk::GIFImageDescriptionFeatures::Pointer featureCalculator = mitk::GIFImageDescriptionFeatures::New();
    auto featureList = featureCalculator->CalculateFeatures(m_IBSI_Phantom_Image_Large, m_IBSI_Phantom_Mask_Large);

    std::map<std::string, double> results;
    for (auto valuePair : featureList)
    {
      MITK_INFO << valuePair.first << " : " << valuePair.second;
      results[valuePair.first] = valuePair.second;
    }
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Image Diagnostics should calculate 22 features.", std::size_t(22), featureList.size());

    CPPUNIT_ASSERT_EQUAL_MESSAGE("Diagnostic::Image Dimension X should be 7 with Large IBSI Phantom Image", int(7), int(results["Diagnostic::Image Dimension X"]));
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Diagnostic::Image Dimension Y should be 6 with Large IBSI Phantom Image", int(6), int(results["Diagnostic::Image Dimension Y"]));
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Diagnostic::Image Dimension Z should be 6 with Large IBSI Phantom Image", int(6), int(results["Diagnostic::Image Dimension Z"]));

    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Diagnostic::Image Spacing X should be 2 with Large IBSI Phantom Image", 2.0, results["Diagnostic::Image Spacing X"], 0.0001);
    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Diagnostic::Image Spacing Y should be 2 with Large IBSI Phantom Image", 2.0, results["Diagnostic::Image Spacing Y"], 0.0001);
    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Diagnostic::Image Spacing Z should be 2 with Large IBSI Phantom Image", 2.0, results["Diagnostic::Image Spacing Z"], 0.0001);

    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Diagnostic::Image Mean intensity should be 0.6865 with Large IBSI Phantom Image", 0.686508, results["Diagnostic::Image Mean intensity"], 0.0001);
    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Diagnostic::Image Minimum intensity should be 0 with Large IBSI Phantom Image", 0, results["Diagnostic::Image Minimum intensity"], 0.0001);
    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Diagnostic::Image Maximum intensity should be 9 with Large IBSI Phantom Image", 9, results["Diagnostic::Image Maximum intensity"], 0.0001);

    CPPUNIT_ASSERT_EQUAL_MESSAGE("Diagnostic::Mask Dimension X should be 7 with Large IBSI Phantom Image", int(7), int(results["Diagnostic::Mask Dimension X"]));
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Diagnostic::Mask Dimension Y should be 6 with Large IBSI Phantom Image", int(6), int(results["Diagnostic::Mask Dimension Y"]));
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Diagnostic::Mask Dimension Z should be 6 with Large IBSI Phantom Image", int(6), int(results["Diagnostic::Mask Dimension Z"]));

    CPPUNIT_ASSERT_EQUAL_MESSAGE("Diagnostic::Mask bounding box X should be 5 with Large IBSI Phantom Image", int(5), int(results["Diagnostic::Mask bounding box X"]));
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Diagnostic::Mask bounding box Y should be 4 with Large IBSI Phantom Image", int(4), int(results["Diagnostic::Mask bounding box Y"]));
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Diagnostic::Mask bounding box Z should be 4 with Large IBSI Phantom Image", int(4), int(results["Diagnostic::Mask bounding box Z"]));

    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Diagnostic::Mask Spacing X should be 2 with Large IBSI Phantom Image", 2.0, results["Diagnostic::Mask Spacing X"], 0.0001);
    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Diagnostic::Mask Spacing Y should be 2 with Large IBSI Phantom Image", 2.0, results["Diagnostic::Mask Spacing Y"], 0.0001);
    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Diagnostic::Mask Spacing Z should be 2 with Large IBSI Phantom Image", 2.0, results["Diagnostic::Mask Spacing Z"], 0.0001);

    CPPUNIT_ASSERT_EQUAL_MESSAGE("Diagnostic::Mask Voxel Count should be 74 with Large IBSI Phantom Image", int(74), int(results["Diagnostic::Mask Voxel Count"]));
    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Diagnostic::Mask Mean intensity should be 2.14865 with Large IBSI Phantom Image", 2.14865, results["Diagnostic::Mask Mean intensity"], 0.0001);
    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Diagnostic::Mask Minimum intensity should be 1 with Large IBSI Phantom Image", 1, results["Diagnostic::Mask Minimum intensity"], 0.0001);
    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Diagnostic::Mask Maximum intensity should be 6 with Large IBSI Phantom Image", 6, results["Diagnostic::Mask Maximum intensity"], 0.0001);
  }

};

MITK_TEST_SUITE_REGISTRATION(mitkGIFImageDescriptionFeatures )<commit_msg>Added a comment to clarify the origin of the values<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

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

#include <mitkTestingMacros.h>
#include <mitkTestFixture.h>
#include "mitkIOUtil.h"
#include <cmath>

#include <mitkGIFImageDescriptionFeatures.h>

class mitkGIFImageDescriptionFeaturesTestSuite : public mitk::TestFixture
{
  CPPUNIT_TEST_SUITE(mitkGIFImageDescriptionFeaturesTestSuite );

  MITK_TEST(ImageDescription_PhantomTest);

  CPPUNIT_TEST_SUITE_END();

private:
	mitk::Image::Pointer m_IBSI_Phantom_Image_Small;
	mitk::Image::Pointer m_IBSI_Phantom_Image_Large;
	mitk::Image::Pointer m_IBSI_Phantom_Mask_Small;
	mitk::Image::Pointer m_IBSI_Phantom_Mask_Large;

public:

  void setUp(void) override
  {
    m_IBSI_Phantom_Image_Small = mitk::IOUtil::LoadImage(GetTestDataFilePath("Radiomics/IBSI_Phantom_Image_Small.nrrd"));
    m_IBSI_Phantom_Image_Large = mitk::IOUtil::LoadImage(GetTestDataFilePath("Radiomics/IBSI_Phantom_Image_Large.nrrd"));
    m_IBSI_Phantom_Mask_Small = mitk::IOUtil::LoadImage(GetTestDataFilePath("Radiomics/IBSI_Phantom_Mask_Small.nrrd"));
    m_IBSI_Phantom_Mask_Large = mitk::IOUtil::LoadImage(GetTestDataFilePath("Radiomics/IBSI_Phantom_Mask_Large.nrrd"));
  }

  void ImageDescription_PhantomTest()
  {
    mitk::GIFImageDescriptionFeatures::Pointer featureCalculator = mitk::GIFImageDescriptionFeatures::New();
    auto featureList = featureCalculator->CalculateFeatures(m_IBSI_Phantom_Image_Large, m_IBSI_Phantom_Mask_Large);

    std::map<std::string, double> results;
    for (auto valuePair : featureList)
    {
      MITK_INFO << valuePair.first << " : " << valuePair.second;
      results[valuePair.first] = valuePair.second;
    }
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Image Diagnostics should calculate 22 features.", std::size_t(22), featureList.size());

    // These values are calculated obtained by using this filter. Changes, especially with mean values could happen.

    CPPUNIT_ASSERT_EQUAL_MESSAGE("Diagnostic::Image Dimension X should be 7 with Large IBSI Phantom Image", int(7), int(results["Diagnostic::Image Dimension X"]));
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Diagnostic::Image Dimension Y should be 6 with Large IBSI Phantom Image", int(6), int(results["Diagnostic::Image Dimension Y"]));
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Diagnostic::Image Dimension Z should be 6 with Large IBSI Phantom Image", int(6), int(results["Diagnostic::Image Dimension Z"]));

    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Diagnostic::Image Spacing X should be 2 with Large IBSI Phantom Image", 2.0, results["Diagnostic::Image Spacing X"], 0.0001);
    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Diagnostic::Image Spacing Y should be 2 with Large IBSI Phantom Image", 2.0, results["Diagnostic::Image Spacing Y"], 0.0001);
    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Diagnostic::Image Spacing Z should be 2 with Large IBSI Phantom Image", 2.0, results["Diagnostic::Image Spacing Z"], 0.0001);

    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Diagnostic::Image Mean intensity should be 0.6865 with Large IBSI Phantom Image", 0.686508, results["Diagnostic::Image Mean intensity"], 0.0001);
    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Diagnostic::Image Minimum intensity should be 0 with Large IBSI Phantom Image", 0, results["Diagnostic::Image Minimum intensity"], 0.0001);
    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Diagnostic::Image Maximum intensity should be 9 with Large IBSI Phantom Image", 9, results["Diagnostic::Image Maximum intensity"], 0.0001);

    CPPUNIT_ASSERT_EQUAL_MESSAGE("Diagnostic::Mask Dimension X should be 7 with Large IBSI Phantom Image", int(7), int(results["Diagnostic::Mask Dimension X"]));
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Diagnostic::Mask Dimension Y should be 6 with Large IBSI Phantom Image", int(6), int(results["Diagnostic::Mask Dimension Y"]));
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Diagnostic::Mask Dimension Z should be 6 with Large IBSI Phantom Image", int(6), int(results["Diagnostic::Mask Dimension Z"]));

    CPPUNIT_ASSERT_EQUAL_MESSAGE("Diagnostic::Mask bounding box X should be 5 with Large IBSI Phantom Image", int(5), int(results["Diagnostic::Mask bounding box X"]));
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Diagnostic::Mask bounding box Y should be 4 with Large IBSI Phantom Image", int(4), int(results["Diagnostic::Mask bounding box Y"]));
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Diagnostic::Mask bounding box Z should be 4 with Large IBSI Phantom Image", int(4), int(results["Diagnostic::Mask bounding box Z"]));

    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Diagnostic::Mask Spacing X should be 2 with Large IBSI Phantom Image", 2.0, results["Diagnostic::Mask Spacing X"], 0.0001);
    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Diagnostic::Mask Spacing Y should be 2 with Large IBSI Phantom Image", 2.0, results["Diagnostic::Mask Spacing Y"], 0.0001);
    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Diagnostic::Mask Spacing Z should be 2 with Large IBSI Phantom Image", 2.0, results["Diagnostic::Mask Spacing Z"], 0.0001);

    CPPUNIT_ASSERT_EQUAL_MESSAGE("Diagnostic::Mask Voxel Count should be 74 with Large IBSI Phantom Image", int(74), int(results["Diagnostic::Mask Voxel Count"]));
    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Diagnostic::Mask Mean intensity should be 2.14865 with Large IBSI Phantom Image", 2.14865, results["Diagnostic::Mask Mean intensity"], 0.0001);
    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Diagnostic::Mask Minimum intensity should be 1 with Large IBSI Phantom Image", 1, results["Diagnostic::Mask Minimum intensity"], 0.0001);
    CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Diagnostic::Mask Maximum intensity should be 6 with Large IBSI Phantom Image", 6, results["Diagnostic::Mask Maximum intensity"], 0.0001);
  }

};

MITK_TEST_SUITE_REGISTRATION(mitkGIFImageDescriptionFeatures )<|endoftext|>


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

#include <fstream>

#include <ros/ros.h>
#include <ros/console.h>
#include <tf/tf.h>
#include <tf/transform_listener.h>
#include <geometry_msgs/PoseWithCovarianceStamped.h>

static tf::StampedTransform transform;
static bool output_first;

static int sub_point_queue_size;

static double velocity;		// km/h
static std::string output_file;

static void write_clicked_point(const geometry_msgs::PoseWithCovarianceStamped::ConstPtr& msg)
{
	if (output_first) {
		std::ofstream ofs(output_file.c_str());
		ofs << std::fixed << msg->pose.pose.position.x + transform.getOrigin().x() << ","
		    << std::fixed << msg->pose.pose.position.y + transform.getOrigin().y() << ","
		    << std::fixed << msg->pose.pose.position.z + transform.getOrigin().z() << std::endl;
	} else {
		std::ofstream ofs(output_file.c_str(), std::ios_base::app);
		ofs << std::fixed << msg->pose.pose.position.x + transform.getOrigin().x() << ","
		    << std::fixed << msg->pose.pose.position.y + transform.getOrigin().y() << ","
		    << std::fixed << msg->pose.pose.position.z + transform.getOrigin().z() << ","
		    << std::fixed << velocity << std::endl;
	}

	if (output_first)
		output_first = false;
}

int main(int argc, char **argv)
{
	ros::init(argc, argv, "waypoint_clicker");

	ros::NodeHandle n;
	n.param<int>("/waypoint_clicker/sub_point_queue_size", sub_point_queue_size, 1);
	n.param<double>("/waypoint_clicker/velocity", velocity, 40);
	n.param<std::string>("/waypoint_clicker/output_file", output_file, "/tmp/lane_waypoint.csv");

	ros::Subscriber sub_point = n.subscribe("/clicked_point", sub_point_queue_size, write_clicked_point);

	tf::TransformListener listener;
	try {
		ros::Time zero = ros::Time(0);
		listener.waitForTransform("map", "world", zero, ros::Duration(10));
		listener.lookupTransform("map", "world", zero, transform);
	} catch (tf::TransformException &ex) {
		ROS_ERROR("%s", ex.what());
	}
	output_first = true;

	ros::spin();

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

#include <fstream>

#include <ros/ros.h>
#include <ros/console.h>
#include <tf/tf.h>
#include <tf/transform_listener.h>
#include <geometry_msgs/PoseWithCovarianceStamped.h>

static tf::StampedTransform transform;
static bool output_first;

static int sub_point_queue_size;

static double velocity;		// km/h
static std::string output_file;

static void write_clicked_point(const geometry_msgs::PoseWithCovarianceStamped::ConstPtr& msg)
{
	if (output_first) {
		std::ofstream ofs(output_file.c_str());
		ofs << std::fixed << msg->pose.pose.position.x + transform.getOrigin().x() << ","
		    << std::fixed << msg->pose.pose.position.y + transform.getOrigin().y() << ","
		    << std::fixed << msg->pose.pose.position.z + transform.getOrigin().z() << std::endl;
	} else {
		std::ofstream ofs(output_file.c_str(), std::ios_base::app);
		ofs << std::fixed << msg->pose.pose.position.x + transform.getOrigin().x() << ","
		    << std::fixed << msg->pose.pose.position.y + transform.getOrigin().y() << ","
		    << std::fixed << msg->pose.pose.position.z + transform.getOrigin().z() << ","
		    << std::fixed << velocity << std::endl;
	}

	if (output_first)
		output_first = false;
}

int main(int argc, char **argv)
{
	ros::init(argc, argv, "waypoint_clicker");

	ros::NodeHandle n;
	n.param<int>("/waypoint_clicker/sub_point_queue_size", sub_point_queue_size, 1);
	n.param<double>("/waypoint_clicker/velocity", velocity, 40);
	n.param<std::string>("/waypoint_clicker/output_file", output_file, "/tmp/lane_waypoint.csv");

	ros::Subscriber sub_point = n.subscribe("/initialpose", sub_point_queue_size, write_clicked_point);

	tf::TransformListener listener;
	try {
		ros::Time zero = ros::Time(0);
		listener.waitForTransform("map", "world", zero, ros::Duration(10));
		listener.lookupTransform("map", "world", zero, transform);
	} catch (tf::TransformException &ex) {
		ROS_ERROR("%s", ex.what());
	}
	output_first = true;

	ros::spin();

	return 0;
}
<|endoftext|>


<commit_before>#include "config.h"

// system
#include <vector>

// boost
#include <boost/filesystem.hpp>

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

// dune-grid-multiscale
#include <dune/grid/multiscale/provider/cube.hh>

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

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

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

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

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

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

              Nothing is done if the file already exists. If not, a parameter file will be created with all neccessary
              keys and values.
  \param[in]  filename
              (Relative) path to the file.
  **/
void ensureParamFile(std::string filename)
{
  // only write param file if there is none
  if (!boost::filesystem::exists(filename)) {
    std::ofstream file;
    file.open(filename);
    file << "[" << id << "]" << std::endl;
    file << "exact_solution.order = 2" << std::endl;
    file << "exact_solution.variable = x" << std::endl;
    file << "exact_solution.expression.0 = -0.5*x[0]*x[0] + 0.5*x[0]" << std::endl;
    file << "[grid.multiscale.provider.cube]" << std::endl;
    file << "level = 4" << std::endl;
    file << "boundaryId = 7" << std::endl;                  // a cube from the factory gets the boundary ids 1 to 4 ind 2d and 1 to 6 in 3d (hopefully)
    file << "partitions.0 = 2" << std::endl;
    file << "partitions.1 = 2" << std::endl;
    file << "partitions.2 = 2" << std::endl;
    file << "filename = " << id << ".msGrid" << std::endl;
    file << "[detailed.solvers.stationary.linear.elliptic.model.default]" << std::endl;
    file << "diffusion.order = 0" << std::endl;
    file << "diffusion.variable = x" << std::endl;
    file << "diffusion.expression.0 = 1.0"  << std::endl;
    file << "diffusion.expression.1 = 1.0"  << std::endl;
    file << "diffusion.expression.2 = 1.0"  << std::endl;
    file << "force.order = 0" << std::endl;
    file << "force.variable = x" << std::endl;
    file << "force.expression.0 = 1.0"  << std::endl;
    file << "force.expression.1 = 1.0"  << std::endl;
    file << "force.expression.2 = 1.0"  << std::endl;
    file << "dirichlet.order = 0"  << std::endl;
    file << "dirichlet.variable = x" << std::endl;
    file << "dirichlet.expression.0 = 0.0"  << std::endl;
    file << "dirichlet.expression.1 = 0.0"  << std::endl;
    file << "dirichlet.expression.2 = 0.0"  << std::endl;
    file << "[detailed.solvers.stationary.linear.elliptic.multiscale.semicontinuousgalerkin]" << std::endl;
    file << "discretization.penaltyFactor = 10.0" << std::endl;
    file << "solve.type = eigen.bicgstab.incompletelut" << std::endl;
    file << "solve.maxIter = 5000"  << std::endl;
    file << "solve.precision = 1e-12"  << std::endl;
    file << "visualize.filename = " << id << ".solution"  << std::endl;
    file << "visualize.name = solution"  << std::endl;
    file.close();
  } // only write param file if there is none
} // void ensureParamFile()

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

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

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

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

    // timer
    Dune::Timer timer;

    info << "setting up grid: " << std::endl;
    debug.suspend();
    typedef Dune::grid::Multiscale::Provider::Cube<> GridProviderType;
    paramTree.assertSub(GridProviderType::id, id);
    const GridProviderType gridProvider(paramTree.sub(GridProviderType::id));
    typedef GridProviderType::MsGridType MsGridType;
    const Dune::shared_ptr< const MsGridType > msGrid = gridProvider.msGridPtr();
    info << "  took " << timer.elapsed()
         << " sec (has " << gridProvider.grid().size(0) << " elements, "
         << msGrid->size() << " subdomain";
    if (msGrid->size() > 1)
      info << "s";
    info << " and a width of "
         << Dune::GridWidth::calcGridWidth(*(msGrid->globalGridPart())) << ")" << std::endl;
    debug.resume();
    info << "visualizing grid... " << std::flush;
    timer.reset();
    debug.suspend();
    msGrid->visualize(paramTree.sub(GridProviderType::id).get("filename", id + "_msGrid"));
    info << "done (took " << timer.elapsed() << " sek)" << std::endl;
    debug.resume();

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

    // solver
    info << "initializing solver";
//    info << ":" << std::endl;
    info << "... " << std::flush;
    debug.suspend();
    timer.reset();
    typedef Dune::Detailed::Solvers::Stationary::Linear::Elliptic::Multiscale::SemicontinuousGalerkin::DuneDetailedDiscretizations<
        ModelType,
        MsGridType,
        BoundaryInfoType,
        polOrder > SolverType;
    paramTree.assertSub(SolverType::id, id);
    SolverType solver(model, msGrid, boundaryInfo, paramTree.sub(SolverType::id));
    solver.init("  ", debug);
    debug.resume();
    info << "done (took " << timer.elapsed() << " sec)" << std::endl;

    info << "solving";
//    info << ":" << std::endl;
    info << "... " << std::flush;
    debug.suspend();
    timer.reset();
    typedef SolverType::VectorBackendType VectorType;
    Dune::shared_ptr< std::vector< VectorType > > solution = solver.createVector();
    solver.solve(*solution, paramTree.sub(SolverType::id).sub("solve"), "  ", debug);
    debug.resume();
    info << "done (took " << timer.elapsed() << " sec)" << std::endl;

//    info << "computing detailed reference solution... " << std::flush;
//    debug.suspend();
//    timer.reset();
//    typedef Dune::Detailed::Solvers::Stationary::Linear::Elliptic::ContinuousGalerkin::DuneDetailedDiscretizations<
//        ModelType,
//        typename MsGridType::GlobalGridPartType,
//        BoundaryInfoType,
//        polOrder >
//      ReferenceSolverType;
//    ReferenceSolverType referenceSolver(model, msGrid->globalGridPart(), boundaryInfo);
//    referenceSolver.init();
//    Dune::shared_ptr< VectorType > referenceSolution = referenceSolver.createVector();
//    referenceSolver.solve(*referenceSolution, paramTree.sub(SolverType::id).sub("solve"), "  ", debug);
//    info << "done (took " << timer.elapsed() << " sec)" << std::endl;
//    debug.resume();

    info << "postprocessing";
//    info << ":" << std::endl;
    info << "... " << std::flush;
    debug.suspend();
    timer.reset();
    solver.visualize(*solution,
                     paramTree.sub(SolverType::id).sub("visualize").get("filename", id + ".solution"),
                     paramTree.sub(SolverType::id).sub("visualize").get("name", "solution"),
                     "  ",
                     debug);
//    referenceSolver.visualize(*referenceSolution,
//                              paramTree.sub(SolverType::id).sub("visualize").get("filename", id + ".solution") + "_reference",
//                              paramTree.sub(SolverType::id).sub("visualize").get("name", "solution") + "_reference",
//                              "  ",
//                              debug);
    debug.resume();
    info << "done (took " << timer.elapsed() << " sec)" << std::endl;

    info << "computing norms:" << std::endl;
    Dune::shared_ptr< typename SolverType::DiscreteFunctionType > discreteSolution = solver.createDiscreteFunction(*solution, "discrete_solution");
    compute_errors(paramTree.sub(id).sub("exact_solution"),
                   *discreteSolution,
                   info, "  ");
    // if we came that far we can as well be happy about it
    return 0;
  } catch(Dune::Exception& e) {
    std::cerr << "Dune reported error: " << e.what() << std::endl;
  } catch(std::exception& e) {
    std::cerr << e.what() << std::endl;
  } catch( ... ) {
    std::cerr << "Unknown exception thrown!" << std::endl;
  } // try
} // main
<commit_msg>[examples...elliptic.multiscale...] minor id() fix<commit_after>#include "config.h"

// system
#include <vector>

// boost
#include <boost/filesystem.hpp>

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

// dune-grid-multiscale
#include <dune/grid/multiscale/provider/cube.hh>

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

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

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

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

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

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

              Nothing is done if the file already exists. If not, a parameter file will be created with all neccessary
              keys and values.
  \param[in]  filename
              (Relative) path to the file.
  **/
void ensureParamFile(std::string filename)
{
  // only write param file if there is none
  if (!boost::filesystem::exists(filename)) {
    std::ofstream file;
    file.open(filename);
    file << "[" << id << "]" << std::endl;
    file << "exact_solution.order = 2" << std::endl;
    file << "exact_solution.variable = x" << std::endl;
    file << "exact_solution.expression.0 = -0.5*x[0]*x[0] + 0.5*x[0]" << std::endl;
    file << "[grid.multiscale.provider.cube]" << std::endl;
    file << "level = 4" << std::endl;
    file << "boundaryId = 7" << std::endl;                  // a cube from the factory gets the boundary ids 1 to 4 ind 2d and 1 to 6 in 3d (hopefully)
    file << "partitions.0 = 2" << std::endl;
    file << "partitions.1 = 2" << std::endl;
    file << "partitions.2 = 2" << std::endl;
    file << "filename = " << id << ".msGrid" << std::endl;
    file << "[detailed.solvers.stationary.linear.elliptic.model.default]" << std::endl;
    file << "diffusion.order = 0" << std::endl;
    file << "diffusion.variable = x" << std::endl;
    file << "diffusion.expression.0 = 1.0"  << std::endl;
    file << "diffusion.expression.1 = 1.0"  << std::endl;
    file << "diffusion.expression.2 = 1.0"  << std::endl;
    file << "force.order = 0" << std::endl;
    file << "force.variable = x" << std::endl;
    file << "force.expression.0 = 1.0"  << std::endl;
    file << "force.expression.1 = 1.0"  << std::endl;
    file << "force.expression.2 = 1.0"  << std::endl;
    file << "dirichlet.order = 0"  << std::endl;
    file << "dirichlet.variable = x" << std::endl;
    file << "dirichlet.expression.0 = 0.0"  << std::endl;
    file << "dirichlet.expression.1 = 0.0"  << std::endl;
    file << "dirichlet.expression.2 = 0.0"  << std::endl;
    file << "[detailed.solvers.stationary.linear.elliptic.multiscale.semicontinuousgalerkin]" << std::endl;
    file << "discretization.penaltyFactor = 10.0" << std::endl;
    file << "solve.type = eigen.bicgstab.incompletelut" << std::endl;
    file << "solve.maxIter = 5000"  << std::endl;
    file << "solve.precision = 1e-12"  << std::endl;
    file << "visualize.filename = " << id << ".solution"  << std::endl;
    file << "visualize.name = solution"  << std::endl;
    file.close();
  } // only write param file if there is none
} // void ensureParamFile()

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

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

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

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

    // timer
    Dune::Timer timer;

    info << "setting up grid: " << std::endl;
    debug.suspend();
    typedef Dune::grid::Multiscale::Provider::Cube<> GridProviderType;
    paramTree.assertSub(GridProviderType::id(), id);
    const GridProviderType gridProvider(paramTree.sub(GridProviderType::id()));
    typedef GridProviderType::MsGridType MsGridType;
    const Dune::shared_ptr< const MsGridType > msGrid = gridProvider.msGridPtr();
    info << "  took " << timer.elapsed()
         << " sec (has " << gridProvider.grid().size(0) << " elements, "
         << msGrid->size() << " subdomain";
    if (msGrid->size() > 1)
      info << "s";
    info << " and a width of "
         << Dune::GridWidth::calcGridWidth(*(msGrid->globalGridPart())) << ")" << std::endl;
    debug.resume();
    info << "visualizing grid... " << std::flush;
    timer.reset();
    debug.suspend();
    msGrid->visualize(paramTree.sub(GridProviderType::id()).get("filename", id + "_msGrid"));
    info << "done (took " << timer.elapsed() << " sek)" << std::endl;
    debug.resume();

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

    // solver
    info << "initializing solver";
//    info << ":" << std::endl;
    info << "... " << std::flush;
    debug.suspend();
    timer.reset();
    typedef Dune::Detailed::Solvers
        ::Stationary
        ::Linear
        ::Elliptic
        ::Multiscale
        ::SemicontinuousGalerkin::DuneDetailedDiscretizations< ModelType, MsGridType, BoundaryInfoType, polOrder >
        SolverType;
    paramTree.assertSub(SolverType::id, id);
    SolverType solver(model, msGrid, boundaryInfo, paramTree.sub(SolverType::id));
    solver.init("  ", debug);
    debug.resume();
    info << "done (took " << timer.elapsed() << " sec)" << std::endl;

    info << "solving";
//    info << ":" << std::endl;
    info << "... " << std::flush;
    debug.suspend();
    timer.reset();
    typedef SolverType::VectorBackendType VectorType;
    Dune::shared_ptr< std::vector< VectorType > > solution = solver.createVector();
    solver.solve(*solution, paramTree.sub(SolverType::id).sub("solve"), "  ", debug);
    debug.resume();
    info << "done (took " << timer.elapsed() << " sec)" << std::endl;

//    info << "computing detailed reference solution... " << std::flush;
//    debug.suspend();
//    timer.reset();
//    typedef Dune::Detailed::Solvers::Stationary::Linear::Elliptic::ContinuousGalerkin::DuneDetailedDiscretizations<
//        ModelType,
//        typename MsGridType::GlobalGridPartType,
//        BoundaryInfoType,
//        polOrder >
//      ReferenceSolverType;
//    ReferenceSolverType referenceSolver(model, msGrid->globalGridPart(), boundaryInfo);
//    referenceSolver.init();
//    Dune::shared_ptr< VectorType > referenceSolution = referenceSolver.createVector();
//    referenceSolver.solve(*referenceSolution, paramTree.sub(SolverType::id).sub("solve"), "  ", debug);
//    info << "done (took " << timer.elapsed() << " sec)" << std::endl;
//    debug.resume();

    info << "postprocessing";
//    info << ":" << std::endl;
    info << "... " << std::flush;
    debug.suspend();
    timer.reset();
    solver.visualize(*solution,
                     paramTree.sub(SolverType::id).sub("visualize").get("filename", id + ".solution"),
                     paramTree.sub(SolverType::id).sub("visualize").get("name", "solution"),
                     "  ",
                     debug);
//    referenceSolver.visualize(*referenceSolution,
//                              paramTree.sub(SolverType::id).sub("visualize").get("filename", id + ".solution") + "_reference",
//                              paramTree.sub(SolverType::id).sub("visualize").get("name", "solution") + "_reference",
//                              "  ",
//                              debug);
    debug.resume();
    info << "done (took " << timer.elapsed() << " sec)" << std::endl;

    info << "computing norms:" << std::endl;
    Dune::shared_ptr< typename SolverType::DiscreteFunctionType > discreteSolution = solver.createDiscreteFunction(*solution, "discrete_solution");
    compute_errors(paramTree.sub(id).sub("exact_solution"),
                   *discreteSolution,
                   info, "  ");
    // if we came that far we can as well be happy about it
    return 0;
  } catch(Dune::Exception& e) {
    std::cerr << "Dune reported error: " << e.what() << std::endl;
  } catch(std::exception& e) {
    std::cerr << e.what() << std::endl;
  } catch( ... ) {
    std::cerr << "Unknown exception thrown!" << std::endl;
  } // try
} // main
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "StrategyOFGPara.h"
#include "MType.h"

/*
Global Top-k & bound
*/

using namespace std;

void StrategyOFGPara::topKCoordinate()
{
	// TODO: make it total asynchronous (remove rph.input(...), send if there is a recent local-k change, broadcast if global k-th changes, change INTERVAL_COORDINATE_TOP_K smaller as a buffer timer)
	//ostringstream oss;
	//auto tt = holder->getScore();
	//oss << logHeadID("GTK-Coord") << tt.size() << " { ";
	//for(auto& v : tt)
	//	oss << v << " ";
	//oss << "}";
	//cout << oss.str() << endl;
	if(net->id() != MASTER_ID) {
		// On workers: send local top-k to master
		++st.topkSend;
		net->send(MASTER_ID, MType::GGatherLocalTopK, holder->getScore());
		// the rest calculattion work will be done by master
		// global top-k will be received later and handled by cbUpdateLowerBound()
	} else {
		// On master: initialize current local top-k
		globalTopKScores.update(holder->getScore(), net->id());
		// then wait for workers' GGatherLocalTopK message and
		//   process them with cbLocalTopK()
		rph.input(MType::GGatherLocalTopK, net->id());
		// after received the GGatherLocalTopK messages from all the workers,
		//   finish this process with topKCoordinateFinish
	}
}

void StrategyOFGPara::topKCoordinateFinish()
{
	rph.resetTypeCondition(MType::GGatherLocalTopK);
	if(globalTopKScores.full()) {
		updateLowerBound(globalTopKScores.lowest(), true, true);
		// update message will not send to master, so result is not updated
		updateLBResult(globalBound);
	}
//	cout << logHead("LOG") + "Global top-k coordination finished, LB="
//		+ to_string(globalBound) << endl;
}

void StrategyOFGPara::topKMerge(const std::vector<double>& recv, const int source)
{
	lock_guard<mutex> lg(mgtk);
	globalTopKScores.update(recv, source);
}

// -------------- Lower Bound Maintaince ----------------

void StrategyOFGPara::initLowerBound()
{
	// move lb down half a unit to accept every thing at the beginning
	//double lb = get<1>(edges.back()) - 0.5 / pgp->size();
	updateLowerBound(0.0, false, false);
}

void StrategyOFGPara::updateLowerBound(double newLB, bool modifyTables, bool fromLocal) {
	// this epsilon checking is IMPORTANT for those with equal score to the k-th.
	//   because in float numbers: (3.0/100 - 2.0/100) > (2.0/100 - 1.0/100)
	// this method may loose the bound but does not lose anyone qualified
	//newLB -= numeric_limits<double>::epsilon();
	if(newLB > globalBound) {
		st.progBound.emplace_back(timer.elapseMS(), newLB);
		globalBound = newLB;
		updateLBCandEdge(newLB);
		if(modifyTables)
			updateLBWaitingMotifs(newLB);
//		cout << logHeadID("DBG") + "LB changed to " + to_string(globalBound)
//			+ (fromLocal ? " by local" : " by remote") << endl;
		if(fromLocal) {
			lowerBoundSend();
		} else {
			updateLBResult(newLB);
		}
	}/* else if(fromLocal) {
		ostringstream oss;
		oss.precision(200);
		oss << logHeadID("XXXX") << "CMP: "<< (newLB > globalBound)<<" Diff: " << newLB - globalBound;
		cout << oss.str() << endl;
	}*/
}

int StrategyOFGPara::updateLBCandEdge(double newLB)
{
	lock_guard<mutex> lg(mce);
	auto it = upper_bound(edges.begin(), edges.end(), newLB,
		[](double th, const tuple<Edge, double, int>& p) {
		return th > get<1>(p);
	});
	int num = distance(it, edges.end());
	edges.erase(it, edges.end());
	return num;
}

int StrategyOFGPara::updateLBResult(double newLB)
{
	lock_guard<mutex> lg(mtk);
	return holder->updateBound(newLB);
}

int StrategyOFGPara::updateLBWaitingMotifs(double newLB)
{
	int size = net->size();
	int id = net->id();
	int count = ltable.updateLowerBound(newLB);
	for(int i = 0; i < size; ++i) {
		if(i != id) {
			rtables[i].updateLowerBound(newLB);
		}
	}
	return count;
}

void StrategyOFGPara::lowerBoundSend()
{
	++st.boundSend;
	net->broadcast(MType::GLowerBound, globalBound);
}

<commit_msg>support dces-b option for ofg-para strategy<commit_after>#include "stdafx.h"
#include "StrategyOFGPara.h"
#include "MType.h"

/*
Global Top-k & bound
*/

using namespace std;

void StrategyOFGPara::topKCoordinate()
{
	// TODO: make it total asynchronous (remove rph.input(...), send if there is a recent local-k change, broadcast if global k-th changes, change INTERVAL_COORDINATE_TOP_K smaller as a buffer timer)
	//ostringstream oss;
	//auto tt = holder->getScore();
	//oss << logHeadID("GTK-Coord") << tt.size() << " { ";
	//for(auto& v : tt)
	//	oss << v << " ";
	//oss << "}";
	//cout << oss.str() << endl;
	if(net->id() != MASTER_ID) {
		// On workers: send local top-k to master
		++st.topkSend;
		net->send(MASTER_ID, MType::GGatherLocalTopK, holder->getScore());
		// the rest calculattion work will be done by master
		// global top-k will be received later and handled by cbUpdateLowerBound()
	} else {
		// On master: initialize current local top-k
		globalTopKScores.update(holder->getScore(), net->id());
		// then wait for workers' GGatherLocalTopK message and
		//   process them with cbLocalTopK()
		rph.input(MType::GGatherLocalTopK, net->id());
		// after received the GGatherLocalTopK messages from all the workers,
		//   finish this process with topKCoordinateFinish
	}
}

void StrategyOFGPara::topKCoordinateFinish()
{
	rph.resetTypeCondition(MType::GGatherLocalTopK);
	if(globalTopKScores.full()) {
		updateLowerBound(globalTopKScores.lowest(), true, true);
		// update message will not send to master, so result is not updated
		updateLBResult(globalBound);
	}
//	cout << logHead("LOG") + "Global top-k coordination finished, LB="
//		+ to_string(globalBound) << endl;
}

void StrategyOFGPara::topKMerge(const std::vector<double>& recv, const int source)
{
	lock_guard<mutex> lg(mgtk);
	globalTopKScores.update(recv, source);
}

// -------------- Lower Bound Maintaince ----------------

void StrategyOFGPara::initLowerBound()
{
	// move lb down half a unit to accept every thing at the beginning
	//double lb = get<1>(edges.back()) - 0.5 / pgp->size();
	updateLowerBound(0.0, false, false);
}

void StrategyOFGPara::updateLowerBound(double newLB, bool modifyTables, bool fromLocal) {
	// this epsilon checking is IMPORTANT for those with equal score to the k-th.
	//   because in float numbers: (3.0/100 - 2.0/100) > (2.0/100 - 1.0/100)
	// this method may loose the bound but does not lose anyone qualified
	//newLB -= numeric_limits<double>::epsilon();
	if(newLB > globalBound) {
		st.progBound.emplace_back(timer.elapseMS(), newLB);
		globalBound = newLB;
		if(flagDCESBound)
			updateLBCandEdge(newLB);
		if(modifyTables)
			updateLBWaitingMotifs(newLB);
//		cout << logHeadID("DBG") + "LB changed to " + to_string(globalBound)
//			+ (fromLocal ? " by local" : " by remote") << endl;
		if(fromLocal) {
			lowerBoundSend();
		} else {
			updateLBResult(newLB);
		}
	}/* else if(fromLocal) {
		ostringstream oss;
		oss.precision(200);
		oss << logHeadID("XXXX") << "CMP: "<< (newLB > globalBound)<<" Diff: " << newLB - globalBound;
		cout << oss.str() << endl;
	}*/
}

int StrategyOFGPara::updateLBCandEdge(double newLB)
{
	lock_guard<mutex> lg(mce);
	auto it = upper_bound(edges.begin(), edges.end(), newLB,
		[](double th, const tuple<Edge, double, int>& p) {
		return th > get<1>(p);
	});
	int num = distance(it, edges.end());
	edges.erase(it, edges.end());
	return num;
}

int StrategyOFGPara::updateLBResult(double newLB)
{
	lock_guard<mutex> lg(mtk);
	return holder->updateBound(newLB);
}

int StrategyOFGPara::updateLBWaitingMotifs(double newLB)
{
	int size = net->size();
	int id = net->id();
	int count = ltable.updateLowerBound(newLB);
	for(int i = 0; i < size; ++i) {
		if(i != id) {
			rtables[i].updateLowerBound(newLB);
		}
	}
	return count;
}

void StrategyOFGPara::lowerBoundSend()
{
	++st.boundSend;
	net->broadcast(MType::GLowerBound, globalBound);
}

<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip> // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple> // get<n>(xxx)
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set> // S.insert(M);
// if (S.find(key) != S.end()) { }
// for (auto it=S.begin(); it != S.end(); it++) { }
// auto it = S.lower_bound(M);
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib> // atoi(xxx)
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.
// insert #if<tab> by my emacs. #if DEBUG == 1 ... #end

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

ll power(ll a, ll n) {
  if (n == 0) {
    return 1;
  } else if (n%2 == 0) {
    ll x = power(a, n/2);
    return x * x;
  } else {
    return power(a, n-1) * a;
  }
}

ll N, A;

int main () {
  cin >> N >> A;
  ll ub = sqrt(N)+1;
  ll lb = 2;
  ll ans = N;
  for (auto i = 2; i < 1000; ++i) {
    if (power(2, i) > N) break;
    while (ub - lb > 1) {
      ll t = (ub + lb)/2;
      if (power(t, i) > N) {
        ub = t;
      } else {
        lb = t;
      }
    }
    // cerr << "i = " << i << ", lb = " << lb << endl;
    for (auto j = 0; j <= i; ++j) {
      if (power(lb, i-j) * power(lb+1, j) >= N) {
        ans = min(ans, lb * (i-j) + (lb+1) * j + A * (i-1));
        break;
      }
    }
    ub = lb;
    lb = 2;
  }
  cout << ans << endl;
}
<commit_msg>submit E.cpp to 'E - Cookies' (cf16-final-open) [C++14 (GCC 5.4.1)]<commit_after>#include <iostream>
#include <iomanip> // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple> // get<n>(xxx)
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set> // S.insert(M);
// if (S.find(key) != S.end()) { }
// for (auto it=S.begin(); it != S.end(); it++) { }
// auto it = S.lower_bound(M);
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib> // atoi(xxx)
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.
// insert #if<tab> by my emacs. #if DEBUG == 1 ... #end

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

ll power(ll a, ll n) {
  if (n == 0) {
    return 1;
  } else if (n%2 == 0) {
    ll x = power(a, n/2);
    return x * x;
  } else {
    return power(a, n-1) * a;
  }
}

ll N, A;

int main () {
  cin >> N >> A;
  ll ub = sqrt(N)+1;
  ll lb = 2;
  ll ans = N;
  for (auto i = 2; i < 1000; ++i) {
    if (power(2, i) > N) break;
    if (i == 2) {
      while (ub - lb > 1) {
        ll t = (ub + lb)/2;
        if (power(t, i) > N) {
          ub = t;
        } else {
          lb = t;
        }
      }
    } else {
      for (auto j = 1; j < 12000; ++j) {
        if (power(j, i) < N) {
          lb = j;
        } else {
          break;
        }
      }
    }
    // cerr << "i = " << i << ", lb = " << lb << endl;
    for (auto j = 0; j <= i; ++j) {
      if (power(lb, i-j) * power(lb+1, j) >= N) {
        ans = min(ans, lb * (i-j) + (lb+1) * j + A * (i-1));
        break;
      }
    }
    ub = lb;
    lb = 2;
  }
  cout << ans << endl;
}
<|endoftext|>


<commit_before>/* JEBBase: generic algorithms and functions
 * Copyright 2014 Jan Erik Breimo
 * All rights reserved.
 *
 * This file is distributed under the BSD License.
 * License text is included with the source distribution.
 */
#ifndef JEBBASE_ALGORITHMS_SORT_HPP
#define JEBBASE_ALGORITHMS_SORT_HPP

#include <utility>
#include "JEBBase/JEBBaseDefinitions.hpp"

namespace JEBBase { namespace Algorithms {

template <typename T>
void sort(T& a, T& b)
{
    if (b < a)
        std::swap(a, b);
}

template <typename T>
void sort(T& a, T& b, T& c)
{
    sort(a, b);
    sort(b, c);
    sort(a, b);
}

template <typename T>
void sort(T& a, T& b, T& c, T& d)
{
    sort(a, c);
    sort(b, d);
    sort(a, b);
    sort(c, d);
    sort(b, c);
}

template <typename T>
void sort(T (&a)[2])
{
    sort(a[0], a[1]);
}

template <typename T>
void sort(T (&a)[3])
{
    sort(a[0], a[1], a[2]);
}

template <typename T>
void sort(T (&a)[4])
{
    sort(a[0], a[1], a[2], a[3]);
}

}}

#endif
<commit_msg>Minor change<commit_after>/* JEBBase: generic algorithms and functions
 * Copyright 2014 Jan Erik Breimo
 * All rights reserved.
 *
 * This file is distributed under the BSD License.
 * License text is included with the source distribution.
 */
#ifndef JEBBASE_ALGORITHMS_SORT_HPP
#define JEBBASE_ALGORITHMS_SORT_HPP

#include <utility>
#include "JEBBase/JEBBaseDefinitions.hpp"

namespace JEBBase { namespace Algorithms {

template <typename T>
void sort(T& a, T& b)
{
    if (b < a)
        std::swap(a, b);
}

template <typename T>
void sort(T& a, T& b, T& c)
{
    sort(a, b);
    sort(b, c);
    sort(a, b);
}

template <typename T>
void sort(T& a, T& b, T& c, T& d)
{
    sort(a, b);
    sort(c, d);
    sort(a, c);
    sort(b, d);
    sort(b, c);
}

template <typename T>
void sort(T (&a)[2])
{
    sort(a[0], a[1]);
}

template <typename T>
void sort(T (&a)[3])
{
    sort(a[0], a[1], a[2]);
}

template <typename T>
void sort(T (&a)[4])
{
    sort(a[0], a[1], a[2], a[3]);
}

}}

#endif
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2017.  All rights reserved
 */
#include    "../../StroikaPreComp.h"

#include    <sys/types.h>
#include    <sys/stat.h>
#include    <fcntl.h>

#if     qPlatform_Windows
#include    <io.h>
#elif   qPlatform_POSIX
#include    <poll.h>
#include    <unistd.h>
#endif

#include    "../../Debug/AssertExternallySynchronizedLock.h"
#include    "../../Debug/Trace.h"
#include    "../../Execution/Common.h"
#include    "../../Execution/ErrNoException.h"
#include    "../../Execution/Exceptions.h"
#if     qPlatform_POSIX
#include    "ErrNoException.h"
#elif   qPlatform_Windows
#include    "../../Execution/Platform/Windows/Exception.h"
#endif
#include    "../../IO/FileAccessException.h"
#include    "../../Streams/BufferedInputStream.h"

#include    "FileInputStream.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Characters;
using   namespace   Stroika::Foundation::IO;
using   namespace   Stroika::Foundation::IO::FileSystem;

using   Execution::make_unique_lock;
using   Streams::InputStream;
using   Streams::SeekOffsetType;

#if     qPlatform_Windows
using   Execution::Platform::Windows::ThrowIfFalseGetLastError;
#endif

// Comment this in to turn on aggressive noisy DbgTrace in this module
//#define   USE_NOISY_TRACE_IN_THIS_MODULE_       1

/*
 ********************************************************************************
 **************************** FileSystem::FileInputStream ***********************
 ********************************************************************************
 */
class   FileInputStream::Rep_ : public InputStream<Byte>::_IRep, private Debug::AssertExternallySynchronizedLock {
public:
    Rep_ () = delete;
    Rep_ (const Rep_&) = delete;
    Rep_ (const String& fileName, SeekableFlag seekable)
        : fFD_ (-1)
        , fSeekable_ (seekable)
    {
        try {
#if     qPlatform_Windows
            errno_t e = ::_wsopen_s (&fFD_, fileName.c_str (), (O_RDONLY | O_BINARY), _SH_DENYNO, 0);
            if (e != 0) {
                Execution::errno_ErrorException::Throw (e);
            }
            ThrowIfFalseGetLastError (fFD_ != -1);
#else
            Execution::ThrowErrNoIfNegative (fFD_ = ::open (fileName.AsNarrowSDKString ().c_str (), O_RDONLY));
#endif
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
            DbgTrace (L"opened fd: %d", fFD_);
#endif
        }
        Stroika_Foundation_IO_FileAccessException_CATCH_REBIND_FILENAME_ACCCESS_HELPER(fileName, FileAccessMode::eRead);
    }
    Rep_ (FileDescriptorType fd, AdoptFDPolicy adoptFDPolicy, SeekableFlag seekable)
        : fFD_ (fd)
        , fSeekable_ (seekable)
        , fAdoptFDPolicy_ (adoptFDPolicy)
    {
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
        DbgTrace (L"attached fd: %d", fFD_);
#endif
    }
    ~Rep_ ()
    {
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
        Debug::TraceContextBumper ctx (L"FileInputStream::Rep_::~Rep_");
        if (fAdoptFDPolicy_ == AdoptFDPolicy::eCloseOnDestruction) {
            DbgTrace (L"closing %d", fFD_);
        }
#endif
        if (fAdoptFDPolicy_ == AdoptFDPolicy::eCloseOnDestruction) {
#if     qPlatform_Windows
            ::_close (fFD_);
#else
            ::close (fFD_);
#endif
        }
    }
    nonvirtual  Rep_& operator= (const Rep_&) = delete;

    virtual bool    IsSeekable () const override
    {
        return fSeekable_ == eSeekable;
    }
    virtual size_t  Read (Byte* intoStart, Byte* intoEnd) override
    {
        RequireNotNull (intoStart);
        RequireNotNull (intoEnd);
        Require (intoStart < intoEnd);
        size_t  nRequested  =   intoEnd - intoStart;
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
        Debug::TraceContextBumper ctx (L"FileInputStream::Rep_::Read");
        DbgTrace (L"(nRequested: %llu)", static_cast<unsigned long long> (nRequested));
#endif
        lock_guard<const AssertExternallySynchronizedLock> critSec { *this };
#if     qPlatform_Windows
        return static_cast<size_t> (Execution::ThrowErrNoIfNegative (::_read (fFD_, intoStart, Math::PinToMaxForType<unsigned int> (nRequested))));
#else
        return static_cast<size_t> (Execution::ThrowErrNoIfNegative (::read (fFD_, intoStart, nRequested)));
#endif
    }
    virtual Memory::Optional<size_t>  ReadSome (ElementType* intoStart, ElementType* intoEnd) override
    {
        Require ((intoStart == nullptr and intoEnd == nullptr) or (intoEnd - intoStart) >= 1);
#if     qPlatform_Windows && 0
        int oldFileFlags = ::fcntl (fFD_, F_GETFL, 0);
        if(fcntl(fFD_, F_SETFL, oldFileFlags | O_NONBLOCK))
            ;
        auto&&  cleanup =   Execution::Finally ([this] () noexcept {
            fcntl (fFD_, F_SETFL, oldFileFlags);
        });
#elif   qPlatform_POSIX
        pollfd  pollData { fFD_, POLLIN, 0 };
        int pollResult = ThrowErrNoIfNegative (Handle_ErrNoResultInterruption ([&]() { return ::poll (&pollData, 1, 0); }));
        Assert (pollResult >= 0);
        if (pollResult == 0) {
            return {};      // if no data available, return {}
        }
        else {
            // we don't know how much is available, but at least one byte. If not actually reading, just return 1
            if (intoStart == nullptr) {
                return 1;
            }
            else {
                // if there is data available, read as much as you can...
                return Read (intoStart, intoEnd);
            }
        }
#endif
        WeakAssert (false);
        // @todo - FIX TO REALLY CHECK
        return {};
    }
    virtual Streams::SeekOffsetType  GetReadOffset () const override
    {
        lock_guard<const AssertExternallySynchronizedLock> critSec { *this };
#if     qPlatform_Windows
        return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::_lseeki64 (fFD_, 0, SEEK_CUR)));
#elif   qPlatform_Linux
        return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek64 (fFD_, 0, SEEK_CUR)));
#else
        return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek (fFD_, 0, SEEK_CUR)));
#endif
    }
    virtual Streams::SeekOffsetType    SeekRead (Streams::Whence whence, Streams::SignedSeekOffsetType offset) override
    {
        using   namespace Streams;
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
        Debug::TraceContextBumper ctx (L"FileInputStream::Rep_::SeekRead");
        DbgTrace (L"(whence: %d, offset: %lld)", whence, static_cast<long long> (offset));
#endif
        lock_guard<const AssertExternallySynchronizedLock> critSec { *this };
        switch (whence) {
            case    Whence::eFromStart: {
                    if (offset < 0) {
                        Execution::Throw (std::range_error ("seek"));
                    }
#if     qPlatform_Windows
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::_lseeki64 (fFD_, offset, SEEK_SET)));
#elif   qPlatform_Linux
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek64 (fFD_, offset, SEEK_SET)));
#else
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek (fFD_, offset, SEEK_SET)));
#endif
                }
                break;
            case    Whence::eFromCurrent: {
#if     qPlatform_Windows
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::_lseeki64 (fFD_, offset, SEEK_CUR)));
#elif   qPlatform_Linux
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek64 (fFD_, offset, SEEK_CUR)));
#else
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek (fFD_, offset, SEEK_CUR)));
#endif
                }
                break;
            case    Whence::eFromEnd: {
#if     qPlatform_Windows
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::_lseeki64 (fFD_, offset, SEEK_END)));
#elif   qPlatform_Linux
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek64 (fFD_, offset, SEEK_END)));
#else
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek (fFD_, offset, SEEK_END)));
#endif
                }
                break;
        }
        RequireNotReached ();
        return 0;
    }

private:
    int             fFD_;
    SeekableFlag    fSeekable_;
    AdoptFDPolicy   fAdoptFDPolicy_{ AdoptFDPolicy::eCloseOnDestruction };
};

FileInputStream::FileInputStream (const String& fileName, SeekableFlag seekable)
    : inherited (make_shared<Rep_> (fileName, seekable))
{
}

FileInputStream::FileInputStream (FileDescriptorType fd, AdoptFDPolicy adoptFDPolicy, SeekableFlag seekable)
    : inherited (make_shared<Rep_> (fd, adoptFDPolicy, seekable))
{
}

InputStream<Byte>   FileInputStream::mk (const String& fileName, SeekableFlag seekable, BufferFlag bufferFlag)
{
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
    Debug::TraceContextBumper ctx (L"FileInputStream::mk");
    DbgTrace (L"(fileName: %s, seekable: %d, bufferFlag: %d)", fileName.c_str (), seekable, bufferFlag);
#endif
    InputStream<Byte>   in  =   FileInputStream (fileName, seekable);
    switch (bufferFlag) {
        case eBuffered:
            return Streams::BufferedInputStream<Byte> (in);
        case eUnbuffered:
            return in;
        default:
            AssertNotReached ();
            return in;
    }
}

InputStream<Byte>   FileInputStream::mk (FileDescriptorType fd, AdoptFDPolicy adoptFDPolicy, SeekableFlag seekable, BufferFlag bufferFlag)
{
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
    Debug::TraceContextBumper ctx (L"FileInputStream::mk");
    DbgTrace (L"(fd: %d, seekable: %d, bufferFlag: %d)", fd, seekable, bufferFlag);
#endif
    InputStream<Byte>   in  =   FileInputStream (fd, adoptFDPolicy, seekable);
    switch (bufferFlag) {
        case eBuffered:
            return Streams::BufferedInputStream<Byte> (in);
        case eUnbuffered:
            return in;
        default:
            AssertNotReached ();
            return in;
    }
}
<commit_msg>fixed problems with poll () usage<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2017.  All rights reserved
 */
#include    "../../StroikaPreComp.h"

#include    <sys/types.h>
#include    <sys/stat.h>
#include    <fcntl.h>

#if     qPlatform_Windows
#include    <io.h>
#elif   qPlatform_POSIX
#include    <poll.h>
#include    <unistd.h>
#endif

#include    "../../Debug/AssertExternallySynchronizedLock.h"
#include    "../../Debug/Trace.h"
#include    "../../Execution/Common.h"
#include    "../../Execution/ErrNoException.h"
#include    "../../Execution/Exceptions.h"
#if     qPlatform_POSIX
#include    "../../Execution/ErrNoException.h"
#elif   qPlatform_Windows
#include    "../../Execution/Platform/Windows/Exception.h"
#endif
#include    "../../IO/FileAccessException.h"
#include    "../../Streams/BufferedInputStream.h"

#include    "FileInputStream.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Characters;
using   namespace   Stroika::Foundation::IO;
using   namespace   Stroika::Foundation::IO::FileSystem;

using   Execution::make_unique_lock;
using   Streams::InputStream;
using   Streams::SeekOffsetType;

#if     qPlatform_Windows
using   Execution::Platform::Windows::ThrowIfFalseGetLastError;
#endif

// Comment this in to turn on aggressive noisy DbgTrace in this module
//#define   USE_NOISY_TRACE_IN_THIS_MODULE_       1

/*
 ********************************************************************************
 **************************** FileSystem::FileInputStream ***********************
 ********************************************************************************
 */
class   FileInputStream::Rep_ : public InputStream<Byte>::_IRep, private Debug::AssertExternallySynchronizedLock {
public:
    Rep_ () = delete;
    Rep_ (const Rep_&) = delete;
    Rep_ (const String& fileName, SeekableFlag seekable)
        : fFD_ (-1)
        , fSeekable_ (seekable)
    {
        try {
#if     qPlatform_Windows
            errno_t e = ::_wsopen_s (&fFD_, fileName.c_str (), (O_RDONLY | O_BINARY), _SH_DENYNO, 0);
            if (e != 0) {
                Execution::errno_ErrorException::Throw (e);
            }
            ThrowIfFalseGetLastError (fFD_ != -1);
#else
            Execution::ThrowErrNoIfNegative (fFD_ = ::open (fileName.AsNarrowSDKString ().c_str (), O_RDONLY));
#endif
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
            DbgTrace (L"opened fd: %d", fFD_);
#endif
        }
        Stroika_Foundation_IO_FileAccessException_CATCH_REBIND_FILENAME_ACCCESS_HELPER(fileName, FileAccessMode::eRead);
    }
    Rep_ (FileDescriptorType fd, AdoptFDPolicy adoptFDPolicy, SeekableFlag seekable)
        : fFD_ (fd)
        , fSeekable_ (seekable)
        , fAdoptFDPolicy_ (adoptFDPolicy)
    {
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
        DbgTrace (L"attached fd: %d", fFD_);
#endif
    }
    ~Rep_ ()
    {
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
        Debug::TraceContextBumper ctx (L"FileInputStream::Rep_::~Rep_");
        if (fAdoptFDPolicy_ == AdoptFDPolicy::eCloseOnDestruction) {
            DbgTrace (L"closing %d", fFD_);
        }
#endif
        if (fAdoptFDPolicy_ == AdoptFDPolicy::eCloseOnDestruction) {
#if     qPlatform_Windows
            ::_close (fFD_);
#else
            ::close (fFD_);
#endif
        }
    }
    nonvirtual  Rep_& operator= (const Rep_&) = delete;

    virtual bool    IsSeekable () const override
    {
        return fSeekable_ == eSeekable;
    }
    virtual size_t  Read (Byte* intoStart, Byte* intoEnd) override
    {
        RequireNotNull (intoStart);
        RequireNotNull (intoEnd);
        Require (intoStart < intoEnd);
        size_t  nRequested  =   intoEnd - intoStart;
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
        Debug::TraceContextBumper ctx (L"FileInputStream::Rep_::Read");
        DbgTrace (L"(nRequested: %llu)", static_cast<unsigned long long> (nRequested));
#endif
        lock_guard<const AssertExternallySynchronizedLock> critSec { *this };
#if     qPlatform_Windows
        return static_cast<size_t> (Execution::ThrowErrNoIfNegative (::_read (fFD_, intoStart, Math::PinToMaxForType<unsigned int> (nRequested))));
#else
        return static_cast<size_t> (Execution::ThrowErrNoIfNegative (::read (fFD_, intoStart, nRequested)));
#endif
    }
    virtual Memory::Optional<size_t>  ReadSome (ElementType* intoStart, ElementType* intoEnd) override
    {
        Require ((intoStart == nullptr and intoEnd == nullptr) or (intoEnd - intoStart) >= 1);
#if     qPlatform_Windows && 0
        int oldFileFlags = ::fcntl (fFD_, F_GETFL, 0);
        if(fcntl(fFD_, F_SETFL, oldFileFlags | O_NONBLOCK))
            ;
        auto&&  cleanup =   Execution::Finally ([this] () noexcept {
            fcntl (fFD_, F_SETFL, oldFileFlags);
        });
#elif   qPlatform_POSIX
        pollfd  pollData { fFD_, POLLIN, 0 };
        int pollResult = Execution::ThrowErrNoIfNegative (Execution::Handle_ErrNoResultInterruption ([&]() { return ::poll (&pollData, 1, 0); }));
        Assert (pollResult >= 0);
        if (pollResult == 0) {
            return {};      // if no data available, return {}
        }
        else {
            // we don't know how much is available, but at least one byte. If not actually reading, just return 1
            if (intoStart == nullptr) {
                return 1;
            }
            else {
                // if there is data available, read as much as you can...
                return Read (intoStart, intoEnd);
            }
        }
#endif
        WeakAssert (false);
        // @todo - FIX TO REALLY CHECK
        return {};
    }
    virtual Streams::SeekOffsetType  GetReadOffset () const override
    {
        lock_guard<const AssertExternallySynchronizedLock> critSec { *this };
#if     qPlatform_Windows
        return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::_lseeki64 (fFD_, 0, SEEK_CUR)));
#elif   qPlatform_Linux
        return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek64 (fFD_, 0, SEEK_CUR)));
#else
        return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek (fFD_, 0, SEEK_CUR)));
#endif
    }
    virtual Streams::SeekOffsetType    SeekRead (Streams::Whence whence, Streams::SignedSeekOffsetType offset) override
    {
        using   namespace Streams;
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
        Debug::TraceContextBumper ctx (L"FileInputStream::Rep_::SeekRead");
        DbgTrace (L"(whence: %d, offset: %lld)", whence, static_cast<long long> (offset));
#endif
        lock_guard<const AssertExternallySynchronizedLock> critSec { *this };
        switch (whence) {
            case    Whence::eFromStart: {
                    if (offset < 0) {
                        Execution::Throw (std::range_error ("seek"));
                    }
#if     qPlatform_Windows
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::_lseeki64 (fFD_, offset, SEEK_SET)));
#elif   qPlatform_Linux
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek64 (fFD_, offset, SEEK_SET)));
#else
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek (fFD_, offset, SEEK_SET)));
#endif
                }
                break;
            case    Whence::eFromCurrent: {
#if     qPlatform_Windows
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::_lseeki64 (fFD_, offset, SEEK_CUR)));
#elif   qPlatform_Linux
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek64 (fFD_, offset, SEEK_CUR)));
#else
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek (fFD_, offset, SEEK_CUR)));
#endif
                }
                break;
            case    Whence::eFromEnd: {
#if     qPlatform_Windows
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::_lseeki64 (fFD_, offset, SEEK_END)));
#elif   qPlatform_Linux
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek64 (fFD_, offset, SEEK_END)));
#else
                    return static_cast<Streams::SeekOffsetType> (Execution::ThrowErrNoIfNegative (::lseek (fFD_, offset, SEEK_END)));
#endif
                }
                break;
        }
        RequireNotReached ();
        return 0;
    }

private:
    int             fFD_;
    SeekableFlag    fSeekable_;
    AdoptFDPolicy   fAdoptFDPolicy_{ AdoptFDPolicy::eCloseOnDestruction };
};

FileInputStream::FileInputStream (const String& fileName, SeekableFlag seekable)
    : inherited (make_shared<Rep_> (fileName, seekable))
{
}

FileInputStream::FileInputStream (FileDescriptorType fd, AdoptFDPolicy adoptFDPolicy, SeekableFlag seekable)
    : inherited (make_shared<Rep_> (fd, adoptFDPolicy, seekable))
{
}

InputStream<Byte>   FileInputStream::mk (const String& fileName, SeekableFlag seekable, BufferFlag bufferFlag)
{
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
    Debug::TraceContextBumper ctx (L"FileInputStream::mk");
    DbgTrace (L"(fileName: %s, seekable: %d, bufferFlag: %d)", fileName.c_str (), seekable, bufferFlag);
#endif
    InputStream<Byte>   in  =   FileInputStream (fileName, seekable);
    switch (bufferFlag) {
        case eBuffered:
            return Streams::BufferedInputStream<Byte> (in);
        case eUnbuffered:
            return in;
        default:
            AssertNotReached ();
            return in;
    }
}

InputStream<Byte>   FileInputStream::mk (FileDescriptorType fd, AdoptFDPolicy adoptFDPolicy, SeekableFlag seekable, BufferFlag bufferFlag)
{
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
    Debug::TraceContextBumper ctx (L"FileInputStream::mk");
    DbgTrace (L"(fd: %d, seekable: %d, bufferFlag: %d)", fd, seekable, bufferFlag);
#endif
    InputStream<Byte>   in  =   FileInputStream (fd, adoptFDPolicy, seekable);
    switch (bufferFlag) {
        case eBuffered:
            return Streams::BufferedInputStream<Byte> (in);
        case eUnbuffered:
            return in;
        default:
            AssertNotReached ();
            return in;
    }
}
<|endoftext|>