<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef SVGWRITER_HXX
#define SVGWRITER_HXX

#include <cppuhelper/weak.hxx>
#include <rtl/ustring.hxx>
#include <tools/debug.hxx>
#include <tools/stream.hxx>
#include <tools/string.hxx>
#include <tools/urlobj.hxx>
#include <tools/stack.hxx>
#include <vcl/salbtype.hxx>
#include <vcl/gdimtf.hxx>
#include <vcl/metaact.hxx>
#include <vcl/metric.hxx>
#include <vcl/virdev.hxx>
#include <vcl/cvtgrf.hxx>
#include <vcl/graphictools.hxx>
#include <vcl/rendergraphicrasterizer.hxx>
#include <xmloff/xmlexp.hxx>
#include <xmloff/nmspmap.hxx>

#include <com/sun/star/uno/Reference.h>
#include <com/sun/star/uno/RuntimeException.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/registry/XRegistryKey.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/io/XInputStream.hpp>
#include <com/sun/star/io/XOutputStream.hpp>
#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
#include <com/sun/star/i18n/CharacterIteratorMode.hpp>
#include <com/sun/star/i18n/XBreakIterator.hpp>

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

#define _SVG_WRITE_EXTENTS      1
#undef _SVG_WRITE_TEXT_DESC
#undef _SVG_USE_CONFIG

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

#define NMSP_CPPU               cppu
#define NMSP_UNO                com::sun::star::uno
#define NMSP_LANG               com::sun::star::lang
#define NMSP_SAX                com::sun::star::xml::sax
#define NMSP_SVG                com::sun::star::svg
#define NMSP_REGISTRY           com::sun::star::registry

#define REF( _def_Obj )           NMSP_UNO::Reference< _def_Obj >
#define SEQ( _def_Obj )           NMSP_UNO::Sequence< _def_Obj >
#define B2UCONST( _def_pChar )    (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(_def_pChar )))
#define SVG_DTD_STRING            B2UCONST( "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">" )
#define SVG_TINY_DTD_STRING     B2UCONST( "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG Tiny 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd\">" )

#define SVGWRITER_WRITE_NONE    0x00000000
#define SVGWRITER_WRITE_FILL    0x00000001
#define SVGWRITER_WRITE_TEXT    0x00000002
#define SVGWRITER_NO_SHAPE_COMMENTS 0x01000000
#define SVGWRITER_WRITE_ALL     0xFFFFFFFF

// ----------------------
// - SVGAttributeWriter -
// ----------------------

class SVGActionWriter;
class SVGExport;
class SVGFontExport;

class SVGAttributeWriter
{
private:

    Font                       maCurFont;
    Color                      maCurLineColor;
    Color                      maCurFillColor;
    SVGExport&                 mrExport;
    SVGFontExport&             mrFontExport;
    SvXMLElementExport*        mpElemFont;
    SvXMLElementExport*        mpElemPaint;

                            SVGAttributeWriter();

    double                  ImplRound( double fVal, sal_Int32 nDecs = 3 );

public:

                            SVGAttributeWriter( SVGExport& rExport, SVGFontExport& rFontExport );
    virtual                 ~SVGAttributeWriter();

    ::rtl::OUString         GetFontStyle( const Font& rFont );
    ::rtl::OUString         GetPaintStyle( const Color& rLineColor, const Color& rFillColor, const LineInfo* pLineInfo );
    void                    AddColorAttr( const char* pColorAttrName, const char* pColorOpacityAttrName, const Color& rColor );
    void                    AddGradientDef( const Rectangle& rObjRect,const Gradient& rGradient, ::rtl::OUString& rGradientId );
    void                    AddPaintAttr( const Color& rLineColor, const Color& rFillColor,
                                          const Rectangle* pObjBoundRect = NULL, const Gradient* pFillGradient = NULL );

    void                    SetFontAttr( const Font& rFont );

    static void             ImplGetColorStr( const Color& rColor, ::rtl::OUString& rColorStr );
};

struct SVGShapeDescriptor
{
    PolyPolygon                 maShapePolyPoly;
    Color                       maShapeFillColor;
    Color                       maShapeLineColor;
    sal_Int32                   mnStrokeWidth;
    SvtGraphicStroke::DashArray maDashArray;
    ::std::auto_ptr< Gradient > mapShapeGradient;
    ::rtl::OUString             maId;

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

    SVGShapeDescriptor() :
        maShapeFillColor( Color( COL_TRANSPARENT ) ),
        maShapeLineColor( Color( COL_TRANSPARENT ) ),
        mnStrokeWidth( 0 )
    {
    }
};

// -------------------
// - SVGActionWriter -
// -------------------

class SVGAttributeWriter;
class SvXMLExport;
class GDIMetaFile;

class SVGActionWriter
{
private:

    sal_Int32                                   mnCurGradientId;
    sal_Int32                                   mnCurMaskId;
    sal_Int32                                   mnCurPatternId;
    Stack                                       maContextStack;
    ::std::auto_ptr< SVGShapeDescriptor >       mapCurShape;
    SVGExport&                                  mrExport;
    SVGFontExport&                              mrFontExport;
    SVGAttributeWriter*                         mpContext;
    VirtualDevice*                              mpVDev;
    MapMode                                     maTargetMapMode;
    sal_uInt32                                  mnInnerMtfCount;
    sal_Bool                                    mbDestroyVDev;
    sal_Bool                                    mbPaintAttrChanged;
    sal_Bool                                    mbFontAttrChanged;
    sal_Bool                                    mbClipAttrChanged;
    sal_Bool                                    mbIsPlacehlolderShape;

    SVGAttributeWriter*     ImplAcquireContext() { maContextStack.Push( mpContext = new SVGAttributeWriter( mrExport, mrFontExport ) ); return mpContext; }
    void                    ImplReleaseContext() { delete (SVGAttributeWriter*)    maContextStack.Pop(); mpContext = (SVGAttributeWriter*) maContextStack.Top(); }

    long                    ImplMap( sal_Int32 nVal ) const;
    Point&                  ImplMap( const Point& rPt, Point& rDstPt ) const;
    Size&                   ImplMap( const Size& rSz, Size& rDstSz ) const;
    Rectangle&              ImplMap( const Rectangle& rRect, Rectangle& rDstRect ) const;
    Polygon&                ImplMap( const Polygon& rPoly, Polygon& rDstPoly ) const;
    PolyPolygon&            ImplMap( const PolyPolygon& rPolyPoly, PolyPolygon& rDstPolyPoly ) const;

    void                    ImplWriteLine( const Point& rPt1, const Point& rPt2, const Color* pLineColor = NULL,
                                           sal_Bool bApplyMapping = sal_True );
    void                    ImplWriteRect( const Rectangle& rRect, long nRadX = 0, long nRadY = 0,
                                           sal_Bool bApplyMapping = sal_True );
    void                    ImplWriteEllipse( const Point& rCenter, long nRadX, long nRadY,
                                              sal_Bool bApplyMapping = sal_True );
    void                    ImplWritePattern( const PolyPolygon& rPolyPoly, const Hatch* pHatch, const Gradient* pGradient, sal_uInt32 nWriteFlags );
    void                    ImplWritePolyPolygon( const PolyPolygon& rPolyPoly, sal_Bool bLineOnly,
                                                  sal_Bool bApplyMapping = sal_True );
    void                    ImplWriteShape( const SVGShapeDescriptor& rShape, sal_Bool bApplyMapping = sal_True );
    void                    ImplWriteGradientEx( const PolyPolygon& rPolyPoly, const Gradient& rGradient, sal_uInt32 nWriteFlags,
                                                 sal_Bool bApplyMapping = sal_True );
    void                    ImplWriteGradientLinear( const PolyPolygon& rPolyPoly, const Gradient& rGradient );
    void                    ImplWriteGradientStop( const Color& rColor, double fOffset );
    Color                   ImplGetColorWithIntensity( const Color& rColor, sal_uInt16 nIntensity );
    Color                   ImplGetGradientColor( const Color& rStartColor, const Color& rEndColor, double fOffset );
    void                    ImplWriteMask( GDIMetaFile& rMtf, const Point& rDestPt, const Size& rDestSize, const Gradient& rGradient, sal_uInt32 nWriteFlags );
    void                    ImplWriteText( const Point& rPos, const String& rText, const sal_Int32* pDXArray, long nWidth, sal_Bool bApplyMapping = sal_True );
    void                    ImplWriteText( const Point& rPos, const String& rText, const sal_Int32* pDXArray, long nWidth, Color aTextColor, sal_Bool bApplyMapping );
    void                    ImplWriteBmp( const BitmapEx& rBmpEx, const Point& rPt, const Size& rSz, const Point& rSrcPt, const Size& rSrcSz,
                                          sal_Bool bApplyMapping = sal_True );

    void                    ImplCheckFontAttributes();
    void                    ImplCheckPaintAttributes();

    void                    ImplWriteActions( const GDIMetaFile& rMtf, sal_uInt32 nWriteFlags, const ::rtl::OUString* pElementId );

public:

    static ::rtl::OUString  GetPathString( const PolyPolygon& rPolyPoly, sal_Bool bLine );

public:

                            SVGActionWriter( SVGExport& rExport, SVGFontExport& rFontExport );
    virtual                 ~SVGActionWriter();

    void                    WriteMetaFile( const Point& rPos100thmm,
                                           const Size& rSize100thmm,
                                           const GDIMetaFile& rMtf,
                                           sal_uInt32 nWriteFlags,
                                           const ::rtl::OUString* pElementId = NULL );
};

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Replace Stack with std::stack< SVGAttributeWriter* ><commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef SVGWRITER_HXX
#define SVGWRITER_HXX

#include <stack>
#include <cppuhelper/weak.hxx>
#include <rtl/ustring.hxx>
#include <tools/debug.hxx>
#include <tools/stream.hxx>
#include <tools/string.hxx>
#include <tools/urlobj.hxx>
#include <vcl/salbtype.hxx>
#include <vcl/gdimtf.hxx>
#include <vcl/metaact.hxx>
#include <vcl/metric.hxx>
#include <vcl/virdev.hxx>
#include <vcl/cvtgrf.hxx>
#include <vcl/graphictools.hxx>
#include <vcl/rendergraphicrasterizer.hxx>
#include <xmloff/xmlexp.hxx>
#include <xmloff/nmspmap.hxx>

#include <com/sun/star/uno/Reference.h>
#include <com/sun/star/uno/RuntimeException.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/registry/XRegistryKey.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/io/XInputStream.hpp>
#include <com/sun/star/io/XOutputStream.hpp>
#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
#include <com/sun/star/i18n/CharacterIteratorMode.hpp>
#include <com/sun/star/i18n/XBreakIterator.hpp>

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

#define _SVG_WRITE_EXTENTS      1
#undef _SVG_WRITE_TEXT_DESC
#undef _SVG_USE_CONFIG

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

#define NMSP_CPPU               cppu
#define NMSP_UNO                com::sun::star::uno
#define NMSP_LANG               com::sun::star::lang
#define NMSP_SAX                com::sun::star::xml::sax
#define NMSP_SVG                com::sun::star::svg
#define NMSP_REGISTRY           com::sun::star::registry

#define REF( _def_Obj )           NMSP_UNO::Reference< _def_Obj >
#define SEQ( _def_Obj )           NMSP_UNO::Sequence< _def_Obj >
#define B2UCONST( _def_pChar )    (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(_def_pChar )))
#define SVG_DTD_STRING            B2UCONST( "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">" )
#define SVG_TINY_DTD_STRING     B2UCONST( "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG Tiny 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd\">" )

#define SVGWRITER_WRITE_NONE    0x00000000
#define SVGWRITER_WRITE_FILL    0x00000001
#define SVGWRITER_WRITE_TEXT    0x00000002
#define SVGWRITER_NO_SHAPE_COMMENTS 0x01000000
#define SVGWRITER_WRITE_ALL     0xFFFFFFFF

// ----------------------
// - SVGAttributeWriter -
// ----------------------

class SVGActionWriter;
class SVGExport;
class SVGFontExport;

class SVGAttributeWriter
{
private:

    Font                       maCurFont;
    Color                      maCurLineColor;
    Color                      maCurFillColor;
    SVGExport&                 mrExport;
    SVGFontExport&             mrFontExport;
    SvXMLElementExport*        mpElemFont;
    SvXMLElementExport*        mpElemPaint;

                            SVGAttributeWriter();

    double                  ImplRound( double fVal, sal_Int32 nDecs = 3 );

public:

                            SVGAttributeWriter( SVGExport& rExport, SVGFontExport& rFontExport );
    virtual                 ~SVGAttributeWriter();

    ::rtl::OUString         GetFontStyle( const Font& rFont );
    ::rtl::OUString         GetPaintStyle( const Color& rLineColor, const Color& rFillColor, const LineInfo* pLineInfo );
    void                    AddColorAttr( const char* pColorAttrName, const char* pColorOpacityAttrName, const Color& rColor );
    void                    AddGradientDef( const Rectangle& rObjRect,const Gradient& rGradient, ::rtl::OUString& rGradientId );
    void                    AddPaintAttr( const Color& rLineColor, const Color& rFillColor,
                                          const Rectangle* pObjBoundRect = NULL, const Gradient* pFillGradient = NULL );

    void                    SetFontAttr( const Font& rFont );

    static void             ImplGetColorStr( const Color& rColor, ::rtl::OUString& rColorStr );
};

struct SVGShapeDescriptor
{
    PolyPolygon                 maShapePolyPoly;
    Color                       maShapeFillColor;
    Color                       maShapeLineColor;
    sal_Int32                   mnStrokeWidth;
    SvtGraphicStroke::DashArray maDashArray;
    ::std::auto_ptr< Gradient > mapShapeGradient;
    ::rtl::OUString             maId;

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

    SVGShapeDescriptor() :
        maShapeFillColor( Color( COL_TRANSPARENT ) ),
        maShapeLineColor( Color( COL_TRANSPARENT ) ),
        mnStrokeWidth( 0 )
    {
    }
};

// -------------------
// - SVGActionWriter -
// -------------------

class SVGAttributeWriter;
class SvXMLExport;
class GDIMetaFile;

class SVGActionWriter
{
private:

    sal_Int32                                   mnCurGradientId;
    sal_Int32                                   mnCurMaskId;
    sal_Int32                                   mnCurPatternId;
    ::std::stack< SVGAttributeWriter* >         maContextStack;
    ::std::auto_ptr< SVGShapeDescriptor >       mapCurShape;
    SVGExport&                                  mrExport;
    SVGFontExport&                              mrFontExport;
    SVGAttributeWriter*                         mpContext;
    VirtualDevice*                              mpVDev;
    MapMode                                     maTargetMapMode;
    sal_uInt32                                  mnInnerMtfCount;
    sal_Bool                                    mbDestroyVDev;
    sal_Bool                                    mbPaintAttrChanged;
    sal_Bool                                    mbFontAttrChanged;
    sal_Bool                                    mbClipAttrChanged;
    sal_Bool                                    mbIsPlacehlolderShape;

    SVGAttributeWriter*     ImplAcquireContext()
    {
        maContextStack.push( mpContext = new SVGAttributeWriter( mrExport, mrFontExport ) );
        return mpContext;
    }
    void                    ImplReleaseContext()
    {
        delete maContextStack.top();
        maContextStack.pop();
        mpContext = maContextStack.top();
    }

    long                    ImplMap( sal_Int32 nVal ) const;
    Point&                  ImplMap( const Point& rPt, Point& rDstPt ) const;
    Size&                   ImplMap( const Size& rSz, Size& rDstSz ) const;
    Rectangle&              ImplMap( const Rectangle& rRect, Rectangle& rDstRect ) const;
    Polygon&                ImplMap( const Polygon& rPoly, Polygon& rDstPoly ) const;
    PolyPolygon&            ImplMap( const PolyPolygon& rPolyPoly, PolyPolygon& rDstPolyPoly ) const;

    void                    ImplWriteLine( const Point& rPt1, const Point& rPt2, const Color* pLineColor = NULL,
                                           sal_Bool bApplyMapping = sal_True );
    void                    ImplWriteRect( const Rectangle& rRect, long nRadX = 0, long nRadY = 0,
                                           sal_Bool bApplyMapping = sal_True );
    void                    ImplWriteEllipse( const Point& rCenter, long nRadX, long nRadY,
                                              sal_Bool bApplyMapping = sal_True );
    void                    ImplWritePattern( const PolyPolygon& rPolyPoly, const Hatch* pHatch, const Gradient* pGradient, sal_uInt32 nWriteFlags );
    void                    ImplWritePolyPolygon( const PolyPolygon& rPolyPoly, sal_Bool bLineOnly,
                                                  sal_Bool bApplyMapping = sal_True );
    void                    ImplWriteShape( const SVGShapeDescriptor& rShape, sal_Bool bApplyMapping = sal_True );
    void                    ImplWriteGradientEx( const PolyPolygon& rPolyPoly, const Gradient& rGradient, sal_uInt32 nWriteFlags,
                                                 sal_Bool bApplyMapping = sal_True );
    void                    ImplWriteGradientLinear( const PolyPolygon& rPolyPoly, const Gradient& rGradient );
    void                    ImplWriteGradientStop( const Color& rColor, double fOffset );
    Color                   ImplGetColorWithIntensity( const Color& rColor, sal_uInt16 nIntensity );
    Color                   ImplGetGradientColor( const Color& rStartColor, const Color& rEndColor, double fOffset );
    void                    ImplWriteMask( GDIMetaFile& rMtf, const Point& rDestPt, const Size& rDestSize, const Gradient& rGradient, sal_uInt32 nWriteFlags );
    void                    ImplWriteText( const Point& rPos, const String& rText, const sal_Int32* pDXArray, long nWidth, sal_Bool bApplyMapping = sal_True );
    void                    ImplWriteText( const Point& rPos, const String& rText, const sal_Int32* pDXArray, long nWidth, Color aTextColor, sal_Bool bApplyMapping );
    void                    ImplWriteBmp( const BitmapEx& rBmpEx, const Point& rPt, const Size& rSz, const Point& rSrcPt, const Size& rSrcSz,
                                          sal_Bool bApplyMapping = sal_True );

    void                    ImplCheckFontAttributes();
    void                    ImplCheckPaintAttributes();

    void                    ImplWriteActions( const GDIMetaFile& rMtf, sal_uInt32 nWriteFlags, const ::rtl::OUString* pElementId );

public:

    static ::rtl::OUString  GetPathString( const PolyPolygon& rPolyPoly, sal_Bool bLine );

public:

                            SVGActionWriter( SVGExport& rExport, SVGFontExport& rFontExport );
    virtual                 ~SVGActionWriter();

    void                    WriteMetaFile( const Point& rPos100thmm,
                                           const Size& rSize100thmm,
                                           const GDIMetaFile& rMtf,
                                           sal_uInt32 nWriteFlags,
                                           const ::rtl::OUString* pElementId = NULL );
};

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#include "native-stack.hh"
#include "native-stack-impl.hh"
#include "net.hh"
#include "ip.hh"
#include "tcp-stack.hh"
#include "udp.hh"
#include "virtio.hh"
#include "xenfront.hh"
#include "proxy.hh"
#include "dhcp.hh"
#include <memory>
#include <queue>
#ifdef HAVE_OSV
#include <osv/firmware.hh>
#include <gnu/libc-version.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

namespace net {

// native_network_stack
class native_network_stack : public network_stack {
    static std::unique_ptr<native_network_stack> _s;
    interface _netif;
    ipv4 _inet;
    udp_v4 _udp;
    bool _dhcp = false;
    promise<> _config;
    timer _timer;

    void on_dhcp(bool, const dhcp::lease &);

    using tcp4 = tcp<ipv4_traits>;
public:
    explicit native_network_stack(boost::program_options::variables_map opts);
    virtual server_socket listen(socket_address sa, listen_options opt) override;
    virtual udp_channel make_udp_channel(ipv4_addr addr) override;
    virtual future<> initialize() override;
    static std::unique_ptr<network_stack> create(boost::program_options::variables_map opts) {
        return std::make_unique<native_network_stack>(opts);
    }
    friend class native_server_socket_impl<tcp4>;
};

udp_channel
native_network_stack::make_udp_channel(ipv4_addr addr) {
    return _udp.make_channel(addr);
}

enum class xen_info {
    nonxen = 0,
    userspace = 1,
    osv = 2,
};

#ifdef HAVE_XEN
static xen_info is_xen()
{
    struct stat buf;
    if (!stat("/proc/xen", &buf) || !stat("/dev/xen", &buf)) {
        return xen_info::userspace;
    }

#ifdef HAVE_OSV
    const char *str = gnu_get_libc_release();
    if (std::string("OSv") != str) {
        return xen_info::nonxen;
    }
    auto firmware = osv::firmware_vendor();
    if (firmware == "Xen") {
        return xen_info::osv;
    }
#endif

    return xen_info::nonxen;
}
#endif

std::unique_ptr<net::device> create_native_net_device(boost::program_options::variables_map opts) {

    if (!smp::main_thread()) {
        return create_proxy_net_device(opts);
    }

#ifdef HAVE_XEN
    auto xen = is_xen();
    if (xen != xen_info::nonxen) {
        return xen::create_xenfront_net_device(opts, xen == xen_info::userspace);
    }
#endif
    return create_virtio_net_device(opts["tap-device"].as<std::string>(), opts);
}

void
add_native_net_options_description(boost::program_options::options_description &opts) {

#ifdef HAVE_XEN
    auto xen = is_xen();
    if (xen != xen_info::nonxen) {
        opts.add(xen::get_xenfront_net_options_description());
        return;
    }
#endif
    opts.add(get_virtio_net_options_description());
}

native_network_stack::native_network_stack(boost::program_options::variables_map opts)
    : _netif(create_native_net_device(opts))
    , _inet(&_netif)
    , _udp(_inet) {
    _inet.set_host_address(ipv4_address(opts["host-ipv4-addr"].as<std::string>()));
    _inet.set_gw_address(ipv4_address(opts["gw-ipv4-addr"].as<std::string>()));
    _inet.set_netmask_address(ipv4_address(opts["netmask-ipv4-addr"].as<std::string>()));
    _udp.set_queue_size(opts["udpv4-queue-size"].as<int>());
    _dhcp = opts["host-ipv4-addr"].defaulted()
            && opts["gw-ipv4-addr"].defaulted()
            && opts["netmask-ipv4-addr"].defaulted() && opts["dhcp"].as<bool>();
}

server_socket
native_network_stack::listen(socket_address sa, listen_options opts) {
    assert(sa.as_posix_sockaddr().sa_family == AF_INET);
    return tcpv4_listen(_inet.get_tcp(), ntohs(sa.as_posix_sockaddr_in().sin_port), opts);
}

void native_network_stack::on_dhcp(bool success, const dhcp::lease & res) {
    if (success) {
        _inet.set_host_address(res.ip);
        _inet.set_gw_address(res.gateway);
        _inet.set_netmask_address(res.netmask);
    }

    // Signal waiters.
    _config.set_value();

    if (smp::main_thread()) {
        // And the other cpus, which, in the case of initial discovery,
        // will be waiting for us.
        for (unsigned i = 1; i < smp::count; i++) {
            smp::submit_to(i, [success, res]() {
                auto & ns = static_cast<native_network_stack&>(engine.net());
                ns.on_dhcp(success, res);
            });
        }
        // And set up to renew the lease later on.
        _timer.set_callback([this, res]() {
            shared_ptr<dhcp> d = make_shared<dhcp>(_inet);
            d->renew(res).then([this, d](bool success, const dhcp::lease & res) {
                on_dhcp(success, res);
            });
        });
        _timer.arm(std::chrono::duration_cast<clock_type::duration>(res.lease_time));
    }
}

future<> native_network_stack::initialize() {
    return network_stack::initialize().then([this]() {
        if (!_dhcp) {
            return make_ready_future();
        }
        // Only run actual discover on main cpu.
        // All other cpus must simply for main thread to complete and signal them.
        if (smp::main_thread()) {
            shared_ptr<dhcp> d = make_shared<dhcp>(_inet);
            return d->discover().then([this, d](bool success, const dhcp::lease & res) {
                on_dhcp(success, res);
            });
        }
        return _config.get_future();
    });
}

std::unique_ptr<native_network_stack> native_network_stack::_s;

boost::program_options::options_description nns_options() {
    boost::program_options::options_description opts(
            "Native networking stack options");
    opts.add_options()
        ("tap-device",
                boost::program_options::value<std::string>()->default_value("tap0"),
                "tap device to connect to")
        ("host-ipv4-addr",
                boost::program_options::value<std::string>()->default_value("192.168.122.2"),
                "static IPv4 address to use")
        ("gw-ipv4-addr",
                boost::program_options::value<std::string>()->default_value("192.168.122.1"),
                "static IPv4 gateway to use")
        ("netmask-ipv4-addr",
                boost::program_options::value<std::string>()->default_value("255.255.255.0"),
                "static IPv4 netmask to use")
        ("udpv4-queue-size",
                boost::program_options::value<int>()->default_value(udp_v4::default_queue_size),
                "Default size of the UDPv4 per-channel packet queue")
        ("dhcp",
                boost::program_options::value<bool>()->default_value(true),
                        "Use DHCP discovery")
        ;

    add_native_net_options_description(opts);
    return opts;
}

network_stack_registrator nns_registrator{
    "native", nns_options(), native_network_stack::create
};

}
<commit_msg>dhcp: filter out DHCP failures<commit_after>/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#include "native-stack.hh"
#include "native-stack-impl.hh"
#include "net.hh"
#include "ip.hh"
#include "tcp-stack.hh"
#include "udp.hh"
#include "virtio.hh"
#include "xenfront.hh"
#include "proxy.hh"
#include "dhcp.hh"
#include <memory>
#include <queue>
#ifdef HAVE_OSV
#include <osv/firmware.hh>
#include <gnu/libc-version.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

namespace net {

// native_network_stack
class native_network_stack : public network_stack {
    static std::unique_ptr<native_network_stack> _s;
    interface _netif;
    ipv4 _inet;
    udp_v4 _udp;
    bool _dhcp = false;
    promise<> _config;
    timer _timer;

    void on_dhcp(bool, const dhcp::lease &);

    using tcp4 = tcp<ipv4_traits>;
public:
    explicit native_network_stack(boost::program_options::variables_map opts);
    virtual server_socket listen(socket_address sa, listen_options opt) override;
    virtual udp_channel make_udp_channel(ipv4_addr addr) override;
    virtual future<> initialize() override;
    static std::unique_ptr<network_stack> create(boost::program_options::variables_map opts) {
        return std::make_unique<native_network_stack>(opts);
    }
    friend class native_server_socket_impl<tcp4>;
};

udp_channel
native_network_stack::make_udp_channel(ipv4_addr addr) {
    return _udp.make_channel(addr);
}

enum class xen_info {
    nonxen = 0,
    userspace = 1,
    osv = 2,
};

#ifdef HAVE_XEN
static xen_info is_xen()
{
    struct stat buf;
    if (!stat("/proc/xen", &buf) || !stat("/dev/xen", &buf)) {
        return xen_info::userspace;
    }

#ifdef HAVE_OSV
    const char *str = gnu_get_libc_release();
    if (std::string("OSv") != str) {
        return xen_info::nonxen;
    }
    auto firmware = osv::firmware_vendor();
    if (firmware == "Xen") {
        return xen_info::osv;
    }
#endif

    return xen_info::nonxen;
}
#endif

std::unique_ptr<net::device> create_native_net_device(boost::program_options::variables_map opts) {

    if (!smp::main_thread()) {
        return create_proxy_net_device(opts);
    }

#ifdef HAVE_XEN
    auto xen = is_xen();
    if (xen != xen_info::nonxen) {
        return xen::create_xenfront_net_device(opts, xen == xen_info::userspace);
    }
#endif
    return create_virtio_net_device(opts["tap-device"].as<std::string>(), opts);
}

void
add_native_net_options_description(boost::program_options::options_description &opts) {

#ifdef HAVE_XEN
    auto xen = is_xen();
    if (xen != xen_info::nonxen) {
        opts.add(xen::get_xenfront_net_options_description());
        return;
    }
#endif
    opts.add(get_virtio_net_options_description());
}

native_network_stack::native_network_stack(boost::program_options::variables_map opts)
    : _netif(create_native_net_device(opts))
    , _inet(&_netif)
    , _udp(_inet) {
    _inet.set_host_address(ipv4_address(opts["host-ipv4-addr"].as<std::string>()));
    _inet.set_gw_address(ipv4_address(opts["gw-ipv4-addr"].as<std::string>()));
    _inet.set_netmask_address(ipv4_address(opts["netmask-ipv4-addr"].as<std::string>()));
    _udp.set_queue_size(opts["udpv4-queue-size"].as<int>());
    _dhcp = opts["host-ipv4-addr"].defaulted()
            && opts["gw-ipv4-addr"].defaulted()
            && opts["netmask-ipv4-addr"].defaulted() && opts["dhcp"].as<bool>();
}

server_socket
native_network_stack::listen(socket_address sa, listen_options opts) {
    assert(sa.as_posix_sockaddr().sa_family == AF_INET);
    return tcpv4_listen(_inet.get_tcp(), ntohs(sa.as_posix_sockaddr_in().sin_port), opts);
}

void native_network_stack::on_dhcp(bool success, const dhcp::lease & res) {
    if (!success) {
        return;
    }

    _inet.set_host_address(res.ip);
    _inet.set_gw_address(res.gateway);
    _inet.set_netmask_address(res.netmask);

    // Signal waiters.
    _config.set_value();

    if (smp::main_thread()) {
        // And the other cpus, which, in the case of initial discovery,
        // will be waiting for us.
        for (unsigned i = 1; i < smp::count; i++) {
            smp::submit_to(i, [success, res]() {
                auto & ns = static_cast<native_network_stack&>(engine.net());
                ns.on_dhcp(success, res);
            });
        }
        // And set up to renew the lease later on.
        _timer.set_callback([this, res]() {
            shared_ptr<dhcp> d = make_shared<dhcp>(_inet);
            d->renew(res).then([this, d](bool success, const dhcp::lease & res) {
                on_dhcp(success, res);
            });
        });
        _timer.arm(std::chrono::duration_cast<clock_type::duration>(res.lease_time));
    }
}

future<> native_network_stack::initialize() {
    return network_stack::initialize().then([this]() {
        if (!_dhcp) {
            return make_ready_future();
        }
        // Only run actual discover on main cpu.
        // All other cpus must simply for main thread to complete and signal them.
        if (smp::main_thread()) {
            shared_ptr<dhcp> d = make_shared<dhcp>(_inet);
            return d->discover().then([this, d](bool success, const dhcp::lease & res) {
                on_dhcp(success, res);
            });
        }
        return _config.get_future();
    });
}

std::unique_ptr<native_network_stack> native_network_stack::_s;

boost::program_options::options_description nns_options() {
    boost::program_options::options_description opts(
            "Native networking stack options");
    opts.add_options()
        ("tap-device",
                boost::program_options::value<std::string>()->default_value("tap0"),
                "tap device to connect to")
        ("host-ipv4-addr",
                boost::program_options::value<std::string>()->default_value("192.168.122.2"),
                "static IPv4 address to use")
        ("gw-ipv4-addr",
                boost::program_options::value<std::string>()->default_value("192.168.122.1"),
                "static IPv4 gateway to use")
        ("netmask-ipv4-addr",
                boost::program_options::value<std::string>()->default_value("255.255.255.0"),
                "static IPv4 netmask to use")
        ("udpv4-queue-size",
                boost::program_options::value<int>()->default_value(udp_v4::default_queue_size),
                "Default size of the UDPv4 per-channel packet queue")
        ("dhcp",
                boost::program_options::value<bool>()->default_value(true),
                        "Use DHCP discovery")
        ;

    add_native_net_options_description(opts);
    return opts;
}

network_stack_registrator nns_registrator{
    "native", nns_options(), native_network_stack::create
};

}
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////////
/// OpenGL Mathematics (glm.g-truc.net)
///
/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net)
/// Permission is hereby granted, free of charge, to any person obtaining a copy
/// of this software and associated documentation files (the "Software"), to deal
/// in the Software without restriction, including without limitation the rights
/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
/// copies of the Software, and to permit persons to whom the Software is
/// furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software.
///
/// Restrictions:
///		By making use of the Software for military purposes, you choose to make
///		a Bunny unhappy.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
/// THE SOFTWARE.
///
/// @ref gtc_round
/// @file glm/gtc/round.inl
/// @date 2014-11-03 / 2014-11-03
/// @author Christophe Riccio
///////////////////////////////////////////////////////////////////////////////////

namespace glm
{
namespace detail
{
	template <typename T, precision P, template <typename, precision> class vecType, bool compute = false>
	struct compute_ceilShift
	{
		GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & v, T)
		{
			return v;
		}
	};

	template <typename T, precision P, template <typename, precision> class vecType>
	struct compute_ceilShift<T, P, vecType, true>
	{
		GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & v, T Shift)
		{
			return v | (v >> Shift);
		}
	};

	template <typename T, precision P, template <typename, precision> class vecType, bool isSigned = true>
	struct compute_ceilPowerOfTwo
	{
		GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x)
		{
			GLM_STATIC_ASSERT(!std::numeric_limits<T>::is_iec559, "'ceilPowerOfTwo' only accept integer scalar or vector inputs");

			vecType<T, P> const Sign(sign(x));

			vecType<T, P> v(abs(x));

			v = v - static_cast<T>(1);
			v = v | (v >> static_cast<T>(1));
			v = v | (v >> static_cast<T>(2));
			v = v | (v >> static_cast<T>(4));
			v = compute_ceilShift<T, P, vecType, sizeof(T) >= 2>::call(v, 8);
			v = compute_ceilShift<T, P, vecType, sizeof(T) >= 4>::call(v, 16);
			v = compute_ceilShift<T, P, vecType, sizeof(T) >= 8>::call(v, 32);
			return (v + static_cast<T>(1)) * Sign;
		}
	};

	template <typename T, precision P, template <typename, precision> class vecType>
	struct compute_ceilPowerOfTwo<T, P, vecType, false>
	{
		GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x)
		{
			GLM_STATIC_ASSERT(!std::numeric_limits<T>::is_iec559, "'ceilPowerOfTwo' only accept integer scalar or vector inputs");

			vecType<T, P> v(x);

			v = v - static_cast<T>(1);
			v = v | (v >> static_cast<T>(1));
			v = v | (v >> static_cast<T>(2));
			v = v | (v >> static_cast<T>(4));
			v = compute_ceilShift<T, P, vecType, sizeof(T) >= 2>::call(v, 8);
			v = compute_ceilShift<T, P, vecType, sizeof(T) >= 4>::call(v, 16);
			v = compute_ceilShift<T, P, vecType, sizeof(T) >= 8>::call(v, 32);
			return v + static_cast<T>(1);
		}
	};

	template <bool is_float, bool is_signed>
	struct compute_ceilMultiple{};

	template <>
	struct compute_ceilMultiple<true, true>
	{
		template <typename genType>
		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
		{
			if(Source > genType(0))
			{
				genType Tmp = Source - genType(1);
				return Tmp + (Multiple - std::fmod(Tmp, Multiple));
			}
			else
				return Source + std::fmod(-Source, Multiple);
		}
	};

	template <>
	struct compute_ceilMultiple<false, false>
	{
		template <typename genType>
		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
		{
			genType Tmp = Source - genType(1);
			return Tmp + (Multiple - (Tmp % Multiple));
		}
	};

	template <>
	struct compute_ceilMultiple<false, true>
	{
		template <typename genType>
		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
		{
			if(Source > genType(0))
			{
				genType Tmp = Source - genType(1);
				return Tmp + (Multiple - (Tmp % Multiple));
			}
			else
				return Source + (-Source % Multiple);
		}
	};

	template <bool is_float, bool is_signed>
	struct compute_floorMultiple{};

	template <>
	struct compute_floorMultiple<true, true>
	{
		template <typename genType>
		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
		{
			if(Source >= genType(0))
				return Source - std::fmod(Source, Multiple);
			else
			{
				genType Tmp = Source + genType(1);
				return Tmp - std::fmod(Tmp, Multiple) - Multiple;
			}
		}
	};

	template <>
	struct compute_floorMultiple<false, false>
	{
		template <typename genType>
		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
		{
			if(Source >= genType(0))
				return Source - Source % Multiple;
			else
			{
				genType Tmp = Source + genType(1);
				return Tmp - Tmp % Multiple - Multiple;
			}
		}
	};

	template <>
	struct compute_floorMultiple<false, true>
	{
		template <typename genType>
		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
		{
			if(Source >= genType(0))
				return Source - Source % Multiple;
			else
			{
				genType Tmp = Source + genType(1);
				return Tmp - Tmp % Multiple - Multiple;
			}
		}
	};

	template <bool is_float, bool is_signed>
	struct compute_roundMultiple{};

	template <>
	struct compute_roundMultiple<true, true>
	{
		template <typename genType>
		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
		{
			if(Source >= genType(0))
				return Source - std::fmod(Source, Multiple);
			else
			{
				genType Tmp = Source + genType(1);
				return Tmp - std::fmod(Tmp, Multiple) - Multiple;
			}
		}
	};

	template <>
	struct compute_roundMultiple<false, false>
	{
		template <typename genType>
		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
		{
			if(Source >= genType(0))
				return Source - Source % Multiple;
			else
			{
				genType Tmp = Source + genType(1);
				return Tmp - Tmp % Multiple - Multiple;
			}
		}
	};

	template <>
	struct compute_roundMultiple<false, true>
	{
		template <typename genType>
		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
		{
			if(Source >= genType(0))
				return Source - Source % Multiple;
			else
			{
				genType Tmp = Source + genType(1);
				return Tmp - Tmp % Multiple - Multiple;
			}
		}
	};
}//namespace detail

	////////////////
	// isPowerOfTwo

	template <typename genType>
	GLM_FUNC_QUALIFIER bool isPowerOfTwo(genType Value)
	{
		genType const Result = glm::abs(Value);
		return !(Result & (Result - 1));
	}

	template <typename T, precision P, template <typename, precision> class vecType>
	GLM_FUNC_QUALIFIER vecType<bool, P> isPowerOfTwo(vecType<T, P> const & Value)
	{
		vecType<T, P> const Result(abs(Value));
		return equal(Result & (Result - 1), vecType<T, P>(0));
	}

	//////////////////
	// ceilPowerOfTwo

	template <typename genType>
	GLM_FUNC_QUALIFIER genType ceilPowerOfTwo(genType value)
	{
		return detail::compute_ceilPowerOfTwo<genType, defaultp, tvec1, std::numeric_limits<genType>::is_signed>::call(tvec1<genType, defaultp>(value)).x;
	}

	template <typename T, precision P, template <typename, precision> class vecType>
	GLM_FUNC_QUALIFIER vecType<T, P> ceilPowerOfTwo(vecType<T, P> const & v)
	{
		return detail::compute_ceilPowerOfTwo<T, P, vecType, std::numeric_limits<T>::is_signed>::call(v);
	}

	///////////////////
	// floorPowerOfTwo

	template <typename genType>
	GLM_FUNC_QUALIFIER genType floorPowerOfTwo(genType value)
	{
		return isPowerOfTwo(value) ? value : highestBitValue(value);
	}

	template <typename T, precision P, template <typename, precision> class vecType>
	GLM_FUNC_QUALIFIER vecType<T, P> floorPowerOfTwo(vecType<T, P> const & v)
	{
		return detail::functor1<T, T, P, vecType>::call(floorPowerOfTwo, v);
	}

	///////////////////
	// roundPowerOfTwo

	template <typename genIUType>
	GLM_FUNC_QUALIFIER genIUType roundPowerOfTwo(genIUType value)
	{
		if(isPowerOfTwo(value))
			return value;

		genIUType const prev = highestBitValue(value);
		genIUType const next = prev << 1;
		return (next - value) < (value - prev) ? next : prev;
	}

	template <typename T, precision P, template <typename, precision> class vecType>
	GLM_FUNC_QUALIFIER vecType<T, P> roundPowerOfTwo(vecType<T, P> const & v)
	{
		return detail::functor1<T, T, P, vecType>::call(roundPowerOfTwo, v);
	}

	////////////////
	// isMultiple

	template <typename genType>
	GLM_FUNC_QUALIFIER bool isMultiple(genType Value, genType Multiple)
	{
		return isMultiple(tvec1<genType>(Value), tvec1<genType>(Multiple)).x;
	}

	template <typename T, precision P, template <typename, precision> class vecType>
	GLM_FUNC_QUALIFIER vecType<bool, P> isMultiple(vecType<T, P> const & Value, T Multiple)
	{
		return (Value % Multiple) == vecType<T, P>(0);
	}

	template <typename T, precision P, template <typename, precision> class vecType>
	GLM_FUNC_QUALIFIER vecType<bool, P> isMultiple(vecType<T, P> const & Value, vecType<T, P> const & Multiple)
	{
		return (Value % Multiple) == vecType<T, P>(0);
	}

	//////////////////////
	// ceilMultiple

	template <typename genType>
	GLM_FUNC_QUALIFIER genType ceilMultiple(genType Source, genType Multiple)
	{
		return detail::compute_ceilMultiple<std::numeric_limits<genType>::is_iec559, std::numeric_limits<genType>::is_signed>::call(Source, Multiple);
	}

	template <typename T, precision P, template <typename, precision> class vecType>
	GLM_FUNC_QUALIFIER vecType<T, P> ceilMultiple(vecType<T, P> const & Source, vecType<T, P> const & Multiple)
	{
		return detail::functor2<T, P, vecType>::call(ceilMultiple, Source, Multiple);
	}

	//////////////////////
	// floorMultiple

	template <typename genType>
	GLM_FUNC_QUALIFIER genType floorMultiple(genType Source, genType Multiple)
	{
		return detail::compute_floorMultiple<std::numeric_limits<genType>::is_iec559, std::numeric_limits<genType>::is_signed>::call(Source, Multiple);
	}

	template <typename T, precision P, template <typename, precision> class vecType>
	GLM_FUNC_QUALIFIER vecType<T, P> floorMultiple(vecType<T, P> const & Source, vecType<T, P> const & Multiple)
	{
		return detail::functor2<T, P, vecType>::call(floorMultiple, Source, Multiple);
	}

	//////////////////////
	// roundMultiple

	template <typename genType>
	GLM_FUNC_QUALIFIER genType roundMultiple(genType Source, genType Multiple)
	{
		return detail::compute_roundMultiple<std::numeric_limits<genType>::is_iec559, std::numeric_limits<genType>::is_signed>::call(Source, Multiple);
	}

	template <typename T, precision P, template <typename, precision> class vecType>
	GLM_FUNC_QUALIFIER vecType<T, P> roundMultiple(vecType<T, P> const & Source, vecType<T, P> const & Multiple)
	{
		return detail::functor2<T, P, vecType>::call(roundMultiple, Source, Multiple);
	}
}//namespace glm
<commit_msg>Fix floorMultiple/ceilMultiple for float<commit_after>///////////////////////////////////////////////////////////////////////////////////
/// OpenGL Mathematics (glm.g-truc.net)
///
/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net)
/// Permission is hereby granted, free of charge, to any person obtaining a copy
/// of this software and associated documentation files (the "Software"), to deal
/// in the Software without restriction, including without limitation the rights
/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
/// copies of the Software, and to permit persons to whom the Software is
/// furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software.
///
/// Restrictions:
///		By making use of the Software for military purposes, you choose to make
///		a Bunny unhappy.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
/// THE SOFTWARE.
///
/// @ref gtc_round
/// @file glm/gtc/round.inl
/// @date 2014-11-03 / 2014-11-03
/// @author Christophe Riccio
///////////////////////////////////////////////////////////////////////////////////

namespace glm
{
namespace detail
{
	template <typename T, precision P, template <typename, precision> class vecType, bool compute = false>
	struct compute_ceilShift
	{
		GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & v, T)
		{
			return v;
		}
	};

	template <typename T, precision P, template <typename, precision> class vecType>
	struct compute_ceilShift<T, P, vecType, true>
	{
		GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & v, T Shift)
		{
			return v | (v >> Shift);
		}
	};

	template <typename T, precision P, template <typename, precision> class vecType, bool isSigned = true>
	struct compute_ceilPowerOfTwo
	{
		GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x)
		{
			GLM_STATIC_ASSERT(!std::numeric_limits<T>::is_iec559, "'ceilPowerOfTwo' only accept integer scalar or vector inputs");

			vecType<T, P> const Sign(sign(x));

			vecType<T, P> v(abs(x));

			v = v - static_cast<T>(1);
			v = v | (v >> static_cast<T>(1));
			v = v | (v >> static_cast<T>(2));
			v = v | (v >> static_cast<T>(4));
			v = compute_ceilShift<T, P, vecType, sizeof(T) >= 2>::call(v, 8);
			v = compute_ceilShift<T, P, vecType, sizeof(T) >= 4>::call(v, 16);
			v = compute_ceilShift<T, P, vecType, sizeof(T) >= 8>::call(v, 32);
			return (v + static_cast<T>(1)) * Sign;
		}
	};

	template <typename T, precision P, template <typename, precision> class vecType>
	struct compute_ceilPowerOfTwo<T, P, vecType, false>
	{
		GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x)
		{
			GLM_STATIC_ASSERT(!std::numeric_limits<T>::is_iec559, "'ceilPowerOfTwo' only accept integer scalar or vector inputs");

			vecType<T, P> v(x);

			v = v - static_cast<T>(1);
			v = v | (v >> static_cast<T>(1));
			v = v | (v >> static_cast<T>(2));
			v = v | (v >> static_cast<T>(4));
			v = compute_ceilShift<T, P, vecType, sizeof(T) >= 2>::call(v, 8);
			v = compute_ceilShift<T, P, vecType, sizeof(T) >= 4>::call(v, 16);
			v = compute_ceilShift<T, P, vecType, sizeof(T) >= 8>::call(v, 32);
			return v + static_cast<T>(1);
		}
	};

	template <bool is_float, bool is_signed>
	struct compute_ceilMultiple{};

	template <>
	struct compute_ceilMultiple<true, true>
	{
		template <typename genType>
		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
		{
			if(Source > genType(0))
				return Source + (Multiple - std::fmod(Source, Multiple));
			else
				return Source + std::fmod(-Source, Multiple);
		}
	};

	template <>
	struct compute_ceilMultiple<false, false>
	{
		template <typename genType>
		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
		{
			genType Tmp = Source - genType(1);
			return Tmp + (Multiple - (Tmp % Multiple));
		}
	};

	template <>
	struct compute_ceilMultiple<false, true>
	{
		template <typename genType>
		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
		{
			if(Source > genType(0))
			{
				genType Tmp = Source - genType(1);
				return Tmp + (Multiple - (Tmp % Multiple));
			}
			else
				return Source + (-Source % Multiple);
		}
	};

	template <bool is_float, bool is_signed>
	struct compute_floorMultiple{};

	template <>
	struct compute_floorMultiple<true, true>
	{
		template <typename genType>
		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
		{
			if(Source >= genType(0))
				return Source - std::fmod(Source, Multiple);
			else
				return Source - std::fmod(Source, Multiple) - Multiple;
		}
	};

	template <>
	struct compute_floorMultiple<false, false>
	{
		template <typename genType>
		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
		{
			if(Source >= genType(0))
				return Source - Source % Multiple;
			else
			{
				genType Tmp = Source + genType(1);
				return Tmp - Tmp % Multiple - Multiple;
			}
		}
	};

	template <>
	struct compute_floorMultiple<false, true>
	{
		template <typename genType>
		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
		{
			if(Source >= genType(0))
				return Source - Source % Multiple;
			else
			{
				genType Tmp = Source + genType(1);
				return Tmp - Tmp % Multiple - Multiple;
			}
		}
	};

	template <bool is_float, bool is_signed>
	struct compute_roundMultiple{};

	template <>
	struct compute_roundMultiple<true, true>
	{
		template <typename genType>
		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
		{
			if(Source >= genType(0))
				return Source - std::fmod(Source, Multiple);
			else
			{
				genType Tmp = Source + genType(1);
				return Tmp - std::fmod(Tmp, Multiple) - Multiple;
			}
		}
	};

	template <>
	struct compute_roundMultiple<false, false>
	{
		template <typename genType>
		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
		{
			if(Source >= genType(0))
				return Source - Source % Multiple;
			else
			{
				genType Tmp = Source + genType(1);
				return Tmp - Tmp % Multiple - Multiple;
			}
		}
	};

	template <>
	struct compute_roundMultiple<false, true>
	{
		template <typename genType>
		GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
		{
			if(Source >= genType(0))
				return Source - Source % Multiple;
			else
			{
				genType Tmp = Source + genType(1);
				return Tmp - Tmp % Multiple - Multiple;
			}
		}
	};
}//namespace detail

	////////////////
	// isPowerOfTwo

	template <typename genType>
	GLM_FUNC_QUALIFIER bool isPowerOfTwo(genType Value)
	{
		genType const Result = glm::abs(Value);
		return !(Result & (Result - 1));
	}

	template <typename T, precision P, template <typename, precision> class vecType>
	GLM_FUNC_QUALIFIER vecType<bool, P> isPowerOfTwo(vecType<T, P> const & Value)
	{
		vecType<T, P> const Result(abs(Value));
		return equal(Result & (Result - 1), vecType<T, P>(0));
	}

	//////////////////
	// ceilPowerOfTwo

	template <typename genType>
	GLM_FUNC_QUALIFIER genType ceilPowerOfTwo(genType value)
	{
		return detail::compute_ceilPowerOfTwo<genType, defaultp, tvec1, std::numeric_limits<genType>::is_signed>::call(tvec1<genType, defaultp>(value)).x;
	}

	template <typename T, precision P, template <typename, precision> class vecType>
	GLM_FUNC_QUALIFIER vecType<T, P> ceilPowerOfTwo(vecType<T, P> const & v)
	{
		return detail::compute_ceilPowerOfTwo<T, P, vecType, std::numeric_limits<T>::is_signed>::call(v);
	}

	///////////////////
	// floorPowerOfTwo

	template <typename genType>
	GLM_FUNC_QUALIFIER genType floorPowerOfTwo(genType value)
	{
		return isPowerOfTwo(value) ? value : highestBitValue(value);
	}

	template <typename T, precision P, template <typename, precision> class vecType>
	GLM_FUNC_QUALIFIER vecType<T, P> floorPowerOfTwo(vecType<T, P> const & v)
	{
		return detail::functor1<T, T, P, vecType>::call(floorPowerOfTwo, v);
	}

	///////////////////
	// roundPowerOfTwo

	template <typename genIUType>
	GLM_FUNC_QUALIFIER genIUType roundPowerOfTwo(genIUType value)
	{
		if(isPowerOfTwo(value))
			return value;

		genIUType const prev = highestBitValue(value);
		genIUType const next = prev << 1;
		return (next - value) < (value - prev) ? next : prev;
	}

	template <typename T, precision P, template <typename, precision> class vecType>
	GLM_FUNC_QUALIFIER vecType<T, P> roundPowerOfTwo(vecType<T, P> const & v)
	{
		return detail::functor1<T, T, P, vecType>::call(roundPowerOfTwo, v);
	}

	////////////////
	// isMultiple

	template <typename genType>
	GLM_FUNC_QUALIFIER bool isMultiple(genType Value, genType Multiple)
	{
		return isMultiple(tvec1<genType>(Value), tvec1<genType>(Multiple)).x;
	}

	template <typename T, precision P, template <typename, precision> class vecType>
	GLM_FUNC_QUALIFIER vecType<bool, P> isMultiple(vecType<T, P> const & Value, T Multiple)
	{
		return (Value % Multiple) == vecType<T, P>(0);
	}

	template <typename T, precision P, template <typename, precision> class vecType>
	GLM_FUNC_QUALIFIER vecType<bool, P> isMultiple(vecType<T, P> const & Value, vecType<T, P> const & Multiple)
	{
		return (Value % Multiple) == vecType<T, P>(0);
	}

	//////////////////////
	// ceilMultiple

	template <typename genType>
	GLM_FUNC_QUALIFIER genType ceilMultiple(genType Source, genType Multiple)
	{
		return detail::compute_ceilMultiple<std::numeric_limits<genType>::is_iec559, std::numeric_limits<genType>::is_signed>::call(Source, Multiple);
	}

	template <typename T, precision P, template <typename, precision> class vecType>
	GLM_FUNC_QUALIFIER vecType<T, P> ceilMultiple(vecType<T, P> const & Source, vecType<T, P> const & Multiple)
	{
		return detail::functor2<T, P, vecType>::call(ceilMultiple, Source, Multiple);
	}

	//////////////////////
	// floorMultiple

	template <typename genType>
	GLM_FUNC_QUALIFIER genType floorMultiple(genType Source, genType Multiple)
	{
		return detail::compute_floorMultiple<std::numeric_limits<genType>::is_iec559, std::numeric_limits<genType>::is_signed>::call(Source, Multiple);
	}

	template <typename T, precision P, template <typename, precision> class vecType>
	GLM_FUNC_QUALIFIER vecType<T, P> floorMultiple(vecType<T, P> const & Source, vecType<T, P> const & Multiple)
	{
		return detail::functor2<T, P, vecType>::call(floorMultiple, Source, Multiple);
	}

	//////////////////////
	// roundMultiple

	template <typename genType>
	GLM_FUNC_QUALIFIER genType roundMultiple(genType Source, genType Multiple)
	{
		return detail::compute_roundMultiple<std::numeric_limits<genType>::is_iec559, std::numeric_limits<genType>::is_signed>::call(Source, Multiple);
	}

	template <typename T, precision P, template <typename, precision> class vecType>
	GLM_FUNC_QUALIFIER vecType<T, P> roundMultiple(vecType<T, P> const & Source, vecType<T, P> const & Multiple)
	{
		return detail::functor2<T, P, vecType>::call(roundMultiple, Source, Multiple);
	}
}//namespace glm
<|endoftext|>


<commit_before>/*
 * Neuralnetwork.cpp
 *
 *  Created on: May 12, 2016
 *      Author: marija
 */

#include "Neuralnetwork.h"
#include <chrono>
using namespace std;

Neural_network::Neural_network(const vector<int> & init, double learning_rate, double acceptable_error):
		eta{learning_rate}, ok{acceptable_error}, config{init} {
	if (init.size() <= 2) throw runtime_error("Invalid initialization of neural network");
	num_layers = init.size();
	for (int i=0; i < num_layers; i++) {
		neurons_per_layer.push_back(init[i]);
	}
	/*add bias*/
	for (int i=0; i < num_layers-1; i++) {
		neurons_per_layer[i]++;
	}
	for (int i=0; i < num_layers; i++) {
		neurons_at_layer.push_back(vector<Neuron>(neurons_per_layer[i]));
	}
	build_network();
}

double Neural_network::generate_init_weight() {
	random_device rd;
	mt19937 gen(rd());
	uniform_real_distribution<> dist(0.1,1.0);
	return dist(gen);
}

void Neural_network::build_network() {
	for (int i=1; i < num_layers; i++) {
		for (int j=0; j<neurons_per_layer[i-1]; j++) {
			for (int k=0; k<neurons_per_layer[i]; k++) {
				Edge_key key{i-1, j, k};
				double w = generate_init_weight();
				neurons_at_layer[i-1][j].add_out_edge(w, key);
				neurons_at_layer[i][k].add_in_edge(w, key);
			}
		}
	}
}

double activation_func(double net) {
	return 1./(1.+exp(-net));
}
void Neural_network::calculate_outputs() {
	for (int i=1; i < num_layers; i++) {
		for (int j=0; j<neurons_per_layer[i]; j++) {
			if (is_bias(i, j)) continue;
			auto keys = neurons_at_layer[i][j].in_edges_keys();
			double res = 0.0;
			for (const auto & key: keys) {
				double out = neurons_at_layer[key.layer][key.in].get_out();
				double w =  neurons_at_layer[key.layer][key.in].out_edges_weights(key);
				res += out*w;
			}
			neurons_at_layer[i][j].set_out(activation_func(res));
		}
	}
}

double activation_func_der(double out) {
	return out*(1.-out);
}

void Neural_network::set_weight(double w, const Edge_key & k){
	neurons_at_layer[k.layer][k.in].out_edges_weights(k) = w;
	neurons_at_layer[k.layer+1][k.out].in_edges_weights(k) = w;
}

bool Neural_network::back_propagation(const vector<double> & targets) {
	bool res = true;
	map<Edge_key, double> sigmas;
	map<Edge_key, double> old_weights;
	/*check error! */
	for (int i=0; i<neurons_per_layer[num_layers-1]; i++) {
		if (abs(neurons_at_layer[num_layers-1][i].get_out() - targets[i]) >= ok) {
			res = false;
			break;
		}
	}
	/*calculate out_sigmas and set weights for output layer*/
	for (int i=0; i<neurons_per_layer[num_layers-1]; i++) {
		Neuron & n = neurons_at_layer[num_layers-1][i];
		vector<Edge_key> keys = n.in_edges_keys();
		for (const auto & key:keys) {
			Neuron & in = neurons_at_layer[key.layer][key.in];
			sigmas[key] = -(targets[i] - n.get_out()) * activation_func_der(n.get_out());
			double w = in.out_edges_weights(key);
			old_weights[key] = w;
			set_weight(w - sigmas[key]*eta*in.get_out(), key);
		}
	}
	for (int i=num_layers-2; i >= 1; i--) {
		for (int j=0; j<neurons_per_layer[i]; j++) {
			Neuron & n = neurons_at_layer[i][j];
			if (is_bias(i, j)) continue;
			vector<Edge_key> keys = n.in_edges_keys();
			vector<Edge_key> sigma_keys = n.out_edges_keys();
			for (const auto & key:keys) {
				Neuron & in = neurons_at_layer[key.layer][key.in];
				double r = activation_func_der(n.get_out());
				sigmas[key] = r;
				double sum = 0.0;
				for (const auto & sk: sigma_keys) {
					sum += sigmas[sk]*old_weights[sk];
				}
				sigmas[key] *= sum;
				double w = in.out_edges_weights(key);
				old_weights[key] = w;
				set_weight(w - sigmas[key]*eta*in.get_out(), key);
			}
		}
	}

	return res;
}

double Neural_network::test(Neural_network & nn, const vector<double> & inputs, const vector<double> & targets) {
	vector<double> res = nn.calculate(inputs);
	double coumpound_error = 0.0;
	cout << "Neural network test with inputs:" << endl;
	for (size_t i=0; i<inputs.size(); i++) {
		cout << "input[" << i << "] = " << inputs[i] << endl;
	}
	for (size_t i=0; i<res.size(); i++) {
		cout << "output[" << i << "] = " << res[i] << endl;
		cout << "expected output: " << targets[i] << endl;
		coumpound_error += abs(targets[i] - res[i]);
		cout << "ERROR = " <<  abs(targets[i] -res[i]) << endl;
	}
	cout << endl;
	return coumpound_error / res.size();
}
vector<double> Neural_network::calculate(const vector<double> & inputs){
	vector<double> out(neurons_per_layer[num_layers-1]);
	for (size_t i=0; i < inputs.size(); i++) {
		neurons_at_layer[0][i].set_out(inputs[i]);
	}
	calculate_outputs();
	for (size_t i=0; i < out.size(); i++) {
		out[i] = neurons_at_layer[num_layers-1][i].get_out();
	}
	return out;
}

void Neural_network::operator() (const vector<vector<double>> & inputs, const vector<vector<double>> & outputs, int epoch_count){
	size_t data_size = inputs[0].size();
	for (size_t i=0; i< inputs.size(); i++) {
		assert(data_size == inputs[i].size());
	}
	for (size_t i=0; i< outputs.size(); i++) {
		assert(data_size == outputs[i].size());
	}
	assert(inputs.size() == neurons_at_layer[0].size()-1);
	assert(outputs.size() == neurons_at_layer[num_layers-1].size());

	vector <double> targets(outputs.size()); // target outputs

	std::chrono::time_point<std::chrono::high_resolution_clock> start, end, total_start;
	double calculation = 0.0;
	double backpropagation = 0.0;
	total_start = std::chrono::high_resolution_clock::now();

	while(epoch_count--) {
		//cout << epoch_count << endl;
		for (size_t current=0; current < data_size; current++) {
			/*init inputs*/
			for (size_t i=0; i < inputs.size(); i++) {
				neurons_at_layer[0][i].set_out(inputs[i][current]);
			}
			/*init target*/
			for (size_t i=0; i < outputs.size(); i++) {
				targets[i] = outputs[i][current];
			}

			start = std::chrono::high_resolution_clock::now();

			/*calculate outputs*/
			calculate_outputs();

			end = std::chrono::high_resolution_clock::now();
			calculation += (std::chrono::duration<double>(end - start)).count();
			start = end;

			/*set new weights*/
			back_propagation(targets);

			end = std::chrono::high_resolution_clock::now();
			backpropagation += (std::chrono::duration<double>(end - start)).count();
		}
	}

	std::chrono::duration<double> total_duration = std::chrono::high_resolution_clock::now() - total_start;
	cout << "total duration " << total_duration.count() << "s" << endl;
	cout << "calc " << calculation << "s (" << 100.0 * calculation / total_duration.count() << "%)" << endl;
	cout << "back " << backpropagation << "s (" << 100.0 *  backpropagation / total_duration.count() << "%)" << endl;

}
<commit_msg>Excess of calculation removed.<commit_after>/*
 * Neuralnetwork.cpp
 *
 *  Created on: May 12, 2016
 *      Author: marija
 */

#include "Neuralnetwork.h"
#include <chrono>
using namespace std;

Neural_network::Neural_network(const vector<int> & init, double learning_rate, double acceptable_error):
		eta{learning_rate}, ok{acceptable_error}, config{init} {
	if (init.size() <= 2) throw runtime_error("Invalid initialization of neural network");
	num_layers = init.size();
	for (int i=0; i < num_layers; i++) {
		neurons_per_layer.push_back(init[i]);
	}
	/*add bias*/
	for (int i=0; i < num_layers-1; i++) {
		neurons_per_layer[i]++;
	}
	for (int i=0; i < num_layers; i++) {
		neurons_at_layer.push_back(vector<Neuron>(neurons_per_layer[i]));
	}
	build_network();
}

double Neural_network::generate_init_weight() {
	random_device rd;
	mt19937 gen(rd());
	uniform_real_distribution<> dist(0.1,1.0);
	return dist(gen);
}

void Neural_network::build_network() {
	for (int i=1; i < num_layers; i++) {
		for (int j=0; j<neurons_per_layer[i-1]; j++) {
			for (int k=0; k<neurons_per_layer[i]; k++) {
				Edge_key key{i-1, j, k};
				double w = generate_init_weight();
				neurons_at_layer[i-1][j].add_out_edge(w, key);
				neurons_at_layer[i][k].add_in_edge(w, key);
			}
		}
	}
}

double activation_func(double net) {
	return 1./(1.+exp(-net));
}
void Neural_network::calculate_outputs() {
	for (int i=1; i < num_layers; i++) {
		for (int j=0; j<neurons_per_layer[i]; j++) {
			if (is_bias(i, j)) continue;
			auto keys = neurons_at_layer[i][j].in_edges_keys();
			double res = 0.0;
			for (const auto & key: keys) {
				double out = neurons_at_layer[key.layer][key.in].get_out();
				double w =  neurons_at_layer[key.layer][key.in].out_edges_weights(key);
				res += out*w;
			}
			neurons_at_layer[i][j].set_out(activation_func(res));
		}
	}
}

double activation_func_der(double out) {
	return out*(1.-out);
}

void Neural_network::set_weight(double w, const Edge_key & k){
	neurons_at_layer[k.layer][k.in].out_edges_weights(k) = w;
	neurons_at_layer[k.layer+1][k.out].in_edges_weights(k) = w;
}

bool Neural_network::back_propagation(const vector<double> & targets) {
	bool res = true;
	map<Edge_key, double> sigmas;
	map<Edge_key, double> old_weights;
	/*check error! */
	for (int i=0; i<neurons_per_layer[num_layers-1]; i++) {
		if (abs(neurons_at_layer[num_layers-1][i].get_out() - targets[i]) >= ok) {
			res = false;
			break;
		}
	}
	/*calculate out_sigmas and set weights for output layer*/
	for (int i=0; i<neurons_per_layer[num_layers-1]; i++) {
		Neuron & n = neurons_at_layer[num_layers-1][i];
		vector<Edge_key> keys = n.in_edges_keys();
		double new_sig_val = -(targets[i] - n.get_out()) * activation_func_der(n.get_out());;
		for (const auto & key:keys) {
			Neuron & in = neurons_at_layer[key.layer][key.in];
			sigmas[key] = new_sig_val;
			double w = in.out_edges_weights(key);
			old_weights[key] = w;
			set_weight(w - sigmas[key]*eta*in.get_out(), key);
		}
	}
	for (int i=num_layers-2; i >= 1; i--) {
		for (int j=0; j<neurons_per_layer[i]; j++) {
			Neuron & n = neurons_at_layer[i][j];
			if (is_bias(i, j)) continue;
			vector<Edge_key> keys = n.in_edges_keys();
			vector<Edge_key> sigma_keys = n.out_edges_keys();
			double r = activation_func_der(n.get_out());
			for (const auto & key:keys) {
				Neuron & in = neurons_at_layer[key.layer][key.in];
				sigmas[key] = r;
				double sum = 0.0;
				for (const auto & sk: sigma_keys) {
					sum += sigmas[sk]*old_weights[sk];
				}
				sigmas[key] *= sum;
				double w = in.out_edges_weights(key);
				old_weights[key] = w;
				set_weight(w - sigmas[key]*eta*in.get_out(), key);
			}
		}
	}

	return res;
}

double Neural_network::test(Neural_network & nn, const vector<double> & inputs, const vector<double> & targets) {
	vector<double> res = nn.calculate(inputs);
	double coumpound_error = 0.0;
	cout << "Neural network test with inputs:" << endl;
	for (size_t i=0; i<inputs.size(); i++) {
		cout << "input[" << i << "] = " << inputs[i] << endl;
	}
	for (size_t i=0; i<res.size(); i++) {
		cout << "output[" << i << "] = " << res[i] << endl;
		cout << "expected output: " << targets[i] << endl;
		coumpound_error += abs(targets[i] - res[i]);
		cout << "ERROR = " <<  abs(targets[i] -res[i]) << endl;
	}
	cout << endl;
	return coumpound_error / res.size();
}
vector<double> Neural_network::calculate(const vector<double> & inputs){
	vector<double> out(neurons_per_layer[num_layers-1]);
	for (size_t i=0; i < inputs.size(); i++) {
		neurons_at_layer[0][i].set_out(inputs[i]);
	}
	calculate_outputs();
	for (size_t i=0; i < out.size(); i++) {
		out[i] = neurons_at_layer[num_layers-1][i].get_out();
	}
	return out;
}

void Neural_network::operator() (const vector<vector<double>> & inputs, const vector<vector<double>> & outputs, int epoch_count){
	size_t data_size = inputs[0].size();
	for (size_t i=0; i< inputs.size(); i++) {
		assert(data_size == inputs[i].size());
	}
	for (size_t i=0; i< outputs.size(); i++) {
		assert(data_size == outputs[i].size());
	}
	assert(inputs.size() == neurons_at_layer[0].size()-1);
	assert(outputs.size() == neurons_at_layer[num_layers-1].size());

	vector <double> targets(outputs.size()); // target outputs

	std::chrono::time_point<std::chrono::high_resolution_clock> start, end, total_start;
	double calculation = 0.0;
	double backpropagation = 0.0;
	total_start = std::chrono::high_resolution_clock::now();

	while(epoch_count--) {
		//cout << epoch_count << endl;
		for (size_t current=0; current < data_size; current++) {
			/*init inputs*/
			for (size_t i=0; i < inputs.size(); i++) {
				neurons_at_layer[0][i].set_out(inputs[i][current]);
			}
			/*init target*/
			for (size_t i=0; i < outputs.size(); i++) {
				targets[i] = outputs[i][current];
			}

			start = std::chrono::high_resolution_clock::now();

			/*calculate outputs*/
			calculate_outputs();

			end = std::chrono::high_resolution_clock::now();
			calculation += (std::chrono::duration<double>(end - start)).count();
			start = end;

			/*set new weights*/
			back_propagation(targets);

			end = std::chrono::high_resolution_clock::now();
			backpropagation += (std::chrono::duration<double>(end - start)).count();
		}
	}

	std::chrono::duration<double> total_duration = std::chrono::high_resolution_clock::now() - total_start;
	cout << "total duration " << total_duration.count() << "s" << endl;
	cout << "calc " << calculation << "s (" << 100.0 * calculation / total_duration.count() << "%)" << endl;
	cout << "back " << backpropagation << "s (" << 100.0 *  backpropagation / total_duration.count() << "%)" << endl;

}
<|endoftext|>


<commit_before>/*
*    flv_media_stream_source.cpp:
*
*    Copyright (C) 2015-2017 Light Lin <blog.poxiao.me> All Rights Reserved.
*
*/

#include <algorithm>
#include <string>

#include "default_task_service.hpp"
#include "error.hpp"
#include "flv_media_stream_source.hpp"
#include "flv_player.hpp"

using namespace concurrency;
using namespace dawn_player;

using namespace Windows::Foundation::Collections;
using namespace Windows::Media::MediaProperties;

namespace dawn_player {

flv_media_stream_source::flv_media_stream_source()
{
}

void flv_media_stream_source::init(const std::shared_ptr<flv_player>& player, MediaStreamSource^ mss)
{
    this->player = player;
    this->mss = mss;
    this->tsk_service = this->player->get_task_service();
    starting_event_token = this->mss->Starting += ref new TypedEventHandler<MediaStreamSource^, MediaStreamSourceStartingEventArgs^>(this, &flv_media_stream_source::on_starting);
    sample_requested_event_token = this->mss->SampleRequested += ref new TypedEventHandler<MediaStreamSource^, MediaStreamSourceSampleRequestedEventArgs^>(this, &flv_media_stream_source::on_sample_requested);
}

IAsyncOperation<flv_media_stream_source^>^ flv_media_stream_source::create(IRandomAccessStream^ random_access_stream)
{
    return create(random_access_stream, true);
}

IAsyncOperation<flv_media_stream_source^>^ flv_media_stream_source::create(IRandomAccessStream^ random_access_stream, bool stream_can_seek)
{
    auto tce = task_completion_event<flv_media_stream_source^>();
    auto result_task = task<flv_media_stream_source^>(tce);
    auto tsk_service = std::make_shared<default_task_service>();
    tsk_service->post_task([tsk_service, random_access_stream, stream_can_seek, tce]() {
        auto player = std::make_shared<flv_player>(tsk_service);
        player->set_source(random_access_stream);
        player->open()
        .then([tsk_service, player, stream_can_seek, tce](task<std::map<std::string, std::string>> tsk) {
            tsk_service->post_task([player, stream_can_seek, tce, tsk]() {
                std::map<std::string, std::string> info;
                try {
                    info = tsk.get();
                }
                catch (const open_error&) {
                    tce.set_exception(ref new Platform::FailureException("Failed to open FLV file."));
                    return;
                }
                std::string acpd = info["AudioCodecPrivateData"];
                unsigned int channel_count = std::stol(acpd.substr(4, 2), 0, 16) + std::stol(acpd.substr(6, 2), 0, 16) * 0x100;
                unsigned int sample_rate = std::stol(acpd.substr(8, 2), 0, 16) + std::stol(acpd.substr(10, 2), 0, 16) * 0x100 +
                    std::stol(acpd.substr(12, 2), 0, 16) * 0x10000 + std::stol(acpd.substr(14, 2), 0, 16) * 0x1000000;
                unsigned int bit_rate = sample_rate * (std::stol(acpd.substr(28, 2), 0, 16) + std::stol(acpd.substr(30, 2), 0, 16) * 0x100);
                auto aep = AudioEncodingProperties::CreateAac(sample_rate, channel_count, bit_rate);
                auto asd = ref new AudioStreamDescriptor(aep);
                auto vep = VideoEncodingProperties::CreateH264();
                auto video_width = std::stoul(info["Width"]);
                auto video_height = std::stoul(info["Height"]);
                // It seems that H.264 only supports even numbered dimensions.
                vep->Width = video_width - (video_width % 2);
                vep->Height = video_height - (video_height % 2);
                auto vsd = ref new VideoStreamDescriptor(vep);
                auto mss = ref new MediaStreamSource(asd);
                mss->AddStreamDescriptor(vsd);
                mss->CanSeek = stream_can_seek && info["CanSeek"] == "True";
                // Set BufferTime to 0 to improve seek experience in Debug mode
                mss->BufferTime = TimeSpan{ 0 };
                auto iter_duration = info.find("Duration");
                if (iter_duration != info.end()) {
                    mss->Duration = TimeSpan{ std::stoll(std::get<1>(*iter_duration)) };
                }
                auto flv_mss = ref new flv_media_stream_source();
                flv_mss->init(player, mss);
                tce.set(flv_mss);
            });
        });
    });
    return create_async([result_task]() {
        return result_task;
    });
}

MediaStreamSource^ flv_media_stream_source::unwrap()
{
    return this->mss;
}

flv_media_stream_source::~flv_media_stream_source()
{
    if (this->player) {
        auto player = this->player;
        this->player = nullptr;
        this->tsk_service->post_task([player]() {
            create_async([player]() {
                return player->close();
            });
        });
    }
    if (this->mss) {
        this->mss->Starting -= this->starting_event_token;
        this->mss->SampleRequested -= this->sample_requested_event_token;
        this->mss = nullptr;
    }
}

void flv_media_stream_source::on_starting(MediaStreamSource^ sender, MediaStreamSourceStartingEventArgs^ args)
{
    auto request = args->Request;
    auto deferral = request->GetDeferral();
    this->tsk_service->post_task([this, request, deferral]() {
        auto start_position = request->StartPosition;
        if (start_position == nullptr) {
            request->SetActualStartPosition(TimeSpan{ this->player->get_start_position() });
            deferral->Complete();
        }
        else {
            create_async([this, start_position, request, deferral]() {
                return this->player->seek(start_position->Value.Duration)
                .then([this, request, deferral](task<std::int64_t> tsk) {
                    this->tsk_service->post_task([tsk, request, deferral]() {
                        auto seek_to_time = tsk.get();
                        request->SetActualStartPosition(TimeSpan{ seek_to_time });
                        deferral->Complete();
                    });
                });
            });
        }
    });
}

void flv_media_stream_source::on_sample_requested(MediaStreamSource^ sender, MediaStreamSourceSampleRequestedEventArgs^ args)
{
    auto request = args->Request;
    auto deferral = request->GetDeferral();
    this->tsk_service->post_task([this, sender, request, deferral]() {
        if (request->StreamDescriptor->GetType()->FullName == AudioStreamDescriptor::typeid->FullName) {
            create_async([this, sender, request, deferral]() {
                return this->player->get_audio_sample()
                    .then([this, sender, request, deferral](task<audio_sample> tsk) {
                    this->tsk_service->post_task([this, sender, request, deferral, tsk]() {
                        try {
                            audio_sample sample = tsk.get();
                            auto data_writer = ref new DataWriter();
                            for (auto byte : sample.data) {
                                data_writer->WriteByte(byte);
                            }
                            auto stream_sample = MediaStreamSample::CreateFromBuffer(data_writer->DetachBuffer(), TimeSpan{ sample.timestamp });
                            request->Sample = stream_sample;
                        }
                        catch (const get_sample_error& gse) {
                            if (gse.code() == get_sample_error_code::end_of_stream) {
                                request->Sample = nullptr;
                            }
                            else {
                                sender->NotifyError(MediaStreamSourceErrorStatus::Other);
                            }
                        }
                        deferral->Complete();
                    });
                });
            });
        }
        else if (request->StreamDescriptor->GetType()->FullName == VideoStreamDescriptor::typeid->FullName) {
            create_async([this, sender, request, deferral]() {
                return this->player->get_video_sample()
                .then([this, sender, request, deferral](task<video_sample> tsk) {
                    this->tsk_service->post_task([this, sender, request, deferral, tsk]() {
                        try {
                            video_sample sample = tsk.get();
                            auto data_writer = ref new DataWriter();
                            if (sample.is_key_frame) {
                                const auto& sps = this->player->get_sps();
                                if (!sps.empty()) {
                                    data_writer->WriteByte(0);
                                    data_writer->WriteByte(0);
                                    data_writer->WriteByte(1);
                                    for (auto byte : sps) {
                                        data_writer->WriteByte(byte);
                                    }
                                }
                                const auto& pps = this->player->get_pps();
                                if (!pps.empty()) {
                                    data_writer->WriteByte(0);
                                    data_writer->WriteByte(0);
                                    data_writer->WriteByte(1);
                                    for (auto byte : pps) {
                                        data_writer->WriteByte(byte);
                                    }
                                }
                            }
                            for (auto byte : sample.data) {
                                data_writer->WriteByte(byte);
                            }
                            auto stream_sample = MediaStreamSample::CreateFromBuffer(data_writer->DetachBuffer(), TimeSpan{ sample.timestamp });
                            stream_sample->DecodeTimestamp = TimeSpan{ sample.dts };
                            stream_sample->KeyFrame = sample.is_key_frame;
                            request->Sample = stream_sample;
                        }
                        catch (const get_sample_error& gse) {
                            if (gse.code() == get_sample_error_code::end_of_stream) {
                                request->Sample = nullptr;
                            }
                            else {
                                sender->NotifyError(MediaStreamSourceErrorStatus::Other);
                            }
                        }
                        deferral->Complete();
                    });
                });
            });
        }
    });
}

} // namespace dawn_player
<commit_msg>flv_media_stream_source: fix crash<commit_after>/*
*    flv_media_stream_source.cpp:
*
*    Copyright (C) 2015-2017 Light Lin <blog.poxiao.me> All Rights Reserved.
*
*/

#include <algorithm>
#include <string>

#include "default_task_service.hpp"
#include "error.hpp"
#include "flv_media_stream_source.hpp"
#include "flv_player.hpp"

using namespace concurrency;
using namespace dawn_player;

using namespace Windows::Foundation::Collections;
using namespace Windows::Media::MediaProperties;

namespace dawn_player {

flv_media_stream_source::flv_media_stream_source()
{
}

void flv_media_stream_source::init(const std::shared_ptr<flv_player>& player, MediaStreamSource^ mss)
{
    this->player = player;
    this->mss = mss;
    this->tsk_service = this->player->get_task_service();
    starting_event_token = this->mss->Starting += ref new TypedEventHandler<MediaStreamSource^, MediaStreamSourceStartingEventArgs^>(this, &flv_media_stream_source::on_starting);
    sample_requested_event_token = this->mss->SampleRequested += ref new TypedEventHandler<MediaStreamSource^, MediaStreamSourceSampleRequestedEventArgs^>(this, &flv_media_stream_source::on_sample_requested);
}

IAsyncOperation<flv_media_stream_source^>^ flv_media_stream_source::create(IRandomAccessStream^ random_access_stream)
{
    return create(random_access_stream, true);
}

IAsyncOperation<flv_media_stream_source^>^ flv_media_stream_source::create(IRandomAccessStream^ random_access_stream, bool stream_can_seek)
{
    auto tce = task_completion_event<flv_media_stream_source^>();
    auto result_task = task<flv_media_stream_source^>(tce);
    auto tsk_service = std::make_shared<default_task_service>();
    tsk_service->post_task([tsk_service, random_access_stream, stream_can_seek, tce]() {
        auto player = std::make_shared<flv_player>(tsk_service);
        player->set_source(random_access_stream);
        player->open()
        .then([tsk_service, player, stream_can_seek, tce](task<std::map<std::string, std::string>> tsk) {
            tsk_service->post_task([player, stream_can_seek, tce, tsk]() {
                std::map<std::string, std::string> info;
                try {
                    info = tsk.get();
                }
                catch (const open_error&) {
                    tce.set_exception(ref new Platform::FailureException("Failed to open FLV file."));
                    return;
                }
                std::string acpd = info["AudioCodecPrivateData"];
                unsigned int channel_count = std::stol(acpd.substr(4, 2), 0, 16) + std::stol(acpd.substr(6, 2), 0, 16) * 0x100;
                unsigned int sample_rate = std::stol(acpd.substr(8, 2), 0, 16) + std::stol(acpd.substr(10, 2), 0, 16) * 0x100 +
                    std::stol(acpd.substr(12, 2), 0, 16) * 0x10000 + std::stol(acpd.substr(14, 2), 0, 16) * 0x1000000;
                unsigned int bit_rate = sample_rate * (std::stol(acpd.substr(28, 2), 0, 16) + std::stol(acpd.substr(30, 2), 0, 16) * 0x100);
                auto aep = AudioEncodingProperties::CreateAac(sample_rate, channel_count, bit_rate);
                auto asd = ref new AudioStreamDescriptor(aep);
                auto vep = VideoEncodingProperties::CreateH264();
                auto video_width = std::stoul(info["Width"]);
                auto video_height = std::stoul(info["Height"]);
                // It seems that H.264 only supports even numbered dimensions.
                vep->Width = video_width - (video_width % 2);
                vep->Height = video_height - (video_height % 2);
                auto vsd = ref new VideoStreamDescriptor(vep);
                auto mss = ref new MediaStreamSource(asd);
                mss->AddStreamDescriptor(vsd);
                mss->CanSeek = stream_can_seek && info["CanSeek"] == "True";
                // Set BufferTime to 0 to improve seek experience in Debug mode
                mss->BufferTime = TimeSpan{ 0 };
                auto iter_duration = info.find("Duration");
                if (iter_duration != info.end()) {
                    mss->Duration = TimeSpan{ std::stoll(std::get<1>(*iter_duration)) };
                }
                auto flv_mss = ref new flv_media_stream_source();
                flv_mss->init(player, mss);
                tce.set(flv_mss);
            });
        });
    });
    return create_async([result_task]() {
        return result_task;
    });
}

MediaStreamSource^ flv_media_stream_source::unwrap()
{
    return this->mss;
}

flv_media_stream_source::~flv_media_stream_source()
{
    if (this->player) {
        auto player = this->player;
        this->player = nullptr;
        this->tsk_service->post_task([player]() {
            create_async([player]() {
                return player->close();
            });
        });
    }
    if (this->mss) {
        this->mss->Starting -= this->starting_event_token;
        this->mss->SampleRequested -= this->sample_requested_event_token;
        this->mss = nullptr;
    }
}

void flv_media_stream_source::on_starting(MediaStreamSource^ sender, MediaStreamSourceStartingEventArgs^ args)
{
    auto request = args->Request;
    auto deferral = request->GetDeferral();
    auto tsk_service = this->tsk_service;
    auto wp_player = std::weak_ptr<flv_player>(this->player);
    tsk_service->post_task([tsk_service, wp_player, request, deferral]() {
        auto start_position = request->StartPosition;
        if (start_position == nullptr) {
            auto player = wp_player.lock();
            if (player) {
                request->SetActualStartPosition(TimeSpan{ player->get_start_position() });
                deferral->Complete();
            }
        }
        else {
            create_async([tsk_service, wp_player, start_position, request, deferral]() {
                auto player = wp_player.lock();
                if (!player) {
                    return task_from_result();
                }
                return player->seek(start_position->Value.Duration)
                .then([tsk_service, request, deferral](task<std::int64_t> tsk) {
                    tsk_service->post_task([tsk, request, deferral]() {
                        auto seek_to_time = tsk.get();
                        request->SetActualStartPosition(TimeSpan{ seek_to_time });
                        deferral->Complete();
                    });
                });
            });
        }
    });
}

void flv_media_stream_source::on_sample_requested(MediaStreamSource^ sender, MediaStreamSourceSampleRequestedEventArgs^ args)
{
    auto request = args->Request;
    auto deferral = request->GetDeferral();
    auto tsk_service = this->tsk_service;
    auto wp_player = std::weak_ptr<flv_player>(this->player);
    tsk_service->post_task([tsk_service, wp_player, sender, request, deferral]() {
        if (request->StreamDescriptor->GetType()->FullName == AudioStreamDescriptor::typeid->FullName) {
            create_async([tsk_service, wp_player, sender, request, deferral]() {
                auto player = wp_player.lock();
                if (!player) {
                    return task_from_result();
                }
                return player->get_audio_sample()
                    .then([tsk_service, sender, request, deferral](task<audio_sample> tsk) {
                    tsk_service->post_task([sender, request, deferral, tsk]() {
                        try {
                            audio_sample sample = tsk.get();
                            auto data_writer = ref new DataWriter();
                            for (auto byte : sample.data) {
                                data_writer->WriteByte(byte);
                            }
                            auto stream_sample = MediaStreamSample::CreateFromBuffer(data_writer->DetachBuffer(), TimeSpan{ sample.timestamp });
                            request->Sample = stream_sample;
                        }
                        catch (const get_sample_error& gse) {
                            if (gse.code() == get_sample_error_code::end_of_stream) {
                                request->Sample = nullptr;
                            }
                            else {
                                sender->NotifyError(MediaStreamSourceErrorStatus::Other);
                            }
                        }
                        deferral->Complete();
                    });
                });
            });
        }
        else if (request->StreamDescriptor->GetType()->FullName == VideoStreamDescriptor::typeid->FullName) {
            create_async([tsk_service, wp_player, sender, request, deferral]() {
                auto player = wp_player.lock();
                if (!player) {
                    return task_from_result();
                }
                return player->get_video_sample()
                .then([tsk_service, wp_player, sender, request, deferral](task<video_sample> tsk) {
                    tsk_service->post_task([wp_player, sender, request, deferral, tsk]() {
                        auto player = wp_player.lock();
                        if (!player) {
                            return;
                        }
                        try {
                            video_sample sample = tsk.get();
                            auto data_writer = ref new DataWriter();
                            if (sample.is_key_frame) {
                                const auto& sps = player->get_sps();
                                if (!sps.empty()) {
                                    data_writer->WriteByte(0);
                                    data_writer->WriteByte(0);
                                    data_writer->WriteByte(1);
                                    for (auto byte : sps) {
                                        data_writer->WriteByte(byte);
                                    }
                                }
                                const auto& pps = player->get_pps();
                                if (!pps.empty()) {
                                    data_writer->WriteByte(0);
                                    data_writer->WriteByte(0);
                                    data_writer->WriteByte(1);
                                    for (auto byte : pps) {
                                        data_writer->WriteByte(byte);
                                    }
                                }
                            }
                            for (auto byte : sample.data) {
                                data_writer->WriteByte(byte);
                            }
                            auto stream_sample = MediaStreamSample::CreateFromBuffer(data_writer->DetachBuffer(), TimeSpan{ sample.timestamp });
                            stream_sample->DecodeTimestamp = TimeSpan{ sample.dts };
                            stream_sample->KeyFrame = sample.is_key_frame;
                            request->Sample = stream_sample;
                        }
                        catch (const get_sample_error& gse) {
                            if (gse.code() == get_sample_error_code::end_of_stream) {
                                request->Sample = nullptr;
                            }
                            else {
                                sender->NotifyError(MediaStreamSourceErrorStatus::Other);
                            }
                        }
                        deferral->Complete();
                    });
                });
            });
        }
    });
}

} // namespace dawn_player
<|endoftext|>