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

#include <memory>
#include <set>

#include <gflags/gflags.h>
#include <grpc/support/log.h>

#include "test/cpp/qps/driver.h"
#include "test/cpp/qps/report.h"
#include "test/cpp/util/benchmark_config.h"

DEFINE_int32(num_clients, 1, "Number of client binaries");
DEFINE_int32(num_servers, 1, "Number of server binaries");

DEFINE_int32(warmup_seconds, 5, "Warmup time (in seconds)");
DEFINE_int32(benchmark_seconds, 30, "Benchmark time (in seconds)");
DEFINE_int32(local_workers, 0, "Number of local workers to start");

// Common config
DEFINE_string(rpc_type, "UNARY", "Type of RPC: UNARY or STREAMING");

// Server config
DEFINE_int32(async_server_threads, 1, "Number of threads for async servers");
DEFINE_string(server_type, "SYNC_SERVER", "Server type");

// Client config
DEFINE_int32(outstanding_rpcs_per_channel, 1,
             "Number of outstanding rpcs per channel");
DEFINE_int32(client_channels, 1, "Number of client channels");

DEFINE_int32(simple_req_size, -1, "Simple proto request payload size");
DEFINE_int32(simple_resp_size, -1, "Simple proto response payload size");
DEFINE_int32(bbuf_req_size, -1, "Byte-buffer request payload size");
DEFINE_int32(bbuf_resp_size, -1, "Byte-buffer response payload size");

DEFINE_string(client_type, "SYNC_CLIENT", "Client type");
DEFINE_int32(async_client_threads, 1, "Async client threads");

DEFINE_double(poisson_load, -1.0, "Poisson offered load (qps)");
DEFINE_double(uniform_lo, -1.0, "Uniform low interarrival time (us)");
DEFINE_double(uniform_hi, -1.0, "Uniform high interarrival time (us)");
DEFINE_double(determ_load, -1.0, "Deterministic offered load (qps)");
DEFINE_double(pareto_base, -1.0, "Pareto base interarrival time (us)");
DEFINE_double(pareto_alpha, -1.0, "Pareto alpha value");

DEFINE_bool(secure_test, false, "Run a secure test");

using grpc::testing::ClientConfig;
using grpc::testing::ServerConfig;
using grpc::testing::ClientType;
using grpc::testing::ServerType;
using grpc::testing::RpcType;
using grpc::testing::ResourceUsage;
using grpc::testing::SecurityParams;

namespace grpc {
namespace testing {

static void QpsDriver() {
  RpcType rpc_type;
  GPR_ASSERT(RpcType_Parse(FLAGS_rpc_type, &rpc_type));

  ClientType client_type;
  ServerType server_type;
  GPR_ASSERT(ClientType_Parse(FLAGS_client_type, &client_type));
  GPR_ASSERT(ServerType_Parse(FLAGS_server_type, &server_type));

  ClientConfig client_config;
  client_config.set_client_type(client_type);
  client_config.set_outstanding_rpcs_per_channel(
      FLAGS_outstanding_rpcs_per_channel);
  client_config.set_client_channels(FLAGS_client_channels);

  // Decide which type to use based on the response type
  if (FLAGS_simple_resp_size >= 0) {
    auto params =
        client_config.mutable_payload_config()->mutable_simple_params();
    params->set_resp_size(FLAGS_simple_resp_size);
    if (FLAGS_simple_req_size >= 0) {
      params->set_req_size(FLAGS_simple_req_size);
    }
  } else if (FLAGS_bbuf_resp_size >= 0) {
    auto params =
        client_config.mutable_payload_config()->mutable_bytebuf_params();
    params->set_resp_size(FLAGS_bbuf_resp_size);
    if (FLAGS_bbuf_req_size >= 0) {
      params->set_req_size(FLAGS_bbuf_req_size);
    }
  } else {
    // set a reasonable default: proto but no payload
    client_config.mutable_payload_config()->mutable_simple_params();
  }

  client_config.set_async_client_threads(FLAGS_async_client_threads);
  client_config.set_rpc_type(rpc_type);

  // set up the load parameters
  if (FLAGS_poisson_load > 0.0) {
    auto poisson = client_config.mutable_load_params()->mutable_poisson();
    poisson->set_offered_load(FLAGS_poisson_load);
  } else if (FLAGS_uniform_lo > 0.0) {
    auto uniform = client_config.mutable_load_params()->mutable_uniform();
    uniform->set_interarrival_lo(FLAGS_uniform_lo / 1e6);
    uniform->set_interarrival_hi(FLAGS_uniform_hi / 1e6);
  } else if (FLAGS_determ_load > 0.0) {
    auto determ = client_config.mutable_load_params()->mutable_determ();
    determ->set_offered_load(FLAGS_determ_load);
  } else if (FLAGS_pareto_base > 0.0) {
    auto pareto = client_config.mutable_load_params()->mutable_pareto();
    pareto->set_interarrival_base(FLAGS_pareto_base / 1e6);
    pareto->set_alpha(FLAGS_pareto_alpha);
  } else {
    client_config.mutable_load_params()->mutable_closed_loop();
    // No further load parameters to set up for closed loop
  }

  client_config.mutable_histogram_params()->set_resolution(
      Histogram::default_resolution());
  client_config.mutable_histogram_params()->set_max_possible(
      Histogram::default_max_possible());

  ServerConfig server_config;
  server_config.set_server_type(server_type);
  server_config.set_host("::"); // Use the wildcard server address
  server_config.set_async_server_threads(FLAGS_async_server_threads);

  if (FLAGS_secure_test) {
    // Set up security params
    SecurityParams security;
    security.set_use_test_ca(true);
    security.set_server_host_override("foo.test.google.fr");
    client_config.mutable_security_params()->CopyFrom(security);
    server_config.mutable_security_params()->CopyFrom(security);
  }

  // Make sure that if we are performing a generic (bytebuf) test
  // that we are also using async streaming
  GPR_ASSERT(!client_config.payload_config().has_bytebuf_params() ||
             (client_config.client_type() == ASYNC_CLIENT &&
              client_config.rpc_type() == STREAMING &&
              server_config.server_type() == ASYNC_SERVER));

  const auto result = RunScenario(
      client_config, FLAGS_num_clients, server_config, FLAGS_num_servers,
      FLAGS_warmup_seconds, FLAGS_benchmark_seconds, FLAGS_local_workers);

  GetReporter()->ReportQPS(*result);
  GetReporter()->ReportQPSPerCore(*result);
  GetReporter()->ReportLatency(*result);
  GetReporter()->ReportTimes(*result);
}

}  // namespace testing
}  // namespace grpc

int main(int argc, char** argv) {
  grpc::testing::InitBenchmark(&argc, &argv, true);

  grpc::testing::QpsDriver();

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

#include <memory>
#include <set>

#include <gflags/gflags.h>
#include <grpc/support/log.h>

#include "test/cpp/qps/driver.h"
#include "test/cpp/qps/report.h"
#include "test/cpp/util/benchmark_config.h"

DEFINE_int32(num_clients, 1, "Number of client binaries");
DEFINE_int32(num_servers, 1, "Number of server binaries");

DEFINE_int32(warmup_seconds, 5, "Warmup time (in seconds)");
DEFINE_int32(benchmark_seconds, 30, "Benchmark time (in seconds)");
DEFINE_int32(local_workers, 0, "Number of local workers to start");

// Common config
DEFINE_string(rpc_type, "UNARY", "Type of RPC: UNARY or STREAMING");

// Server config
DEFINE_int32(async_server_threads, 1, "Number of threads for async servers");
DEFINE_string(server_type, "SYNC_SERVER", "Server type");

// Client config
DEFINE_int32(outstanding_rpcs_per_channel, 1,
             "Number of outstanding rpcs per channel");
DEFINE_int32(client_channels, 1, "Number of client channels");

DEFINE_int32(simple_req_size, -1, "Simple proto request payload size");
DEFINE_int32(simple_resp_size, -1, "Simple proto response payload size");
DEFINE_int32(bbuf_req_size, -1, "Byte-buffer request payload size");
DEFINE_int32(bbuf_resp_size, -1, "Byte-buffer response payload size");

DEFINE_string(client_type, "SYNC_CLIENT", "Client type");
DEFINE_int32(async_client_threads, 1, "Async client threads");

DEFINE_double(poisson_load, -1.0, "Poisson offered load (qps)");
DEFINE_double(uniform_lo, -1.0, "Uniform low interarrival time (us)");
DEFINE_double(uniform_hi, -1.0, "Uniform high interarrival time (us)");
DEFINE_double(determ_load, -1.0, "Deterministic offered load (qps)");
DEFINE_double(pareto_base, -1.0, "Pareto base interarrival time (us)");
DEFINE_double(pareto_alpha, -1.0, "Pareto alpha value");

DEFINE_bool(secure_test, false, "Run a secure test");

using grpc::testing::ClientConfig;
using grpc::testing::ServerConfig;
using grpc::testing::ClientType;
using grpc::testing::ServerType;
using grpc::testing::RpcType;
using grpc::testing::ResourceUsage;
using grpc::testing::SecurityParams;

namespace grpc {
namespace testing {

static void QpsDriver() {
  RpcType rpc_type;
  GPR_ASSERT(RpcType_Parse(FLAGS_rpc_type, &rpc_type));

  ClientType client_type;
  ServerType server_type;
  GPR_ASSERT(ClientType_Parse(FLAGS_client_type, &client_type));
  GPR_ASSERT(ServerType_Parse(FLAGS_server_type, &server_type));

  ClientConfig client_config;
  client_config.set_client_type(client_type);
  client_config.set_outstanding_rpcs_per_channel(
      FLAGS_outstanding_rpcs_per_channel);
  client_config.set_client_channels(FLAGS_client_channels);

  // Decide which type to use based on the response type
  if (FLAGS_simple_resp_size >= 0) {
    auto params =
        client_config.mutable_payload_config()->mutable_simple_params();
    params->set_resp_size(FLAGS_simple_resp_size);
    if (FLAGS_simple_req_size >= 0) {
      params->set_req_size(FLAGS_simple_req_size);
    }
  } else if (FLAGS_bbuf_resp_size >= 0) {
    auto params =
        client_config.mutable_payload_config()->mutable_bytebuf_params();
    params->set_resp_size(FLAGS_bbuf_resp_size);
    if (FLAGS_bbuf_req_size >= 0) {
      params->set_req_size(FLAGS_bbuf_req_size);
    }
  } else {
    // set a reasonable default: proto but no payload
    client_config.mutable_payload_config()->mutable_simple_params();
  }

  client_config.set_async_client_threads(FLAGS_async_client_threads);
  client_config.set_rpc_type(rpc_type);

  // set up the load parameters
  if (FLAGS_poisson_load > 0.0) {
    auto poisson = client_config.mutable_load_params()->mutable_poisson();
    poisson->set_offered_load(FLAGS_poisson_load);
  } else if (FLAGS_uniform_lo > 0.0) {
    auto uniform = client_config.mutable_load_params()->mutable_uniform();
    uniform->set_interarrival_lo(FLAGS_uniform_lo / 1e6);
    uniform->set_interarrival_hi(FLAGS_uniform_hi / 1e6);
  } else if (FLAGS_determ_load > 0.0) {
    auto determ = client_config.mutable_load_params()->mutable_determ();
    determ->set_offered_load(FLAGS_determ_load);
  } else if (FLAGS_pareto_base > 0.0) {
    auto pareto = client_config.mutable_load_params()->mutable_pareto();
    pareto->set_interarrival_base(FLAGS_pareto_base / 1e6);
    pareto->set_alpha(FLAGS_pareto_alpha);
  } else {
    client_config.mutable_load_params()->mutable_closed_loop();
    // No further load parameters to set up for closed loop
  }

  client_config.mutable_histogram_params()->set_resolution(
      Histogram::default_resolution());
  client_config.mutable_histogram_params()->set_max_possible(
      Histogram::default_max_possible());

  ServerConfig server_config;
  server_config.set_server_type(server_type);
  server_config.set_host("::");  // Use the wildcard server address
  server_config.set_async_server_threads(FLAGS_async_server_threads);

  if (FLAGS_secure_test) {
    // Set up security params
    SecurityParams security;
    security.set_use_test_ca(true);
    security.set_server_host_override("foo.test.google.fr");
    client_config.mutable_security_params()->CopyFrom(security);
    server_config.mutable_security_params()->CopyFrom(security);
  }

  // Make sure that if we are performing a generic (bytebuf) test
  // that we are also using async streaming
  GPR_ASSERT(!client_config.payload_config().has_bytebuf_params() ||
             (client_config.client_type() == ASYNC_CLIENT &&
              client_config.rpc_type() == STREAMING &&
              server_config.server_type() == ASYNC_SERVER));

  const auto result = RunScenario(
      client_config, FLAGS_num_clients, server_config, FLAGS_num_servers,
      FLAGS_warmup_seconds, FLAGS_benchmark_seconds, FLAGS_local_workers);

  GetReporter()->ReportQPS(*result);
  GetReporter()->ReportQPSPerCore(*result);
  GetReporter()->ReportLatency(*result);
  GetReporter()->ReportTimes(*result);
}

}  // namespace testing
}  // namespace grpc

int main(int argc, char** argv) {
  grpc::testing::InitBenchmark(&argc, &argv, true);

  grpc::testing::QpsDriver();

  return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: pam.hxx,v $
 *
 *  $Revision: 1.12 $
 *
 *  last change: $Author: vg $ $Date: 2005-02-22 08:16:40 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _PAM_HXX
#define _PAM_HXX

#include <stddef.h>         // fuer MemPool
#ifndef _GEN_HXX //autogen
#include <tools/gen.hxx>
#endif
#ifndef _SVMEMPOOL_HXX //autogen
#include <tools/mempool.hxx>
#endif

#ifndef _CSHTYP_HXX
#include <cshtyp.hxx>       // fuer die Funktions-Definitionen
#endif
#ifndef _RING_HXX
#include <ring.hxx>         // Superklasse
#endif
#ifndef _INDEX_HXX
#include <index.hxx>        // fuer SwIndex
#endif
#ifndef _NDINDEX_HXX
#include <ndindex.hxx>      // fuer SwNodeIndex
#endif

#ifndef INCLUDED_SWDLLAPI_H
#include "swdllapi.h"
#endif

class SwFmt;
class SfxPoolItem;
class SfxItemSet;
class SwDoc;
class SwNode;
class SwCntntNode;
class SwNodes;
class SwPaM;

namespace com { namespace sun { namespace star { namespace util {
    struct SearchOptions;
} } } }

namespace utl {
    class TextSearch;
};

struct SwPosition
{
    SwNodeIndex nNode;
    SwIndex nContent;

    SwPosition( const SwNode& rNode );
    SwPosition( const SwNodeIndex &rNode );
    SwPosition( const SwNodeIndex &rNode, const SwIndex &rCntnt );

    SwPosition( const SwPosition & );
    SwPosition &operator=(const SwPosition &);

    // #111827#
    /**
       Returns the document this position is in.

       @return the document this position is in.
    */
    SwDoc * GetDoc() const;

    FASTBOOL operator < (const SwPosition &) const;
    FASTBOOL operator > (const SwPosition &) const;
    FASTBOOL operator <=(const SwPosition &) const;
    FASTBOOL operator >=(const SwPosition &) const;
    FASTBOOL operator ==(const SwPosition &) const;
    FASTBOOL operator !=(const SwPosition &) const;
};

// das Ergebnis eines Positions Vergleiches
enum SwComparePosition {
    POS_BEFORE,             // Pos1 liegt vor Pos2
    POS_BEHIND,             // Pos1 liegt hinter Pos2
    POS_INSIDE,             // Pos1 liegt vollstaendig in Pos2
    POS_OUTSIDE,            // Pos2 liegt vollstaendig in Pos1
    POS_EQUAL,              // Pos1 ist genauso gross wie Pos2
    POS_OVERLAP_BEFORE,     // Pos1 ueberlappt Pos2 am Anfang
    POS_OVERLAP_BEHIND,     // Pos1 ueberlappt Pos2 am Ende
    POS_COLLIDE_START,      // Pos1 Start stoesst an Pos2 Ende
    POS_COLLIDE_END         // Pos1 End stoesst an Pos2 Start
};
SwComparePosition ComparePosition(
            const SwPosition& rStt1, const SwPosition& rEnd1,
            const SwPosition& rStt2, const SwPosition& rEnd2 );

SwComparePosition ComparePosition(
            const unsigned long nStt1, const unsigned long nEnd1,
            const unsigned long nStt2, const unsigned long nEnd2 );

// SwPointAndMark / SwPaM
struct SwMoveFnCollection;
typedef SwMoveFnCollection* SwMoveFn;
SW_DLLPUBLIC extern SwMoveFn fnMoveForward; // SwPam::Move()/Find() default argument.
extern SwMoveFn fnMoveBackward;

typedef FASTBOOL (*SwGoInDoc)( SwPaM& rPam, SwMoveFn fnMove );
extern SwGoInDoc fnGoDoc;
extern SwGoInDoc fnGoSection;
extern SwGoInDoc fnGoNode;
SW_DLLPUBLIC extern SwGoInDoc fnGoCntnt; // SwPam::Move() default argument.
extern SwGoInDoc fnGoCntntCells;
extern SwGoInDoc fnGoCntntSkipHidden;
extern SwGoInDoc fnGoCntntCellsSkipHidden;

void _InitPam();

class SwPaM : public Ring
{
    SwPosition aBound1;
    SwPosition aBound2;
    SwPosition *pPoint;
    SwPosition *pMark;
    FASTBOOL bIsInFrontOfLabel;

    SwPaM* MakeRegion( SwMoveFn fnMove, const SwPaM * pOrigRg = 0 );

public:
    SwPaM( const SwPosition& rPos, SwPaM* pRing = 0 );
    SwPaM( const SwPosition& rMk, const SwPosition& rPt, SwPaM* pRing = 0 );
    SwPaM( const SwNodeIndex& rMk, const SwNodeIndex& rPt,
           long nMkOffset = 0, long nPtOffset = 0, SwPaM* pRing = 0 );
    SwPaM( const SwNode& rMk, const SwNode& rPt,
           long nMkOffset = 0, long nPtOffset = 0, SwPaM* pRing = 0 );
    SwPaM(  const SwNodeIndex& rMk, xub_StrLen nMkCntnt,
            const SwNodeIndex& rPt, xub_StrLen nPtCntnt, SwPaM* pRing = 0 );
    SwPaM(  const SwNode& rMk, xub_StrLen nMkCntnt,
            const SwNode& rPt, xub_StrLen nPtCntnt, SwPaM* pRing = 0 );
    SwPaM( const SwNode& rNd, xub_StrLen nCntnt = 0, SwPaM* pRing = 0 );
    SwPaM( const SwNodeIndex& rNd, xub_StrLen nCntnt = 0, SwPaM* pRing = 0 );
    virtual ~SwPaM();

    // @@@ semantic: no copy ctor.
    SwPaM( SwPaM & );
    // @@@ semantic: no copy assignment for super class Ring.
    SwPaM& operator=( const SwPaM & );

    // Bewegen des Cursors
    FASTBOOL Move( SwMoveFn fnMove = fnMoveForward,
                    SwGoInDoc fnGo = fnGoCntnt );

    // Suchen
    BYTE Find(  const com::sun::star::util::SearchOptions& rSearchOpt,
                utl::TextSearch& rSTxt,
                SwMoveFn fnMove = fnMoveForward,
                const SwPaM *pPam =0, FASTBOOL bInReadOnly = FALSE);
    FASTBOOL Find(  const SwFmt& rFmt,
                SwMoveFn fnMove = fnMoveForward,
                const SwPaM *pPam =0, FASTBOOL bInReadOnly = FALSE);
    FASTBOOL Find(  const SfxPoolItem& rAttr, FASTBOOL bValue = TRUE,
                SwMoveFn fnMove = fnMoveForward,
                const SwPaM *pPam =0, FASTBOOL bInReadOnly = FALSE );
    FASTBOOL Find(  const SfxItemSet& rAttr, FASTBOOL bNoColls = FALSE,
                SwMoveFn fnMove = fnMoveForward,
                const SwPaM *pPam =0, FASTBOOL bInReadOnly = FALSE );

    inline FASTBOOL IsInFrontOfLabel() const { return bIsInFrontOfLabel; }
    inline void _SetInFrontOfLabel( FASTBOOL bNew ) { bIsInFrontOfLabel = bNew; }

    virtual void SetMark();
    void DeleteMark() { pMark = pPoint; }
#ifdef PRODUCT
    void Exchange()
    {
        if(pPoint != pMark)
        {
            SwPosition *pTmp = pPoint;
            pPoint = pMark;
            pMark = pTmp;
        }
    }
#else
    void Exchange();
#endif
    /*
     * Undokumented Feature: Liefert zurueck, ob das Pam ueber
     * eine Selektion verfuegt oder nicht. Definition einer
     * Selektion: Point und Mark zeigen auf unterschiedliche
     * Puffer.
     */
    FASTBOOL HasMark() const { return pPoint == pMark? FALSE : TRUE; }

    const SwPosition *GetPoint() const { return pPoint; }
          SwPosition *GetPoint()       { return pPoint; }
    const SwPosition *GetMark()  const { return pMark; }
          SwPosition *GetMark()        { return pMark; }

    const SwPosition *Start() const
                    { return (*pPoint) <= (*pMark)? pPoint: pMark; }
          SwPosition *Start()
                    { return (*pPoint) <= (*pMark)? pPoint: pMark; }
    const SwPosition *End()   const
                    { return (*pPoint) > (*pMark)? pPoint: pMark; }
          SwPosition *End()
                    { return (*pPoint) > (*pMark)? pPoint: pMark; }

    // erfrage vom SwPaM den aktuellen Node/ContentNode am SPoint / Mark
    SwNode* GetNode( BOOL bPoint = TRUE ) const
    {
        return &( bPoint ? pPoint->nNode : pMark->nNode ).GetNode();
    }
    SwCntntNode* GetCntntNode( BOOL bPoint = TRUE ) const
    {
        return ( bPoint ? pPoint->nNode : pMark->nNode ).GetNode().GetCntntNode();
    }

    /**
       Normalizes PaM, i.e. sort point and mark.

       @param bPointFirst TRUE: If the point is behind the mark then swap.
                          FALSE: If the mark is behind the point then swap.
    */
    SwPaM & Normalize(BOOL bPointFirst = TRUE);

    // erfrage vom SwPaM das Dokument, in dem er angemeldet ist
    SwDoc* GetDoc() const { return pPoint->nNode.GetNode().GetDoc(); }
    SwPosition& GetBound( BOOL bOne = TRUE )
    {   return bOne ? aBound1 : aBound2; }
    const SwPosition& GetBound( BOOL bOne = TRUE ) const
    {   return bOne ? aBound1 : aBound2; }

    // erfrage die Seitennummer auf der der Cursor steht
    USHORT GetPageNum( BOOL bAtPoint = TRUE, const Point* pLayPos = 0 );

    // steht in etwas geschuetztem oder in die Selektion umspannt
    // etwas geschuetztes.
    FASTBOOL HasReadonlySel( bool bFormView ) const;

    DECL_FIXEDMEMPOOL_NEWDEL(SwPaM);

    String GetTxt() const;
};

FASTBOOL CheckNodesRange( const SwNodeIndex&, const SwNodeIndex&, FASTBOOL );
FASTBOOL GoInCntnt( SwPaM & rPam, SwMoveFn fnMove );

#endif  // _PAM_HXX
<commit_msg>INTEGRATION: CWS ooo19126 (1.12.306); FILE MERGED 2005/09/05 13:36:22 rt 1.12.306.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: pam.hxx,v $
 *
 *  $Revision: 1.13 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 02:04:30 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _PAM_HXX
#define _PAM_HXX

#include <stddef.h>         // fuer MemPool
#ifndef _GEN_HXX //autogen
#include <tools/gen.hxx>
#endif
#ifndef _SVMEMPOOL_HXX //autogen
#include <tools/mempool.hxx>
#endif

#ifndef _CSHTYP_HXX
#include <cshtyp.hxx>       // fuer die Funktions-Definitionen
#endif
#ifndef _RING_HXX
#include <ring.hxx>         // Superklasse
#endif
#ifndef _INDEX_HXX
#include <index.hxx>        // fuer SwIndex
#endif
#ifndef _NDINDEX_HXX
#include <ndindex.hxx>      // fuer SwNodeIndex
#endif

#ifndef INCLUDED_SWDLLAPI_H
#include "swdllapi.h"
#endif

class SwFmt;
class SfxPoolItem;
class SfxItemSet;
class SwDoc;
class SwNode;
class SwCntntNode;
class SwNodes;
class SwPaM;

namespace com { namespace sun { namespace star { namespace util {
    struct SearchOptions;
} } } }

namespace utl {
    class TextSearch;
};

struct SwPosition
{
    SwNodeIndex nNode;
    SwIndex nContent;

    SwPosition( const SwNode& rNode );
    SwPosition( const SwNodeIndex &rNode );
    SwPosition( const SwNodeIndex &rNode, const SwIndex &rCntnt );

    SwPosition( const SwPosition & );
    SwPosition &operator=(const SwPosition &);

    // #111827#
    /**
       Returns the document this position is in.

       @return the document this position is in.
    */
    SwDoc * GetDoc() const;

    FASTBOOL operator < (const SwPosition &) const;
    FASTBOOL operator > (const SwPosition &) const;
    FASTBOOL operator <=(const SwPosition &) const;
    FASTBOOL operator >=(const SwPosition &) const;
    FASTBOOL operator ==(const SwPosition &) const;
    FASTBOOL operator !=(const SwPosition &) const;
};

// das Ergebnis eines Positions Vergleiches
enum SwComparePosition {
    POS_BEFORE,             // Pos1 liegt vor Pos2
    POS_BEHIND,             // Pos1 liegt hinter Pos2
    POS_INSIDE,             // Pos1 liegt vollstaendig in Pos2
    POS_OUTSIDE,            // Pos2 liegt vollstaendig in Pos1
    POS_EQUAL,              // Pos1 ist genauso gross wie Pos2
    POS_OVERLAP_BEFORE,     // Pos1 ueberlappt Pos2 am Anfang
    POS_OVERLAP_BEHIND,     // Pos1 ueberlappt Pos2 am Ende
    POS_COLLIDE_START,      // Pos1 Start stoesst an Pos2 Ende
    POS_COLLIDE_END         // Pos1 End stoesst an Pos2 Start
};
SwComparePosition ComparePosition(
            const SwPosition& rStt1, const SwPosition& rEnd1,
            const SwPosition& rStt2, const SwPosition& rEnd2 );

SwComparePosition ComparePosition(
            const unsigned long nStt1, const unsigned long nEnd1,
            const unsigned long nStt2, const unsigned long nEnd2 );

// SwPointAndMark / SwPaM
struct SwMoveFnCollection;
typedef SwMoveFnCollection* SwMoveFn;
SW_DLLPUBLIC extern SwMoveFn fnMoveForward; // SwPam::Move()/Find() default argument.
extern SwMoveFn fnMoveBackward;

typedef FASTBOOL (*SwGoInDoc)( SwPaM& rPam, SwMoveFn fnMove );
extern SwGoInDoc fnGoDoc;
extern SwGoInDoc fnGoSection;
extern SwGoInDoc fnGoNode;
SW_DLLPUBLIC extern SwGoInDoc fnGoCntnt; // SwPam::Move() default argument.
extern SwGoInDoc fnGoCntntCells;
extern SwGoInDoc fnGoCntntSkipHidden;
extern SwGoInDoc fnGoCntntCellsSkipHidden;

void _InitPam();

class SwPaM : public Ring
{
    SwPosition aBound1;
    SwPosition aBound2;
    SwPosition *pPoint;
    SwPosition *pMark;
    FASTBOOL bIsInFrontOfLabel;

    SwPaM* MakeRegion( SwMoveFn fnMove, const SwPaM * pOrigRg = 0 );

public:
    SwPaM( const SwPosition& rPos, SwPaM* pRing = 0 );
    SwPaM( const SwPosition& rMk, const SwPosition& rPt, SwPaM* pRing = 0 );
    SwPaM( const SwNodeIndex& rMk, const SwNodeIndex& rPt,
           long nMkOffset = 0, long nPtOffset = 0, SwPaM* pRing = 0 );
    SwPaM( const SwNode& rMk, const SwNode& rPt,
           long nMkOffset = 0, long nPtOffset = 0, SwPaM* pRing = 0 );
    SwPaM(  const SwNodeIndex& rMk, xub_StrLen nMkCntnt,
            const SwNodeIndex& rPt, xub_StrLen nPtCntnt, SwPaM* pRing = 0 );
    SwPaM(  const SwNode& rMk, xub_StrLen nMkCntnt,
            const SwNode& rPt, xub_StrLen nPtCntnt, SwPaM* pRing = 0 );
    SwPaM( const SwNode& rNd, xub_StrLen nCntnt = 0, SwPaM* pRing = 0 );
    SwPaM( const SwNodeIndex& rNd, xub_StrLen nCntnt = 0, SwPaM* pRing = 0 );
    virtual ~SwPaM();

    // @@@ semantic: no copy ctor.
    SwPaM( SwPaM & );
    // @@@ semantic: no copy assignment for super class Ring.
    SwPaM& operator=( const SwPaM & );

    // Bewegen des Cursors
    FASTBOOL Move( SwMoveFn fnMove = fnMoveForward,
                    SwGoInDoc fnGo = fnGoCntnt );

    // Suchen
    BYTE Find(  const com::sun::star::util::SearchOptions& rSearchOpt,
                utl::TextSearch& rSTxt,
                SwMoveFn fnMove = fnMoveForward,
                const SwPaM *pPam =0, FASTBOOL bInReadOnly = FALSE);
    FASTBOOL Find(  const SwFmt& rFmt,
                SwMoveFn fnMove = fnMoveForward,
                const SwPaM *pPam =0, FASTBOOL bInReadOnly = FALSE);
    FASTBOOL Find(  const SfxPoolItem& rAttr, FASTBOOL bValue = TRUE,
                SwMoveFn fnMove = fnMoveForward,
                const SwPaM *pPam =0, FASTBOOL bInReadOnly = FALSE );
    FASTBOOL Find(  const SfxItemSet& rAttr, FASTBOOL bNoColls = FALSE,
                SwMoveFn fnMove = fnMoveForward,
                const SwPaM *pPam =0, FASTBOOL bInReadOnly = FALSE );

    inline FASTBOOL IsInFrontOfLabel() const { return bIsInFrontOfLabel; }
    inline void _SetInFrontOfLabel( FASTBOOL bNew ) { bIsInFrontOfLabel = bNew; }

    virtual void SetMark();
    void DeleteMark() { pMark = pPoint; }
#ifdef PRODUCT
    void Exchange()
    {
        if(pPoint != pMark)
        {
            SwPosition *pTmp = pPoint;
            pPoint = pMark;
            pMark = pTmp;
        }
    }
#else
    void Exchange();
#endif
    /*
     * Undokumented Feature: Liefert zurueck, ob das Pam ueber
     * eine Selektion verfuegt oder nicht. Definition einer
     * Selektion: Point und Mark zeigen auf unterschiedliche
     * Puffer.
     */
    FASTBOOL HasMark() const { return pPoint == pMark? FALSE : TRUE; }

    const SwPosition *GetPoint() const { return pPoint; }
          SwPosition *GetPoint()       { return pPoint; }
    const SwPosition *GetMark()  const { return pMark; }
          SwPosition *GetMark()        { return pMark; }

    const SwPosition *Start() const
                    { return (*pPoint) <= (*pMark)? pPoint: pMark; }
          SwPosition *Start()
                    { return (*pPoint) <= (*pMark)? pPoint: pMark; }
    const SwPosition *End()   const
                    { return (*pPoint) > (*pMark)? pPoint: pMark; }
          SwPosition *End()
                    { return (*pPoint) > (*pMark)? pPoint: pMark; }

    // erfrage vom SwPaM den aktuellen Node/ContentNode am SPoint / Mark
    SwNode* GetNode( BOOL bPoint = TRUE ) const
    {
        return &( bPoint ? pPoint->nNode : pMark->nNode ).GetNode();
    }
    SwCntntNode* GetCntntNode( BOOL bPoint = TRUE ) const
    {
        return ( bPoint ? pPoint->nNode : pMark->nNode ).GetNode().GetCntntNode();
    }

    /**
       Normalizes PaM, i.e. sort point and mark.

       @param bPointFirst TRUE: If the point is behind the mark then swap.
                          FALSE: If the mark is behind the point then swap.
    */
    SwPaM & Normalize(BOOL bPointFirst = TRUE);

    // erfrage vom SwPaM das Dokument, in dem er angemeldet ist
    SwDoc* GetDoc() const { return pPoint->nNode.GetNode().GetDoc(); }
    SwPosition& GetBound( BOOL bOne = TRUE )
    {   return bOne ? aBound1 : aBound2; }
    const SwPosition& GetBound( BOOL bOne = TRUE ) const
    {   return bOne ? aBound1 : aBound2; }

    // erfrage die Seitennummer auf der der Cursor steht
    USHORT GetPageNum( BOOL bAtPoint = TRUE, const Point* pLayPos = 0 );

    // steht in etwas geschuetztem oder in die Selektion umspannt
    // etwas geschuetztes.
    FASTBOOL HasReadonlySel( bool bFormView ) const;

    DECL_FIXEDMEMPOOL_NEWDEL(SwPaM);

    String GetTxt() const;
};

FASTBOOL CheckNodesRange( const SwNodeIndex&, const SwNodeIndex&, FASTBOOL );
FASTBOOL GoInCntnt( SwPaM & rPam, SwMoveFn fnMove );

#endif  // _PAM_HXX
<|endoftext|>


<commit_before>// Reverse by Predicate
// c++11, c++14

#include <algorithm>

template <typename I, typename P>
void reverse_by_predicate(I begin, I end, P pred)
    //requires BidirectionalIterator<I> && Predicate<P, ValueType<I>>
{
    while (begin != end) {
        end = std::rotate(begin, std::find_if(begin, end, pred), end);
        if (begin == end) { return; }
        end = std::rotate(begin, std::find_if_not(begin, end, pred), end);
    }
}

// Reverse sub-sequences of some larger sequence.
//
// Useful when elements relate to each other in more complex ways than just
// their position in a range.  In the attached example, we reverse the words in
// a sentence by rotating blocks of "spaces" and "non-spaces" to the end of our
// range.  `std::rotate` returns the new position of what used to be in
// `begin`, which in our case was the start of our block.
//
// Thus by setting our `end` to this return value, we remove it from the blocks
// of text left to reverse.  Finally, we know that the next block of text we
// are to reverse will be the logical negation (`if -> if_not, if_not -> if`)
// of our previous search; hence the alternating rotation points.
//
// In more mathematical terms:
//
//   * Let `H` be longest _"block"_ of values with consistent predicate
//   evaluations.
//   * Let `T` be the rest of the values.
//
//   * Then `reverse(H + T) = reverse(T) + H`; and `T` can be broken up into
//   its own `H + T` pair.
//
//
// *Note*:  This can become more flexible if we allow our predicate to return
// any value, and split on non-equal evaluations.  This is left as an exercise
// for the reader!
//

#include <algorithm>
#include <iostream>
#include <string>

template <typename I, typename P>
void reverse_by_predicate(I begin, I end, P pred)
    //requires BidirectionalIterator<I> && Predicate<P, ValueType<I>>
{
    while (begin != end) {
        end = std::rotate(begin, std::find_if(begin + 1, end, pred), end);
        if (begin == end) { return; }
        end = std::rotate(begin, std::find_if_not(begin + 1, end, pred), end);
    }
}

int main()
{
    std::string str{ "mary had a little lamb whose fleece was white as snow" };
    std::cout << '"' << str << '"' << std::endl;
    reverse_by_predicate(str.begin(), str.end(), ::isspace);
    std::cout << '"' << str << '"' << std::endl;
    // `str` is now: "snow as white was fleece whose lamb little a had mary"
}
<commit_msg>Update reverse-by-predicate.cpp<commit_after>// Reverse by Predicate
// c++11, c++14

#include <algorithm>

template <typename I, typename P>
void reverse_by_predicate(I begin, I end, P pred)
    //requires BidirectionalIterator<I> && Predicate<P, ValueType<I>>
{
    while (begin != end) {
        end = std::rotate(begin, std::find_if(begin, end, pred), end);
        if (begin == end) { return; }
        end = std::rotate(begin, std::find_if_not(begin, end, pred), end);
    }
}

// Reverse sub-sequences of some larger sequence.
//
// Useful when elements relate to each other in more complex ways than just
// their position in a range.  In the attached example, we reverse the words in
// a sentence by rotating blocks of "spaces" and "non-spaces" to the end of our
// range.  `std::rotate` returns the new position of what used to be in
// `begin`, which in our case was the start of our block.
//
// Thus by setting our `end` to this return value, we remove it from the blocks
// of text left to reverse.  Finally, we know that the next block of text we
// are to reverse will be the logical negation (`if -> if_not, if_not -> if`)
// of our previous search; hence the alternating rotation points.
//
// In more mathematical terms:
//
//   * Let `H` be longest _"block"_ of values with consistent predicate
//   evaluations.
//   * Let `T` be the rest of the values.
//
//   * Then `reverse(H + T) = reverse(T) + H`; and `T` can be broken up into
//   its own `H + T` pair.
//
//
// *Note*:  This can become more flexible if we allow our predicate to return
// any value, and split on non-equal evaluations.  This is left as an exercise
// for the reader!
//

#include <algorithm>
#include <iostream>
#include <string>

template <typename I, typename P>
void reverse_by_predicate(I begin, I end, P pred)
    //requires BidirectionalIterator<I> && Predicate<P, ValueType<I>>
{
    while (begin != end) {
        end = std::rotate(begin, std::find_if(begin, end, pred), end);
        if (begin == end) { return; }
        end = std::rotate(begin, std::find_if_not(begin, end, pred), end);
    }
}

int main()
{
    std::string str{ "mary had a little lamb whose fleece was white as snow" };
    std::cout << '"' << str << '"' << std::endl;
    reverse_by_predicate(str.begin(), str.end(), ::isspace);
    std::cout << '"' << str << '"' << std::endl;
    // `str` is now: "snow as white was fleece whose lamb little a had mary"
}
<|endoftext|>


<commit_before>/**
 * @file game_object.hpp
 * @brief Contains methods to game_object class' management. This methods can control the entire
 * game object, setting the components, free them, loading and playing audio, animations, components,
 * setting and displaying hitboxes, detecting and notifing collission with other game objects.
 *
 * MIT License
 * Copyright (c) 2017 MindScape
 *
 * https://github.com/TecProg2017-2/mindscape/blob/master/LICENSE.md
 */

//TODO trocar os vectors de componentes para unordered maps
//TODO acabar com o primeiro construtor e definir hit box como um componente
//TODO colocar todos os estados para usar o SATE MAP

#ifndef GAME_OBJECT_H
#define GAME_OBJECT_H

#include <iostream>
#include <map>
#include <unordered_map>
#include <vector>
#include <list>
#include <string>
#include <utility>
#include "SDL2basics.hpp"
#include "component.hpp"
#include "image.hpp"
#include "text.hpp"
#include "audio.hpp"
#include "hitbox.hpp"
#include "keyboard_event.hpp"
#include "state_map.hpp"
#include "animation.hpp"
#include "observer.hpp"
#include "observable.hpp"
#include "../../include/game_event.hpp"

namespace engine {

    class Animation;

    /**
     * @brief A Game class.
     *
     * This class can control all the components of the game object.
     * @warning Limitations: The number of game object in game is limited to the pc memory. All game object after being
     * used needs to be free.
     */
    class GameObject : public Observer, public Observable {
        private:
            std::pair<float, float> speed;
            std::pair<float, float> position;
            std::vector<Hitbox *> hitboxes;
            Animation* actual_animation = NULL;
            bool active;
            std::list<Observer *> observers;

            void run_collisions(GameObject *);

        protected:
            virtual void on_collision(GameObject *, Hitbox *, Hitbox *) {

            };

        public:
            static bool on_limit_of_level;
            std::string name;
            int priority;
            bool collidable;
            std::vector<Component *> audios;
            std::vector<Component *> images;
            std::vector<Component *> texts;
            std::map<std::string, Animation *> animations;
            std::map<KeyboardEvent::Key, std::string> translations;
            std::string state;
            std::string game_object_direction;
            StateMap states;

            GameObject() {

            };

            GameObject(
              std::string p_name,
              std::pair<float, float> p_position,
              int p_priority,
              std::map<KeyboardEvent::Key,std::string> p_translations,
              StateMap p_states = StateMap())

            :name(p_name),
            position(p_position),
            active(false),
            priority(p_priority),
            translations(p_translations),
            states(p_states),
            speed(std::make_pair(0.0, 0.0)) {

            };

            ~GameObject() {

            };

            bool load();
            void free();
            void draw();
            void add_component(Component *);
            void add_animation(std::string, Animation *);
            bool equals(GameObject *);
            void collide(GameObject *);
            Audio * get_audio_by_name(std::string);
            void play_song(std::string);
            void stop_song(std::string);
            void set_repetitions(std::string, int repet);
            void set_music_volume(std::string, int vol);
            void free_music(std::string);
            std::pair<float, float> get_position();
            float get_position_x();
            float get_position_y();
            void set_position(std::pair<float, float>);
            void set_position_x(float);
            void set_position_y(float);
            std::pair<float, float> get_speed();
            float get_speed_x();
            float get_speed_y();
            void set_speed(std::pair<float, float>);
            void set_speed_x(float);
            void set_speed_y(float);
            void activate();
            void deactivate();
            void deactivate_components();
            bool is_active();
            std::string get_state(std::string);
            std::vector<Hitbox*> get_hitboxes();
            void create_hitbox(std::pair<int, int>, std::pair<int, int>);
            virtual void on_event(GameEvent) {

            };
            void update_hitboxes();
            virtual void update_state();
            void set_actual_animation(Animation *);
            Animation* get_actual_animation();
            void attach_observer(Observer *);
            void detach_observer(Observer *);
            void notify_observers();
            virtual void notify(Observable *) {

            };
      };
}

#endif
<commit_msg>[INITIALIZATION] Apply initialization in game_object.hpp variables<commit_after>/**
 * @file game_object.hpp
 * @brief Contains methods to game_object class' management. This methods can control the entire
 * game object, setting the components, free them, loading and playing audio, animations, components,
 * setting and displaying hitboxes, detecting and notifing collission with other game objects.
 *
 * MIT License
 * Copyright (c) 2017 MindScape
 *
 * https://github.com/TecProg2017-2/mindscape/blob/master/LICENSE.md
 */

//TODO trocar os vectors de componentes para unordered maps
//TODO acabar com o primeiro construtor e definir hit box como um componente
//TODO colocar todos os estados para usar o SATE MAP

#ifndef GAME_OBJECT_H
#define GAME_OBJECT_H

#include <iostream>
#include <map>
#include <unordered_map>
#include <vector>
#include <list>
#include <string>
#include <utility>
#include "SDL2basics.hpp"
#include "component.hpp"
#include "image.hpp"
#include "text.hpp"
#include "audio.hpp"
#include "hitbox.hpp"
#include "keyboard_event.hpp"
#include "state_map.hpp"
#include "animation.hpp"
#include "observer.hpp"
#include "observable.hpp"
#include "../../include/game_event.hpp"

namespace engine {

    class Animation;

    /**
     * @brief A Game class.
     *
     * This class can control all the components of the game object.
     * @warning Limitations: The number of game object in game is limited to the pc memory. All game object after being
     * used needs to be free.
     */
    class GameObject : public Observer, public Observable {
        private:
            std::pair<float, float> speed = std::make_pair(0.0, 0.0);
            std::pair<float, float> position = std::make_pair(0.0, 0.0);
            std::vector<Hitbox *> hitboxes;
            Animation* actual_animation = NULL;
            bool active = true;
            std::list<Observer *> observers;

            void run_collisions(GameObject *);

        protected:
            virtual void on_collision(GameObject *, Hitbox *, Hitbox *) {

            };

        public:
            static bool on_limit_of_level;
            std::string name;
            int priority;
            bool collidable;
            std::vector<Component *> audios;
            std::vector<Component *> images;
            std::vector<Component *> texts;
            std::map<std::string, Animation *> animations;
            std::map<KeyboardEvent::Key, std::string> translations;
            std::string state;
            std::string game_object_direction;
            StateMap states;

            GameObject() {

            };

            GameObject(
              std::string p_name,
              std::pair<float, float> p_position,
              int p_priority,
              std::map<KeyboardEvent::Key,std::string> p_translations,
              StateMap p_states = StateMap())

            :name(p_name),
            position(p_position),
            active(false),
            priority(p_priority),
            translations(p_translations),
            states(p_states),
            speed(std::make_pair(0.0, 0.0)) {

            };

            ~GameObject() {

            };

            bool load();
            void free();
            void draw();
            void add_component(Component *);
            void add_animation(std::string, Animation *);
            bool equals(GameObject *);
            void collide(GameObject *);
            Audio * get_audio_by_name(std::string);
            void play_song(std::string);
            void stop_song(std::string);
            void set_repetitions(std::string, int repet);
            void set_music_volume(std::string, int vol);
            void free_music(std::string);
            std::pair<float, float> get_position();
            float get_position_x();
            float get_position_y();
            void set_position(std::pair<float, float>);
            void set_position_x(float);
            void set_position_y(float);
            std::pair<float, float> get_speed();
            float get_speed_x();
            float get_speed_y();
            void set_speed(std::pair<float, float>);
            void set_speed_x(float);
            void set_speed_y(float);
            void activate();
            void deactivate();
            void deactivate_components();
            bool is_active();
            std::string get_state(std::string);
            std::vector<Hitbox*> get_hitboxes();
            void create_hitbox(std::pair<int, int>, std::pair<int, int>);
            virtual void on_event(GameEvent) {

            };
            void update_hitboxes();
            virtual void update_state();
            void set_actual_animation(Animation *);
            Animation* get_actual_animation();
            void attach_observer(Observer *);
            void detach_observer(Observer *);
            void notify_observers();
            virtual void notify(Observable *) {

            };
      };
}

#endif
<|endoftext|>


<commit_before>#include "halley/file/path.h"
#include <sstream>

using namespace Halley;

Path::Path()
{}

Path::Path(const char* name)
{
	setPath(name);
}

Path::Path(const std::string& name)
{
	setPath(name);
}

Path::Path(const String& name)
{
	setPath(name);
}

void Path::setPath(const String& value)
{
	String rawPath = value;
#ifdef _WIN32
	rawPath.replace("\\", "/");
#endif

	pathParts = rawPath.split('/');
	normalise();
}

Path::Path(std::vector<String> parts)
	: pathParts(parts)
{
	normalise();
}

void Path::normalise()
{
	size_t writePos = 0;
	bool lastIsBack = false;

	auto write = [&] (const String& p)
	{
		pathParts.at(writePos++) = p;
		lastIsBack = false;
	};

	int n = int(pathParts.size());
	for (int i = 0; i < n; ++i) {
		bool first = i == 0;
		bool last = i == n - 1;

		String current = pathParts[i]; // Important: don't make this a reference
		if (current == "") {
			if (first) {
				write(current);
			} else if (last) {
				write(".");
			}
		} else if (current == ".") {
			if (first || last) {
				write(current);
			}
		} else if (current == "..") {
			if (writePos > 0 && pathParts[writePos - 1] != "..") {
				--writePos;
				lastIsBack = true;
			} else {
				write(current);
			}
		} else {
			write(current);
		}
	}
	if (lastIsBack) {
		write(".");
	}

	pathParts.resize(writePos);
}

Path& Path::operator=(const std::string& other)
{
	setPath(other);
	return *this;
}

Path& Path::operator=(const String& other)
{
	setPath(other);
	return *this;
}

Path Path::getFilename() const
{
	return pathParts.back();
}

Path Path::getStem() const
{
	String filename = getFilename().pathParts.front();
	if (filename == "." || filename == "..") {
		return filename;
	}
	size_t dotPos = filename.find('.');
	return filename.substr(0, dotPos);
}

String Path::getExtension() const
{
	String filename = getFilename().pathParts.front();
	if (filename == "." || filename == "..") {
		return filename;
	}
	size_t dotPos = filename.find('.');
	return filename.substr(dotPos);
}

String Path::getString() const
{
	std::stringstream s;
	bool first = true;
	for (auto& p : pathParts) {
		if (first) {
			first = false;
		} else {
			s << "/";
		}
		s << p;
	}
	return s.str();
}

Path Path::parentPath() const
{
	return Path(getString() + "/..");
}

Path Path::replaceExtension(String newExtension) const
{
	auto parts = pathParts;
	parts.back() = getStem().getString() + newExtension;
	return Path(parts);
}

Path Path::operator/(const char* other) const
{
	return operator/(Path(other));
}

Path Path::operator/(const Path& other) const
{
	auto parts = pathParts;
	for (auto& p : other.pathParts) {
		parts.push_back(p);
	}
	return Path(parts);
}

Path Path::operator/(const String& other) const
{
	return operator/(Path(other));
}

Path Path::operator/(const std::string& other) const
{
	return operator/(Path(other));
}

bool Path::operator==(const char* other) const
{
	return operator==(Path(other));
}

bool Path::operator==(const String& other) const
{
	return operator==(Path(other));
}

bool Path::operator==(const Path& other) const
{
	return ! operator!=(other);
}

bool Path::operator!=(const Path& other) const
{
	if (pathParts.size() != other.pathParts.size()) {
		return true;
	}

	for (size_t i = 0; i < pathParts.size(); ++i) {
		auto& a = pathParts[i];
		auto& b = other.pathParts[i];
#ifdef _WIN32
		if (a.asciiLower() != b.asciiLower()) {
#else
		if (a != b) {
#endif
			return true;
		}
	}
	return false;
}

std::string Path::string() const
{
	return getString().cppStr();
}

std::ostream& Halley::operator<<(std::ostream& os, const Path& p)
{
	return (os << p.string());
}

Path Path::getRoot() const
{
	return pathParts.front();
}

<commit_msg>Fix metafile importing/path extension reading.<commit_after>#include "halley/file/path.h"
#include <sstream>

using namespace Halley;

Path::Path()
{}

Path::Path(const char* name)
{
	setPath(name);
}

Path::Path(const std::string& name)
{
	setPath(name);
}

Path::Path(const String& name)
{
	setPath(name);
}

void Path::setPath(const String& value)
{
	String rawPath = value;
#ifdef _WIN32
	rawPath.replace("\\", "/");
#endif

	pathParts = rawPath.split('/');
	normalise();
}

Path::Path(std::vector<String> parts)
	: pathParts(parts)
{
	normalise();
}

void Path::normalise()
{
	size_t writePos = 0;
	bool lastIsBack = false;

	auto write = [&] (const String& p)
	{
		pathParts.at(writePos++) = p;
		lastIsBack = false;
	};

	int n = int(pathParts.size());
	for (int i = 0; i < n; ++i) {
		bool first = i == 0;
		bool last = i == n - 1;

		String current = pathParts[i]; // Important: don't make this a reference
		if (current == "") {
			if (first) {
				write(current);
			} else if (last) {
				write(".");
			}
		} else if (current == ".") {
			if (first || last) {
				write(current);
			}
		} else if (current == "..") {
			if (writePos > 0 && pathParts[writePos - 1] != "..") {
				--writePos;
				lastIsBack = true;
			} else {
				write(current);
			}
		} else {
			write(current);
		}
	}
	if (lastIsBack) {
		write(".");
	}

	pathParts.resize(writePos);
}

Path& Path::operator=(const std::string& other)
{
	setPath(other);
	return *this;
}

Path& Path::operator=(const String& other)
{
	setPath(other);
	return *this;
}

Path Path::getFilename() const
{
	return pathParts.back();
}

Path Path::getStem() const
{
	String filename = pathParts.back();
	if (filename == "." || filename == "..") {
		return filename;
	}
	size_t dotPos = filename.find_last_of('.');
	return filename.substr(0, dotPos);
}

String Path::getExtension() const
{
	String filename = pathParts.back();
	if (filename == "." || filename == "..") {
		return filename;
	}
	size_t dotPos = filename.find_last_of('.');
	return filename.substr(dotPos);
}

String Path::getString() const
{
	std::stringstream s;
	bool first = true;
	for (auto& p : pathParts) {
		if (first) {
			first = false;
		} else {
			s << "/";
		}
		s << p;
	}
	return s.str();
}

Path Path::parentPath() const
{
	return Path(getString() + "/..");
}

Path Path::replaceExtension(String newExtension) const
{
	auto parts = pathParts;
	parts.back() = getStem().getString() + newExtension;
	return Path(parts);
}

Path Path::operator/(const char* other) const
{
	return operator/(Path(other));
}

Path Path::operator/(const Path& other) const
{
	auto parts = pathParts;
	for (auto& p : other.pathParts) {
		parts.push_back(p);
	}
	return Path(parts);
}

Path Path::operator/(const String& other) const
{
	return operator/(Path(other));
}

Path Path::operator/(const std::string& other) const
{
	return operator/(Path(other));
}

bool Path::operator==(const char* other) const
{
	return operator==(Path(other));
}

bool Path::operator==(const String& other) const
{
	return operator==(Path(other));
}

bool Path::operator==(const Path& other) const
{
	return ! operator!=(other);
}

bool Path::operator!=(const Path& other) const
{
	if (pathParts.size() != other.pathParts.size()) {
		return true;
	}

	for (size_t i = 0; i < pathParts.size(); ++i) {
		auto& a = pathParts[i];
		auto& b = other.pathParts[i];
#ifdef _WIN32
		if (a.asciiLower() != b.asciiLower()) {
#else
		if (a != b) {
#endif
			return true;
		}
	}
	return false;
}

std::string Path::string() const
{
	return getString().cppStr();
}

std::ostream& Halley::operator<<(std::ostream& os, const Path& p)
{
	return (os << p.string());
}

Path Path::getRoot() const
{
	return pathParts.front();
}

<|endoftext|>


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

#if defined(EQUEUE_PLATFORM_MBED)

#include <stdbool.h>
#include "mbed.h"

// Ticker operations
static bool equeue_tick_inited = false;
static volatile unsigned equeue_minutes = 0;
static unsigned equeue_timer[
        (sizeof(Timer)+sizeof(unsigned)-1)/sizeof(unsigned)];
static unsigned equeue_ticker[
        (sizeof(Ticker)+sizeof(unsigned)-1)/sizeof(unsigned)];

static void equeue_tick_update() {
    equeue_minutes += reinterpret_cast<Timer*>(equeue_timer)->read_ms();
    reinterpret_cast<Timer*>(equeue_timer)->reset();
}

static void equeue_tick_init() {
    MBED_STATIC_ASSERT(sizeof(equeue_timer) >= sizeof(Timer),
            "The equeue_timer buffer must fit the class Timer");
    MBED_STATIC_ASSERT(sizeof(equeue_ticker) >= sizeof(Ticker),
            "The equeue_ticker buffer must fit the class Ticker");
    new (equeue_timer) Timer;
    new (equeue_ticker) Ticker;

    equeue_minutes = 0;
    reinterpret_cast<Timer*>(equeue_timer)->start();
    reinterpret_cast<Ticker*>(equeue_ticker)
            ->attach_us(equeue_tick_update, 1000 << 16);

    equeue_tick_inited = true;
}

unsigned equeue_tick() {
    if (!equeue_tick_inited) {
        equeue_tick_init();
    }

    unsigned minutes;
    unsigned ms;

    do {
        minutes = equeue_minutes;
        ms = reinterpret_cast<Timer*>(equeue_timer)->read_ms();
    } while (minutes != equeue_minutes);

    return minutes + ms;
}

// Mutex operations
int equeue_mutex_create(equeue_mutex_t *m) { return 0; }
void equeue_mutex_destroy(equeue_mutex_t *m) { }

void equeue_mutex_lock(equeue_mutex_t *m) {
    core_util_critical_section_enter();
}

void equeue_mutex_unlock(equeue_mutex_t *m) {
    core_util_critical_section_exit();
}

// Semaphore operations
#ifdef MBED_CONF_RTOS_PRESENT

int equeue_sema_create(equeue_sema_t *s) {
    MBED_STATIC_ASSERT(sizeof(equeue_sema_t) >= sizeof(Semaphore),
            "The equeue_sema_t must fit the class Semaphore");
    new (s) Semaphore(0);
    return 0;
}

void equeue_sema_destroy(equeue_sema_t *s) {
    reinterpret_cast<Semaphore*>(s)->~Semaphore();
}

void equeue_sema_signal(equeue_sema_t *s) {
    reinterpret_cast<Semaphore*>(s)->release();
}

bool equeue_sema_wait(equeue_sema_t *s, int ms) {
    if (ms < 0) {
        ms = osWaitForever;
    }

    return (reinterpret_cast<Semaphore*>(s)->wait(ms) > 0);
}

#else

// Semaphore operations
int equeue_sema_create(equeue_sema_t *s) {
    *s = false;
    return 0;
}

void equeue_sema_destroy(equeue_sema_t *s) {
}

void equeue_sema_signal(equeue_sema_t *s) {
    *s = 1;
}

static void equeue_sema_timeout(equeue_sema_t *s) {
    *s = -1;
}

bool equeue_sema_wait(equeue_sema_t *s, int ms) {
    int signal = 0;
    Timeout timeout;
    if (ms > 0) {
        timeout.attach_us(callback(equeue_sema_timeout, s), ms*1000);
    }

    core_util_critical_section_enter();
    while (!*s) {
        sleep();
        core_util_critical_section_exit();
        core_util_critical_section_enter();
    }

    signal = *s;
    *s = false;
    core_util_critical_section_exit();

    return (signal > 0);
}

#endif

#endif
<commit_msg>events: Remove strict-aliasing warning<commit_after>/*
 * Implementation for the mbed library
 * https://github.com/mbedmicro/mbed
 *
 * Copyright (c) 2016 Christopher Haster
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "equeue/equeue_platform.h"

#if defined(EQUEUE_PLATFORM_MBED)

#include <stdbool.h>
#include "mbed.h"

// Ticker operations
static bool equeue_tick_inited = false;
static volatile unsigned equeue_minutes = 0;
static unsigned equeue_timer[
        (sizeof(Timer)+sizeof(unsigned)-1)/sizeof(unsigned)];
static unsigned equeue_ticker[
        (sizeof(Ticker)+sizeof(unsigned)-1)/sizeof(unsigned)];

static void equeue_tick_update() {
    equeue_minutes += reinterpret_cast<Timer*>(equeue_timer)->read_ms();
    reinterpret_cast<Timer*>(equeue_timer)->reset();
}

static void equeue_tick_init() {
    MBED_STATIC_ASSERT(sizeof(equeue_timer) >= sizeof(Timer),
            "The equeue_timer buffer must fit the class Timer");
    MBED_STATIC_ASSERT(sizeof(equeue_ticker) >= sizeof(Ticker),
            "The equeue_ticker buffer must fit the class Ticker");
    Timer *timer = new (equeue_timer) Timer;
    Ticker *ticker = new (equeue_ticker) Ticker;

    equeue_minutes = 0;
    timer->start();
    ticker->attach_us(equeue_tick_update, 1000 << 16);

    equeue_tick_inited = true;
}

unsigned equeue_tick() {
    if (!equeue_tick_inited) {
        equeue_tick_init();
    }

    unsigned minutes;
    unsigned ms;

    do {
        minutes = equeue_minutes;
        ms = reinterpret_cast<Timer*>(equeue_timer)->read_ms();
    } while (minutes != equeue_minutes);

    return minutes + ms;
}

// Mutex operations
int equeue_mutex_create(equeue_mutex_t *m) { return 0; }
void equeue_mutex_destroy(equeue_mutex_t *m) { }

void equeue_mutex_lock(equeue_mutex_t *m) {
    core_util_critical_section_enter();
}

void equeue_mutex_unlock(equeue_mutex_t *m) {
    core_util_critical_section_exit();
}

// Semaphore operations
#ifdef MBED_CONF_RTOS_PRESENT

int equeue_sema_create(equeue_sema_t *s) {
    MBED_STATIC_ASSERT(sizeof(equeue_sema_t) >= sizeof(Semaphore),
            "The equeue_sema_t must fit the class Semaphore");
    new (s) Semaphore(0);
    return 0;
}

void equeue_sema_destroy(equeue_sema_t *s) {
    reinterpret_cast<Semaphore*>(s)->~Semaphore();
}

void equeue_sema_signal(equeue_sema_t *s) {
    reinterpret_cast<Semaphore*>(s)->release();
}

bool equeue_sema_wait(equeue_sema_t *s, int ms) {
    if (ms < 0) {
        ms = osWaitForever;
    }

    return (reinterpret_cast<Semaphore*>(s)->wait(ms) > 0);
}

#else

// Semaphore operations
int equeue_sema_create(equeue_sema_t *s) {
    *s = false;
    return 0;
}

void equeue_sema_destroy(equeue_sema_t *s) {
}

void equeue_sema_signal(equeue_sema_t *s) {
    *s = 1;
}

static void equeue_sema_timeout(equeue_sema_t *s) {
    *s = -1;
}

bool equeue_sema_wait(equeue_sema_t *s, int ms) {
    int signal = 0;
    Timeout timeout;
    if (ms > 0) {
        timeout.attach_us(callback(equeue_sema_timeout, s), ms*1000);
    }

    core_util_critical_section_enter();
    while (!*s) {
        sleep();
        core_util_critical_section_exit();
        core_util_critical_section_enter();
    }

    signal = *s;
    *s = false;
    core_util_critical_section_exit();

    return (signal > 0);
}

#endif

#endif
<|endoftext|>


<commit_before>/** ==========================================================================
* 2014 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
* with no warranties. This code is yours to share, use and modify with no
* strings attached and no restrictions or obligations.
 *
 * For more information see g3log/LICENSE or refer refer to http://unlicense.org
* ============================================================================*/

#include <g2logworker.hpp>
#include <g2log.hpp>
#include <iostream>
#include <cctype>
#include <future>
#include <vector>
#include <string>
#include <chrono>
#include <thread>

namespace
{
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
const std::string path_to_log_file = "./";
#else
const std::string path_to_log_file = "/tmp/";
#endif

void ToLower(std::string &str)
{
   for (auto &character : str) {
      character = std::tolower(character);
   }
}

void RaiseSIGABRT() {
   std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
   raise(SIGABRT);
   LOG(WARNING) << "Expected to have died by now...";
}

void RaiseSIGFPE() {
   std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
   LOGF_IF(INFO, (false != true), "Exiting %s SIGFPE", "by");
   raise(SIGFPE);
   LOG(WARNING) << "Expected to have died by now...";
}

void RaiseSIGSEGV() {
   std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
   LOG(DEBUG) << "Exit by SIGSEGV";
   raise(SIGSEGV);
   LOG(WARNING) << "Expected to have died by now...";
}

void RaiseSIGILL() {
   std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
   LOGF(DEBUG, "Exit by %s", "SIGILL");
   raise(SIGILL);
   LOG(WARNING) << "Expected to have died by now...";
}

void RAiseSIGTERM() {
   std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
   LOGF_IF(INFO, (false != true), "Exiting %s SIGFPE", "by");
   raise(SIGTERM);
   LOG(WARNING) << "Expected to have died by now...";
}

int gShouldBeZero = 1;
void DivisionByZero() {
   std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
   std::cout << "Executing DivisionByZero: gShouldBeZero: "  << gShouldBeZero << std::endl;
   LOG(INFO) << "Division by zero is a big no-no";
   int value = 3;
   auto test = value / gShouldBeZero;
   LOG(WARNING) << "Expected to have died by now..., test value: " << test;
}

void IllegalPrintf() {
   std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
   LOG(DEBUG) << "Impending doom due to illeteracy";
   LOGF(INFO, "2nd attempt at ILLEGAL PRINTF_SYNTAX %d EXAMPLE. %s %s", "hello", 1);
   LOG(WARNING) << "Expected to have died by now...";
}

void OutOfBoundsArrayIndexing() {
   std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
   std::vector<int> v;
   v[0] = 5;
   LOG(WARNING) << "Expected to have died by now...";
}

void AccessViolation() {
   std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
   char* ptr = 0;
   LOG(INFO) << "Death by access violation is imminent";
   *ptr = 0;
   LOG(WARNING) << "Expected to have died by now...";
}

void NoExitFunction() {
   std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
   CHECK(false) << "This function should never be called";
}

void RaiseSIGABRTAndAccessViolation() {
   std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;

   auto f1 = std::async(std::launch::async, &RaiseSIGABRT);
   auto f2 = std::async(std::launch::async, &AccessViolation);
   f1.wait();
   f2.wait();
}

void CallActualExitFunction(std::function<void()> fatal_function) {
   fatal_function();
}

void CallExitFunction(std::function<void()> fatal_function) {
   CallActualExitFunction(fatal_function);
}

void ExecuteDeathFunction(const bool runInNewThread, int fatalChoice) {
   std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
   auto exitFunction = &NoExitFunction;
   switch (fatalChoice) {
   case 1: exitFunction = &RaiseSIGABRT;  break;
   case 2: exitFunction = &RaiseSIGFPE;  break;
   case 3: exitFunction = &RaiseSIGSEGV;  break;
   case 4: exitFunction = &RaiseSIGILL;  break;
   case 5: exitFunction = &RAiseSIGTERM;  break;
   case 6: exitFunction = &DivisionByZero;  gShouldBeZero = 0; DivisionByZero();  break;
   case 7: exitFunction = &IllegalPrintf;  break;
   case 8: exitFunction = &OutOfBoundsArrayIndexing;  break;
   case 9: exitFunction = &AccessViolation;  break;
   case 10: exitFunction = &RaiseSIGABRTAndAccessViolation; break;
   case 11: throw 123456789; break;
   default: break;
   }
   if (runInNewThread) {
      auto dieInNearFuture = std::async(std::launch::async, CallExitFunction, exitFunction);
      dieInNearFuture.wait();
   } else {
      CallExitFunction(exitFunction);
   }

   std::string unexpected = "Expected to exit by FATAL event. That did not happen (printf choice in Windows?).";
   unexpected.append("Choice was: ").append(std::to_string(fatalChoice)).append(", async?: ")
   .append(std::to_string(runInNewThread)).append("\n\n***** TEST WILL RUN AGAIN *****\n\n");

   std::cerr << unexpected  << std::endl;
   LOG(WARNING) << unexpected;

}

bool AskForAsyncDeath() {
   std::string option;
   while (true) {
      option.clear();
      std::cout << "Do you want to run the test in a separate thread? [yes/no]" << std::endl;
      std::getline(std::cin, option);
      ToLower(option);
      if (("yes" != option) && ("no" != option)) {
         std::cout << "\nInvalid value: [" << option << "]\n\n\n";
      } else {
         break;
      }
   }
   return ("yes" == option);
}

int ChoiceOfFatalExit() {
   std::string option;
   int choice = {0};

   while (true) {
      std::cout << "\n\n\n\nChoose your exit" << std::endl;
      std::cout << "By throwing an fatal signal" << std::endl;
      std::cout << "or By executing a fatal code snippet" << std::endl;
      std::cout << "[1] Signal SIGABRT" << std::endl;
      std::cout << "[2] Signal SIGFPE" << std::endl;
      std::cout << "[3] Signal SIGSEGV" << std::endl;
      std::cout << "[4] Signal IGILL" << std::endl;
      std::cout << "[5] Signal SIGTERM" << std::endl;

      std::cout << "[6] Division By Zero" << std::endl;
      std::cout << "[7] Illegal printf" << std::endl;
      std::cout << "[8] Out of bounds array indexing  " << std::endl;
      std::cout << "[9] Access violation" << std::endl;
      std::cout << "[10] Rasing SIGABRT + Access Violation in two separate threads" << std::endl;
      std::cout << "[11] Just throw" << std::endl;

      std::cout << std::flush;

      try {
         std::getline(std::cin, option);
         choice = std::stoi(option);
         if (choice <= 0 || choice > 11) {
            std::cout << "Invalid choice: [" << option << "\n\n";
         }  else {
            return choice;
         }
      } catch (...) {
         std::cout << "Invalid choice: [" << option << "\n\n";
      }
   }
}

void ForwardChoiceForFatalExit(bool runInNewThread, int fatalChoice) {
   ExecuteDeathFunction(runInNewThread, fatalChoice);
}

void ChooseFatalExit() {
   const bool runInNewThread = AskForAsyncDeath();
   const int exitChoice = ChoiceOfFatalExit();
   ForwardChoiceForFatalExit(runInNewThread, exitChoice);
}
} // namespace

int main(int argc, char** argv)
{
   auto logger_n_handle = g2::LogWorker::createWithDefaultLogger(argv[0], path_to_log_file);
   g2::initializeLogging(logger_n_handle.worker.get());
   std::future<std::string> log_file_name = logger_n_handle.sink->call(&g2::FileSink::fileName);
   std::cout << "**** G3LOG FATAL EXAMPLE ***\n\n"
             << "Choose your type of fatal exit, then "
             << " read the generated log and backtrace.\n"
             << "The logfile is generated at:  [" << log_file_name.get() << "]\n\n" << std::endl;

   LOGF(DEBUG, "Fatal exit example starts now, it's as easy as  %d", 123);
   LOG(INFO) << "Feel free to read the source code also in g3log/example/main_fatal_choice.cpp";

   while (true) {
      ChooseFatalExit();
   }

   LOG(WARNING) << "Expected to exit by fatal event, this code line should never be reached";
   CHECK(false) << "Forced death";
   return 0;

}

<commit_msg>Changed what was thrown<commit_after>/** ==========================================================================
* 2014 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
* with no warranties. This code is yours to share, use and modify with no
* strings attached and no restrictions or obligations.
 *
 * For more information see g3log/LICENSE or refer refer to http://unlicense.org
* ============================================================================*/

#include <g2logworker.hpp>
#include <g2log.hpp>
#include <iostream>
#include <cctype>
#include <future>
#include <vector>
#include <string>
#include <chrono>
#include <thread>

namespace
{
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
const std::string path_to_log_file = "./";
#else
const std::string path_to_log_file = "/tmp/";
#endif

void ToLower(std::string &str)
{
   for (auto &character : str) {
      character = std::tolower(character);
   }
}

void RaiseSIGABRT() {
   std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
   raise(SIGABRT);
   LOG(WARNING) << "Expected to have died by now...";
}

void RaiseSIGFPE() {
   std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
   LOGF_IF(INFO, (false != true), "Exiting %s SIGFPE", "by");
   raise(SIGFPE);
   LOG(WARNING) << "Expected to have died by now...";
}

void RaiseSIGSEGV() {
   std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
   LOG(DEBUG) << "Exit by SIGSEGV";
   raise(SIGSEGV);
   LOG(WARNING) << "Expected to have died by now...";
}

void RaiseSIGILL() {
   std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
   LOGF(DEBUG, "Exit by %s", "SIGILL");
   raise(SIGILL);
   LOG(WARNING) << "Expected to have died by now...";
}

void RAiseSIGTERM() {
   std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
   LOGF_IF(INFO, (false != true), "Exiting %s SIGFPE", "by");
   raise(SIGTERM);
   LOG(WARNING) << "Expected to have died by now...";
}

int gShouldBeZero = 1;
void DivisionByZero() {
   std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
   std::cout << "Executing DivisionByZero: gShouldBeZero: "  << gShouldBeZero << std::endl;
   LOG(INFO) << "Division by zero is a big no-no";
   int value = 3;
   auto test = value / gShouldBeZero;
   LOG(WARNING) << "Expected to have died by now..., test value: " << test;
}

void IllegalPrintf() {
   std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
   LOG(DEBUG) << "Impending doom due to illeteracy";
   LOGF(INFO, "2nd attempt at ILLEGAL PRINTF_SYNTAX %d EXAMPLE. %s %s", "hello", 1);
   LOG(WARNING) << "Expected to have died by now...";
}

void OutOfBoundsArrayIndexing() {
   std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
   std::vector<int> v;
   v[0] = 5;
   LOG(WARNING) << "Expected to have died by now...";
}

void AccessViolation() {
   std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
   char* ptr = 0;
   LOG(INFO) << "Death by access violation is imminent";
   *ptr = 0;
   LOG(WARNING) << "Expected to have died by now...";
}

void NoExitFunction() {
   std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
   CHECK(false) << "This function should never be called";
}

void RaiseSIGABRTAndAccessViolation() {
   std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;

   auto f1 = std::async(std::launch::async, &RaiseSIGABRT);
   auto f2 = std::async(std::launch::async, &AccessViolation);
   f1.wait();
   f2.wait();
}

void CallActualExitFunction(std::function<void()> fatal_function) {
   fatal_function();
}

void CallExitFunction(std::function<void()> fatal_function) {
   CallActualExitFunction(fatal_function);
}

void ExecuteDeathFunction(const bool runInNewThread, int fatalChoice) {
   std::cout << "Calling :" << __FUNCTION__ << " Line: " << __LINE__ << std::endl << std::flush;
   auto exitFunction = &NoExitFunction;
   switch (fatalChoice) {
   case 1: exitFunction = &RaiseSIGABRT;  break;
   case 2: exitFunction = &RaiseSIGFPE;  break;
   case 3: exitFunction = &RaiseSIGSEGV;  break;
   case 4: exitFunction = &RaiseSIGILL;  break;
   case 5: exitFunction = &RAiseSIGTERM;  break;
   case 6: exitFunction = &DivisionByZero;  gShouldBeZero = 0; DivisionByZero();  break;
   case 7: exitFunction = &IllegalPrintf;  break;
   case 8: exitFunction = &OutOfBoundsArrayIndexing;  break;
   case 9: exitFunction = &AccessViolation;  break;
   case 10: exitFunction = &RaiseSIGABRTAndAccessViolation; break;
   case 11: throw 1233210; break;
   default: break;
   }
   if (runInNewThread) {
      auto dieInNearFuture = std::async(std::launch::async, CallExitFunction, exitFunction);
      dieInNearFuture.wait();
   } else {
      CallExitFunction(exitFunction);
   }

   std::string unexpected = "Expected to exit by FATAL event. That did not happen (printf choice in Windows?).";
   unexpected.append("Choice was: ").append(std::to_string(fatalChoice)).append(", async?: ")
   .append(std::to_string(runInNewThread)).append("\n\n***** TEST WILL RUN AGAIN *****\n\n");

   std::cerr << unexpected  << std::endl;
   LOG(WARNING) << unexpected;

}

bool AskForAsyncDeath() {
   std::string option;
   while (true) {
      option.clear();
      std::cout << "Do you want to run the test in a separate thread? [yes/no]" << std::endl;
      std::getline(std::cin, option);
      ToLower(option);
      if (("yes" != option) && ("no" != option)) {
         std::cout << "\nInvalid value: [" << option << "]\n\n\n";
      } else {
         break;
      }
   }
   return ("yes" == option);
}

int ChoiceOfFatalExit() {
   std::string option;
   int choice = {0};

   while (true) {
      std::cout << "\n\n\n\nChoose your exit" << std::endl;
      std::cout << "By throwing an fatal signal" << std::endl;
      std::cout << "or By executing a fatal code snippet" << std::endl;
      std::cout << "[1] Signal SIGABRT" << std::endl;
      std::cout << "[2] Signal SIGFPE" << std::endl;
      std::cout << "[3] Signal SIGSEGV" << std::endl;
      std::cout << "[4] Signal IGILL" << std::endl;
      std::cout << "[5] Signal SIGTERM" << std::endl;

      std::cout << "[6] Division By Zero" << std::endl;
      std::cout << "[7] Illegal printf" << std::endl;
      std::cout << "[8] Out of bounds array indexing  " << std::endl;
      std::cout << "[9] Access violation" << std::endl;
      std::cout << "[10] Rasing SIGABRT + Access Violation in two separate threads" << std::endl;
      std::cout << "[11] Just throw" << std::endl;

      std::cout << std::flush;

      try {
         std::getline(std::cin, option);
         choice = std::stoi(option);
         if (choice <= 0 || choice > 11) {
            std::cout << "Invalid choice: [" << option << "\n\n";
         }  else {
            return choice;
         }
      } catch (...) {
         std::cout << "Invalid choice: [" << option << "\n\n";
      }
   }
}

void ForwardChoiceForFatalExit(bool runInNewThread, int fatalChoice) {
   ExecuteDeathFunction(runInNewThread, fatalChoice);
}

void ChooseFatalExit() {
   const bool runInNewThread = AskForAsyncDeath();
   const int exitChoice = ChoiceOfFatalExit();
   ForwardChoiceForFatalExit(runInNewThread, exitChoice);
}
} // namespace

int main(int argc, char** argv)
{
   auto logger_n_handle = g2::LogWorker::createWithDefaultLogger(argv[0], path_to_log_file);
   g2::initializeLogging(logger_n_handle.worker.get());
   std::future<std::string> log_file_name = logger_n_handle.sink->call(&g2::FileSink::fileName);
   std::cout << "**** G3LOG FATAL EXAMPLE ***\n\n"
             << "Choose your type of fatal exit, then "
             << " read the generated log and backtrace.\n"
             << "The logfile is generated at:  [" << log_file_name.get() << "]\n\n" << std::endl;

   LOGF(DEBUG, "Fatal exit example starts now, it's as easy as  %d", 123);
   LOG(INFO) << "Feel free to read the source code also in g3log/example/main_fatal_choice.cpp";

   while (true) {
      ChooseFatalExit();
   }

   LOG(WARNING) << "Expected to exit by fatal event, this code line should never be reached";
   CHECK(false) << "Forced death";
   return 0;

}

<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <functional>
#include <memory>
#include <cmath>
#include <cstring>

#include "../include/Neuralnet.hpp"
#include "../include/Layer.hpp"
#include "../include/FullyConnected.hpp"
#include "../include/Convolutional.hpp"
#include "../include/Pooling.hpp"

using namespace std;

// pixel normalize function
void normalize ( vector<vector<vector<double>>>& image, vector<vector<double>>& ave )
{
    for( int i = 0; i < image[0].size(); ++i ){
        ave.emplace_back(image[0][0].size(), 0.0);

        for( int j = 0; j < image.size(); ++j ){
            for( int k = 0; k < image[0][i].size(); ++k ) ave[i][k] += image[j][i][k];
        }
        for( int j = 0; j < image[0][i].size(); ++j ) ave[i][j] /= image.size();

        for( int j = 0; j < image.size(); ++j )
			for( int k = 0; k < image[0][i].size(); ++k )
				image[j][i][k] -= ave[i][k];
    }
}

int main( int argc, char* argv[] )
{
	// define mini-batch size.
	const int BATCH_SIZE = 50;

	// parallelism for model parallel.
	int INNER = 1;
	for( int i = 1; i < argc; ++i ){
		if( strcmp(argv[i], "--inner") == 0 ){
			sscanf(argv[i+1], "%d", &INNER);
			++i;
		}
	}

	MPI_Init(&argc, &argv);

	MPI_Comm outer_world, inner_world;
	int world_rank, world_nprocs;       // rank and number of processes in all processes.
	int inner_rank, inner_nprocs;       // rank and number of processes in model parallel.
	int outer_rank, outer_nprocs;       // rank and number of processes in data parallel.

	MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
	MPI_Comm_size(MPI_COMM_WORLD, &world_nprocs);

	// determine model parallel's rank of each processes.
	MPI_Comm_split(MPI_COMM_WORLD, world_rank / INNER, world_rank, &inner_world);
	MPI_Comm_rank(inner_world, &inner_rank);
	MPI_Comm_size(inner_world, &inner_nprocs);

	// determine data parallel's rank of each processes.
	MPI_Comm_split(MPI_COMM_WORLD, world_rank % INNER, world_rank, &outer_world);
	MPI_Comm_rank(outer_world, &outer_rank);
	MPI_Comm_size(outer_world, &outer_nprocs);

	// construct neuralnetwork with CrossEntropy.
    Neuralnet net(shared_ptr<LossFunction>(new CrossEntropy), outer_world, inner_world);
	vector<shared_ptr<Layer>> layers;

	// define layers.
	layers.emplace_back(new Convolutional(1, 28*28, 28,
										  10, 28*28, 28,
										  5, 5, 1, shared_ptr<Function>(new ReLU)));
	layers.emplace_back(new Pooling(10, 28*28, 28,
									10, 14*14, 14,
									3, 3, 2, shared_ptr<Function>(new Identity)));
	layers.emplace_back(new Convolutional(10, 14*14, 14,
										  20, 14*14, 14,
										  5, 5, 1, shared_ptr<Function>(new ReLU)));
	layers.emplace_back(new Pooling(20, 14*14, 14,
									20, 7*7, 7,
									2, 2, 2, shared_ptr<Function>(new Identity)));
	layers.emplace_back(new FullyConnected(20, 7*7, 1, 512, shared_ptr<Function>(new ReLU)));
	layers.emplace_back(new FullyConnected(1, 512, 1, 10, shared_ptr<Function>(new Softmax)));

	// this neuralnet has 7 layers, input, Conv1, MaxPool, Conv2, MaxPool, Fc1 and Fc2;
	for( int i = 0; i < layers.size(); ++i ){
		net.add_layer(layers[i]);
	}

	// read a test data of MNIST(http://yann.lecun.com/exdb/mnist/).
	vector<int> train_lab;
	vector<vector<vector<double>>> train_x;
	const int N = 10000 / outer_nprocs;
	ifstream train_image("train-images-idx3-ubyte", ios_base::binary);
	ifstream train_image("train-images-idx3-ubyte", ios_base::binary);
	if( !train_image.is_open() ){
		cerr << "\"train-images-idx3-ubyte\" is not found!" << endl;
		return 1;
	}
	ifstream train_label("train-labels-idx1-ubyte", ios_base::binary);
	if( !train_label.is_open() ){
		cerr << "\"train-labels-idx1-ubyte\" is not found!" << endl;
		return 1;
	}

	train_image.seekg(4*4 + 28*28*outer_rank * N, ios_base::beg);
	train_label.seekg(4*2 + outer_rank * N, ios_base::beg);
	for( int i = 0; i < N; ++i ){
		unsigned char tmp_lab;
		train_label.read((char*)&tmp_lab, sizeof(unsigned char));
		train_lab.push_back(tmp_lab);

		vector<vector<double>> tmp(1, vector<double>(28*28));
		for( int j = 0; j < 28*28; ++j ){
			unsigned char c;
			train_image.read((char*)&c, sizeof(unsigned char));
			tmp[0][j] = (c/255.0);
		}

		train_x.push_back(tmp);
	}

	// set supervised data.
	vector<vector<vector<double>>> d(N, vector<vector<double>>(1, vector<double>(10, 0.0)));
	for( int i = 0; i < N; ++i ) d[i][0][train_lab[i]] = 1.0;

	vector<vector<double>> ave;
	// normalize train image.
	normalize(train_x, ave);

	// read a train data of MNIST.
	vector<int> test_lab;
	vector<vector<vector<double>>> test_x;
	const int M = 5000;
	ifstream test_image("t10k-images-idx3-ubyte", ios_base::binary);
	if( !test_image.is_open() ){
		cerr << "\"t10k-images-idx3-ubyte\" is not found!" << endl;
		return 1;
	}
	ifstream test_label("t10k-labels-idx1-ubyte", ios_base::binary);
	if( !test_label.is_open() ){
		cerr << "\"t10k-labels-idx1-ubyte\" is not found!" << endl;
		return 1;
	}

	test_image.seekg(4*4, ios_base::beg);
	test_label.seekg(4*2, ios_base::beg);
	for( int i = 0; i < M; ++i ){
		unsigned char tmp_lab;
		test_label.read((char*)&tmp_lab, sizeof(unsigned char));
		test_lab.push_back(tmp_lab);

		vector<vector<double>> tmp(1, vector<double>(28*28));
		for( int j = 0; j < 28*28; ++j ){
			unsigned char c;
			test_image.read((char*)&c, sizeof(unsigned char));
			tmp[0][j] = (c/255.0 - ave[0][j]);
		}

		test_x.push_back(tmp);
	}

	// train data into Matrix class for checking error.
	vector<Matrix<double>> X(1, Matrix<double>(28*28, M)), D(1, Matrix<double>(10, M));
	for( int i = 0; i < M; ++i ){
		for( int j = 0; j < 28*28; ++j ){
			X[0](j, i) = test_x[i][0][j];
		}
		D[0](test_lab[i], i) = 1.0;
	}

	// checking error function.
	double prev_time, total_time;
	auto check_error = [&](const Neuralnet& nn, const int iter, const std::vector<Matrix<double>>& x, const std::vector<Matrix<double>>& d ) -> void {
		if( iter%((N/BATCH_SIZE)) != 0 || iter == 0 ) return;

		double tmp_time = MPI_Wtime();

		// calculating answer rate among all train data.
		int train_ans_num = 0;
		auto y = nn.apply(train_x);
		for( int i = 0; i < y.size(); ++i ){
			int idx, lab;
			double max_num = 0.0;
			for( int j = 0; j < 10; ++j ){
				if( max_num < y[i][0][j] ){
					max_num = y[i][0][j];
					idx = j;
				}
			}
			if( idx == train_lab[i] ) ++train_ans_num;
		}

		// calculating answer rate among all test data.
		int test_ans_num = 0;
		auto Y = nn.apply(X);
		for( int i = 0; i < Y[0].n; ++i ){
			int idx, lab;
			double max_num = 0.0;
			for( int j = 0; j < 10; ++j ){
				if( max_num < Y[0](j,i) ){
					max_num = Y[0](j,i);
					idx = j;
				}
				if( D[0](j, i) == 1.0 ) lab = j;
			}
			if( idx == lab ) ++test_ans_num;
		}

		// output answer rate each test data batch.
		if( inner_rank == 0 ){
			for( int i = 0; i < outer_nprocs; ++i ){
				if( i == outer_rank ){
					printf("outer rank : %d\n", outer_rank);
					printf("  Elapsed time : %.3f, Total time : %.3f\n", MPI_Wtime() - prev_time, MPI_Wtime() - total_time);
					printf("  Train answer rate : %.2f%%\n", (double)train_ans_num/y.size()*100.0);
					printf("  Test answer rate  : %.2f%%\n", (double)test_ans_num/X[0].n*100.0);
				}
				MPI_Barrier(outer_world);
			}
			prev_time = MPI_Wtime();
		}
		if( world_rank == 0 ) puts("");
	};

	// set a hyper parameter.
	net.set_EPS(1.0E-3);
	net.set_LAMBDA(0.0);
	net.set_BATCHSIZE(BATCH_SIZE);
	net.set_UPDATEITER(N/BATCH_SIZE*2);
	// learning the neuralnet in 20 EPOCH and output error defined above in each epoch.
	prev_time = total_time = MPI_Wtime();
	net.learning(train_x, d, N/BATCH_SIZE*10, check_error);

	MPI_Finalize();
}
<commit_msg>Fixed compile error.<commit_after>#include <iostream>
#include <fstream>
#include <functional>
#include <memory>
#include <cmath>
#include <cstring>

#include "../include/Neuralnet.hpp"
#include "../include/Layer.hpp"
#include "../include/FullyConnected.hpp"
#include "../include/Convolutional.hpp"
#include "../include/Pooling.hpp"

using namespace std;

// pixel normalize function
void normalize ( vector<vector<vector<double>>>& image, vector<vector<double>>& ave )
{
    for( int i = 0; i < image[0].size(); ++i ){
        ave.emplace_back(image[0][0].size(), 0.0);

        for( int j = 0; j < image.size(); ++j ){
            for( int k = 0; k < image[0][i].size(); ++k ) ave[i][k] += image[j][i][k];
        }
        for( int j = 0; j < image[0][i].size(); ++j ) ave[i][j] /= image.size();

        for( int j = 0; j < image.size(); ++j )
			for( int k = 0; k < image[0][i].size(); ++k )
				image[j][i][k] -= ave[i][k];
    }
}

int main( int argc, char* argv[] )
{
	// define mini-batch size.
	const int BATCH_SIZE = 50;

	// parallelism for model parallel.
	int INNER = 1;
	for( int i = 1; i < argc; ++i ){
		if( strcmp(argv[i], "--inner") == 0 ){
			sscanf(argv[i+1], "%d", &INNER);
			++i;
		}
	}

	MPI_Init(&argc, &argv);

	MPI_Comm outer_world, inner_world;
	int world_rank, world_nprocs;       // rank and number of processes in all processes.
	int inner_rank, inner_nprocs;       // rank and number of processes in model parallel.
	int outer_rank, outer_nprocs;       // rank and number of processes in data parallel.

	MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
	MPI_Comm_size(MPI_COMM_WORLD, &world_nprocs);

	// determine model parallel's rank of each processes.
	MPI_Comm_split(MPI_COMM_WORLD, world_rank / INNER, world_rank, &inner_world);
	MPI_Comm_rank(inner_world, &inner_rank);
	MPI_Comm_size(inner_world, &inner_nprocs);

	// determine data parallel's rank of each processes.
	MPI_Comm_split(MPI_COMM_WORLD, world_rank % INNER, world_rank, &outer_world);
	MPI_Comm_rank(outer_world, &outer_rank);
	MPI_Comm_size(outer_world, &outer_nprocs);

	// construct neuralnetwork with CrossEntropy.
    Neuralnet net(shared_ptr<LossFunction>(new CrossEntropy), outer_world, inner_world);
	vector<shared_ptr<Layer>> layers;

	// define layers.
	layers.emplace_back(new Convolutional(1, 28*28, 28,
										  10, 28*28, 28,
										  5, 5, 1, shared_ptr<Function>(new ReLU)));
	layers.emplace_back(new Pooling(10, 28*28, 28,
									10, 14*14, 14,
									3, 3, 2, shared_ptr<Function>(new Identity)));
	layers.emplace_back(new Convolutional(10, 14*14, 14,
										  20, 14*14, 14,
										  5, 5, 1, shared_ptr<Function>(new ReLU)));
	layers.emplace_back(new Pooling(20, 14*14, 14,
									20, 7*7, 7,
									2, 2, 2, shared_ptr<Function>(new Identity)));
	layers.emplace_back(new FullyConnected(20, 7*7, 1, 512, shared_ptr<Function>(new ReLU)));
	layers.emplace_back(new FullyConnected(1, 512, 1, 10, shared_ptr<Function>(new Softmax)));

	// this neuralnet has 7 layers, input, Conv1, MaxPool, Conv2, MaxPool, Fc1 and Fc2;
	for( int i = 0; i < layers.size(); ++i ){
		net.add_layer(layers[i]);
	}

	// read a test data of MNIST(http://yann.lecun.com/exdb/mnist/).
	vector<int> train_lab;
	vector<vector<vector<double>>> train_x;
	const int N = 10000 / outer_nprocs;
	ifstream train_image("train-images-idx3-ubyte", ios_base::binary);
	if( !train_image.is_open() ){
		cerr << "\"train-images-idx3-ubyte\" is not found!" << endl;
		return 1;
	}
	ifstream train_label("train-labels-idx1-ubyte", ios_base::binary);
	if( !train_label.is_open() ){
		cerr << "\"train-labels-idx1-ubyte\" is not found!" << endl;
		return 1;
	}

	train_image.seekg(4*4 + 28*28*outer_rank * N, ios_base::beg);
	train_label.seekg(4*2 + outer_rank * N, ios_base::beg);
	for( int i = 0; i < N; ++i ){
		unsigned char tmp_lab;
		train_label.read((char*)&tmp_lab, sizeof(unsigned char));
		train_lab.push_back(tmp_lab);

		vector<vector<double>> tmp(1, vector<double>(28*28));
		for( int j = 0; j < 28*28; ++j ){
			unsigned char c;
			train_image.read((char*)&c, sizeof(unsigned char));
			tmp[0][j] = (c/255.0);
		}

		train_x.push_back(tmp);
	}

	// set supervised data.
	vector<vector<vector<double>>> d(N, vector<vector<double>>(1, vector<double>(10, 0.0)));
	for( int i = 0; i < N; ++i ) d[i][0][train_lab[i]] = 1.0;

	vector<vector<double>> ave;
	// normalize train image.
	normalize(train_x, ave);

	// read a train data of MNIST.
	vector<int> test_lab;
	vector<vector<vector<double>>> test_x;
	const int M = 5000;
	ifstream test_image("t10k-images-idx3-ubyte", ios_base::binary);
	if( !test_image.is_open() ){
		cerr << "\"t10k-images-idx3-ubyte\" is not found!" << endl;
		return 1;
	}
	ifstream test_label("t10k-labels-idx1-ubyte", ios_base::binary);
	if( !test_label.is_open() ){
		cerr << "\"t10k-labels-idx1-ubyte\" is not found!" << endl;
		return 1;
	}

	test_image.seekg(4*4, ios_base::beg);
	test_label.seekg(4*2, ios_base::beg);
	for( int i = 0; i < M; ++i ){
		unsigned char tmp_lab;
		test_label.read((char*)&tmp_lab, sizeof(unsigned char));
		test_lab.push_back(tmp_lab);

		vector<vector<double>> tmp(1, vector<double>(28*28));
		for( int j = 0; j < 28*28; ++j ){
			unsigned char c;
			test_image.read((char*)&c, sizeof(unsigned char));
			tmp[0][j] = (c/255.0 - ave[0][j]);
		}

		test_x.push_back(tmp);
	}

	// train data into Matrix class for checking error.
	vector<Matrix<double>> X(1, Matrix<double>(28*28, M)), D(1, Matrix<double>(10, M));
	for( int i = 0; i < M; ++i ){
		for( int j = 0; j < 28*28; ++j ){
			X[0](j, i) = test_x[i][0][j];
		}
		D[0](test_lab[i], i) = 1.0;
	}

	// checking error function.
	double prev_time, total_time;
	auto check_error = [&](const Neuralnet& nn, const int iter, const std::vector<Matrix<double>>& x, const std::vector<Matrix<double>>& d ) -> void {
		if( iter%((N/BATCH_SIZE)) != 0 || iter == 0 ) return;

		double tmp_time = MPI_Wtime();

		// calculating answer rate among all train data.
		int train_ans_num = 0;
		auto y = nn.apply(train_x);
		for( int i = 0; i < y.size(); ++i ){
			int idx, lab;
			double max_num = 0.0;
			for( int j = 0; j < 10; ++j ){
				if( max_num < y[i][0][j] ){
					max_num = y[i][0][j];
					idx = j;
				}
			}
			if( idx == train_lab[i] ) ++train_ans_num;
		}

		// calculating answer rate among all test data.
		int test_ans_num = 0;
		auto Y = nn.apply(X);
		for( int i = 0; i < Y[0].n; ++i ){
			int idx, lab;
			double max_num = 0.0;
			for( int j = 0; j < 10; ++j ){
				if( max_num < Y[0](j,i) ){
					max_num = Y[0](j,i);
					idx = j;
				}
				if( D[0](j, i) == 1.0 ) lab = j;
			}
			if( idx == lab ) ++test_ans_num;
		}

		// output answer rate each test data batch.
		if( inner_rank == 0 ){
			for( int i = 0; i < outer_nprocs; ++i ){
				if( i == outer_rank ){
					printf("outer rank : %d\n", outer_rank);
					printf("  Elapsed time : %.3f, Total time : %.3f\n", MPI_Wtime() - prev_time, MPI_Wtime() - total_time);
					printf("  Train answer rate : %.2f%%\n", (double)train_ans_num/y.size()*100.0);
					printf("  Test answer rate  : %.2f%%\n", (double)test_ans_num/X[0].n*100.0);
				}
				MPI_Barrier(outer_world);
			}
			prev_time = MPI_Wtime();
		}
		if( world_rank == 0 ) puts("");
	};

	// set a hyper parameter.
	net.set_EPS(1.0E-3);
	net.set_LAMBDA(0.0);
	net.set_BATCHSIZE(BATCH_SIZE);
	net.set_UPDATEITER(N/BATCH_SIZE*2);
	// learning the neuralnet in 20 EPOCH and output error defined above in each epoch.
	prev_time = total_time = MPI_Wtime();
	net.learning(train_x, d, N/BATCH_SIZE*10, check_error);

	MPI_Finalize();
}
<|endoftext|>