<commit_before>/// \file libport/assert.hh
/// \brief Provide nice assert like macros.

#ifndef LIBPORT_ASSERT_HH
# define LIBPORT_ASSERT_HH

# include <cassert>
# include <cstdlib>

// We have mysterious random aborts on OSX which is compiled with
// NDEBUG.  Temporarily disable NDEBUG to have verbose paborts.
# if defined NDEBUG
#  define LIBPORT_ASSERT_VERBOSE 0
# else
#  define LIBPORT_ASSERT_VERBOSE 1
# endif

# if LIBPORT_ASSERT_VERBOSE
#  include <iostream> // std::cerr
#  include <libport/cstdio> // libport::strerror.
# endif

# include <libport/compiler.hh>

namespace libport
{
  /// A wrapper to std::abort to ensure that it is declared as
  /// noreturn (which is not the case of std::abort with MSVC).
  ATTRIBUTE_NORETURN
  inline
  void abort()
  {
    std::abort();
  }
}

/*---------------------------.
| passert -- Pretty assert.  |
`---------------------------*/

/// \def passert(Subject, Assertion)
/// Same as assert, but on failure, dump \a Subject of std::cerr.
# if ! LIBPORT_ASSERT_VERBOSE
#  define passert(Subject, Assertion)
# else

#  define passert(Subject, Assertion)			\
  ((void) ((Assertion)					\
	   ? 0						\
	   : __passert (__FILE__ ":" <<  __LINE__,	\
			Subject, Assertion)))

#  define __passert(Loc, Subject, Assertion)				\
  (std::cerr								\
     << Loc << ": failed assertion: " << #Assertion << std::endl	\
     << Loc << ": with "						\
     << #Subject << " = " << Subject << std::endl,			\
   libport::abort(),                                                    \
   0)

# endif // LIBPORT_ASSERT_VERBOSE

/*-------------------------.
| pabort -- Pretty abort.  |
`-------------------------*/

/// \def pabort(Msg)
///
/// Same as abort, but when NDEBUG is not set, report the Msg using
/// the operator<< on std::cerr.  Msg may include << itself.  So
/// if Msg is complex, beware of predence issues with << and use parens
/// on the invocation side.

# if ! LIBPORT_ASSERT_VERBOSE
#  define pabort(Msg)       libport::abort()
# else

#  define pabort(Msg)					\
  ((void) (__pabort (__FILE__ ":" << __LINE__, Msg)))

#  define __pabort(Loc, Msg)						\
  (std::cerr << Loc << ": abort: " << Msg << std::endl,			\
   libport::abort())

# endif // LIBPORT_ASSERT_VERBOSE

/*----------------------------------------------.
| errabort -- perror (well, strerror) + abort.  |
`----------------------------------------------*/

/// \def errabort(Msg)
# define errabort(Msg)    \
  pabort(libport::strerror(errno) << ": " << Msg)

/*--------------------------------------------------------.
| assert_exp -- Require a non-null value, and return it.  |
`--------------------------------------------------------*/

# if ! LIBPORT_ASSERT_VERBOSE
#  define assert_exp(Obj)		(Obj)
# else
// Basically, an assert that can be used in an expression.  I meant to
// use "nonnull", but this name is unused by libstdc++, so the #define
// breaks everything.
namespace libport
{
  template <typename T>
  inline
  T
  assert_exp_(T t, const char* file, int line, const char* msg)
  {
    if (!t)
    {
      std::cerr
	<< file << ": " << line << ": failed assertion: " << msg << std::endl;
      libport::abort();
    }
    return t;
  }
}

#  define assert_exp(Obj)		\
  libport::assert_exp_(Obj, __FILE__, __LINE__ , #Obj)
# endif // LIBPORT_ASSERT_VERBOSE

#endif // !LIBPORT_ASSERT_HH
<commit_msg>Make pabort print its message even in NDEBUG mode.<commit_after>/// \file libport/assert.hh
/// \brief Provide nice assert like macros.

#ifndef LIBPORT_ASSERT_HH
# define LIBPORT_ASSERT_HH

# include <cassert>
# include <cstdlib>

// We have mysterious random aborts on OSX which is compiled with
// NDEBUG.  Temporarily disable NDEBUG to have verbose paborts.
# if defined NDEBUG
#  define LIBPORT_ASSERT_VERBOSE 0
# else
#  define LIBPORT_ASSERT_VERBOSE 1
# endif

# include <iostream> // std::cerr
# include <libport/cstdio> // libport::strerror.

# include <libport/compiler.hh>

namespace libport
{
  /// A wrapper to std::abort to ensure that it is declared as
  /// noreturn (which is not the case of std::abort with MSVC).
  ATTRIBUTE_NORETURN
  inline
  void abort()
  {
    std::abort();
  }
}

/*---------------------------.
| passert -- Pretty assert.  |
`---------------------------*/

/// \def passert(Subject, Assertion)
/// Same as assert, but on failure, dump \a Subject of std::cerr.
# if ! LIBPORT_ASSERT_VERBOSE
#  define passert(Subject, Assertion)
# else

#  define passert(Subject, Assertion)			\
  ((void) ((Assertion)					\
	   ? 0						\
	   : __passert (__FILE__ ":" <<  __LINE__,	\
			Subject, Assertion)))

#  define __passert(Loc, Subject, Assertion)				\
  (std::cerr								\
     << Loc << ": failed assertion: " << #Assertion << std::endl	\
     << Loc << ": with "						\
     << #Subject << " = " << Subject << std::endl,			\
   libport::abort(),                                                    \
   0)

# endif // LIBPORT_ASSERT_VERBOSE

/*-------------------------.
| pabort -- Pretty abort.  |
`-------------------------*/

/// \def pabort(Msg)
///
/// Same as abort, but when NDEBUG is not set, report the Msg using
/// the operator<< on std::cerr.  Msg may include << itself.  So
/// if Msg is complex, beware of predence issues with << and use parens
/// on the invocation side.

# define pabort(Msg)					\
  ((void) (__pabort (__FILE__ ":" << __LINE__, Msg)))

# define __pabort(Loc, Msg)						\
  (std::cerr << Loc << ": abort: " << Msg << std::endl,			\
   libport::abort())

/*----------------------------------------------.
| errabort -- perror (well, strerror) + abort.  |
`----------------------------------------------*/

/// \def errabort(Msg)
# define errabort(Msg)    \
  pabort(libport::strerror(errno) << ": " << Msg)

/*--------------------------------------------------------.
| assert_exp -- Require a non-null value, and return it.  |
`--------------------------------------------------------*/

# if ! LIBPORT_ASSERT_VERBOSE
#  define assert_exp(Obj)		(Obj)
# else
// Basically, an assert that can be used in an expression.  I meant to
// use "nonnull", but this name is unused by libstdc++, so the #define
// breaks everything.
namespace libport
{
  template <typename T>
  inline
  T
  assert_exp_(T t, const char* file, int line, const char* msg)
  {
    if (!t)
    {
      std::cerr
	<< file << ": " << line << ": failed assertion: " << msg << std::endl;
      libport::abort();
    }
    return t;
  }
}

#  define assert_exp(Obj)		\
  libport::assert_exp_(Obj, __FILE__, __LINE__ , #Obj)
# endif // LIBPORT_ASSERT_VERBOSE

#endif // !LIBPORT_ASSERT_HH
<|endoftext|>


<commit_before>// This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0

#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
typedef websocketpp::server<websocketpp::config::asio> server;

#include <jsonipc/jsonipc.hh>

#include <bse/bse.hh>
#include <bse/platform.hh>
#include <bse/regex.hh>

#undef B0 // pollution from termios.h

static Bse::ServerH bse_server;
static const bool verbose = false;

// Configure websocket server
struct CustomServerConfig : public websocketpp::config::asio {
  static const size_t connection_read_buffer_size = 16384;
};
using ServerEndpoint = websocketpp::server<CustomServerConfig>;
static ServerEndpoint websocket_server;

static std::string
handle_jsonipc (const std::string &message, const websocketpp::connection_hdl &hdl)
{
  static Jsonipc::IpcDispatcher jd;
  const ptrdiff_t conid = ptrdiff_t (websocket_server.get_con_from_hdl (hdl).get());
  if (verbose)
    Bse::printerr ("%p: REQUEST: %s\n", conid, message);
  const std::string reply = jd.dispatch_message (message);
  if (verbose)
    Bse::printerr ("%p: REPLY:   %s\n", conid, reply);
  return reply;
}

static std::string
user_agent_nick (const std::string &useragent)
{
  using namespace Bse;
  std::string nick;
  if      (Re::search (R"(\bFirefox/)", useragent))
    nick += "Firefox";
  else if (Re::search (R"(\bElectron/)", useragent))
    nick += "Electron";
  else if (Re::search (R"(\bChrome/)", useragent))
    nick += "Chrome";
  else if (Re::search (R"(\bSafari/)", useragent))
    nick += "Safari";
  else
    nick += "Unknown";
  return nick;
}

static bool
ws_validate_connection (websocketpp::connection_hdl hdl)
{
  ServerEndpoint::connection_ptr con = websocket_server.get_con_from_hdl (hdl);
  // using subprotocol as auth string
  const std::vector<std::string> &subprotocols = con->get_requested_subprotocols();
  if (subprotocols.size() == 1)
    {
      if (subprotocols[0] == "auth123")
        {
          con->select_subprotocol (subprotocols[0]);
          return true;
        }
    }
  return false;
}

static void
ws_open_connection (websocketpp::connection_hdl hdl)
{
  ServerEndpoint::connection_ptr con = websocket_server.get_con_from_hdl (hdl);
  // https://github.com/zaphoyd/websocketpp/issues/694#issuecomment-454623641
  const auto &socket = con->get_raw_socket();
  const auto &address = socket.remote_endpoint().address();
  const int rport = socket.remote_endpoint().port();
  const websocketpp::http::parser::request &rq = con->get_request();
  const websocketpp::http::parser::header_list &headermap = rq.get_headers();
  std::string useragent;
  for (auto it : headermap) // request headers
    if (it.first == "User-Agent")
      useragent = it.second;
  std::string nick = user_agent_nick (useragent);
  if (!nick.empty())
    nick = "(" + nick + ")";
  using namespace Bse::AnsiColors;
  auto B1 = color (BOLD);
  auto B0 = color (BOLD_OFF);
  Bse::printout ("%p: %sACCEPT:%s %s:%d/ %s\n", ptrdiff_t (con.get()), B1, B0, address.to_string().c_str(), rport, nick);
  // Bse::printout ("User-Agent: %s\n", useragent);
}

static void
ws_message (websocketpp::connection_hdl con, server::message_ptr msg)
{
  const std::string &message = msg->get_payload();
  // send message to BSE thread and block until its been handled
  Aida::ScopedSemaphore sem;
  auto handle_wsmsg = [&message, &con, &sem] () {
    std::string reply = handle_jsonipc (message, con);
    if (!reply.empty())
      websocket_server.send (con, reply, websocketpp::frame::opcode::text);
    sem.post();
  };
  bse_server.__iface_ptr__()->__execution_context_mt__().enqueue_mt (handle_wsmsg);
  sem.wait();
}

static void
print_usage (bool help)
{
  if (!help)
    {
      Bse::printout ("beast-sound-engine version %s\n", Bse::version());
      return;
    }
  Bse::printout ("Usage: beast-sound-engine [OPTIONS]\n");
  Bse::printout ("  --help     Print command line help\n");
  Bse::printout ("  --version  Print program version\n");
}

int
main (int argc, char *argv[])
{
  Bse::init_async (&argc, argv, argv[0]); // Bse::cstrings_to_vector (NULL)
  bse_server = Bse::init_server_instance();

  // parse arguments
  bool seen_dashdash = false;
  std::vector<std::string> words;
  for (size_t i = 0; i < argc; i++)
    if (!argv[i])
      continue;
    else if (argv[i][0] == '-' && argv[i][1] == '-' && argv[i][2] == 0)
      seen_dashdash = true;
    else if (!seen_dashdash && argv[i][0] == '-')
      {
        const char *arg = argv[i] + 1 + (argv[i][1] == '-');
        const char *eq = strchr (arg, '=');
        const std::string arg_name = !eq ? arg : std::string (arg, eq - arg);
        if (arg_name == "version")
          {
            print_usage (false);
            return 0;
          }
        else if (arg_name == "h" || arg_name == "help")
          {
            print_usage (true);
            return 0;
          }
        else
          {
            Bse::printerr ("%s: invalid argument: %s\n", argv[0], argv[i]);
            print_usage (true);
            return 1;
          }
      }
    else
      words.push_back (argv[i]);

  const int BEAST_AUDIO_ENGINE_PORT = 27239;    // 0x3ea67 % 32768

  // setup websocket and run asio loop
  websocket_server.set_validate_handler (&ws_validate_connection);
  websocket_server.set_open_handler (&ws_open_connection);
  websocket_server.set_message_handler (&ws_message);
  websocket_server.init_asio();
  websocket_server.clear_access_channels (websocketpp::log::alevel::all);
  websocket_server.set_reuse_addr (true);
  namespace IP = boost::asio::ip;
  IP::tcp::endpoint endpoint_local = IP::tcp::endpoint (IP::address::from_string ("127.0.0.1"), BEAST_AUDIO_ENGINE_PORT);
  websocket_server.listen (endpoint_local);
  websocket_server.start_accept();

  using namespace Bse::AnsiColors;
  auto B1 = color (BOLD);
  auto B0 = color (BOLD_OFF);
  Bse::printout ("%sLISTEN:%s ws://localhost:%d/\n", B1, B0, BEAST_AUDIO_ENGINE_PORT);

  websocket_server.run();

  return 0;
}
<commit_msg>BSE: beast-sound-engine: add JS example comment for echo tests<commit_after>// This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0

#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
typedef websocketpp::server<websocketpp::config::asio> server;

#include <jsonipc/jsonipc.hh>

#include <bse/bse.hh>
#include <bse/platform.hh>
#include <bse/regex.hh>

#undef B0 // pollution from termios.h

static Bse::ServerH bse_server;
static const bool verbose = false;

// Configure websocket server
struct CustomServerConfig : public websocketpp::config::asio {
  static const size_t connection_read_buffer_size = 16384;
};
using ServerEndpoint = websocketpp::server<CustomServerConfig>;
static ServerEndpoint websocket_server;

static std::string
handle_jsonipc (const std::string &message, const websocketpp::connection_hdl &hdl)
{
  static Jsonipc::IpcDispatcher jd;
  const ptrdiff_t conid = ptrdiff_t (websocket_server.get_con_from_hdl (hdl).get());
  if (verbose)
    Bse::printerr ("%p: REQUEST: %s\n", conid, message);
  const std::string reply = jd.dispatch_message (message);
  if (verbose)
    Bse::printerr ("%p: REPLY:   %s\n", conid, reply);
  return reply;
}

static std::string
user_agent_nick (const std::string &useragent)
{
  using namespace Bse;
  std::string nick;
  if      (Re::search (R"(\bFirefox/)", useragent))
    nick += "Firefox";
  else if (Re::search (R"(\bElectron/)", useragent))
    nick += "Electron";
  else if (Re::search (R"(\bChrome/)", useragent))
    nick += "Chrome";
  else if (Re::search (R"(\bSafari/)", useragent))
    nick += "Safari";
  else
    nick += "Unknown";
  return nick;
}

static bool
ws_validate_connection (websocketpp::connection_hdl hdl)
{
  ServerEndpoint::connection_ptr con = websocket_server.get_con_from_hdl (hdl);
  // using subprotocol as auth string
  const std::vector<std::string> &subprotocols = con->get_requested_subprotocols();
  if (subprotocols.size() == 1)
    {
      if (subprotocols[0] == "auth123")
        {
          con->select_subprotocol (subprotocols[0]);
          return true;
        }
    }
  return false;
}

static void
ws_open_connection (websocketpp::connection_hdl hdl)
{
  ServerEndpoint::connection_ptr con = websocket_server.get_con_from_hdl (hdl);
  // https://github.com/zaphoyd/websocketpp/issues/694#issuecomment-454623641
  const auto &socket = con->get_raw_socket();
  const auto &address = socket.remote_endpoint().address();
  const int rport = socket.remote_endpoint().port();
  const websocketpp::http::parser::request &rq = con->get_request();
  const websocketpp::http::parser::header_list &headermap = rq.get_headers();
  std::string useragent;
  for (auto it : headermap) // request headers
    if (it.first == "User-Agent")
      useragent = it.second;
  std::string nick = user_agent_nick (useragent);
  if (!nick.empty())
    nick = "(" + nick + ")";
  using namespace Bse::AnsiColors;
  auto B1 = color (BOLD);
  auto B0 = color (BOLD_OFF);
  Bse::printout ("%p: %sACCEPT:%s %s:%d/ %s\n", ptrdiff_t (con.get()), B1, B0, address.to_string().c_str(), rport, nick);
  // Bse::printout ("User-Agent: %s\n", useragent);
}

static void
ws_message (websocketpp::connection_hdl con, server::message_ptr msg)
{
  const std::string &message = msg->get_payload();
  // send message to BSE thread and block until its been handled
  Aida::ScopedSemaphore sem;
  auto handle_wsmsg = [&message, &con, &sem] () {
    std::string reply = handle_jsonipc (message, con);
    if (!reply.empty())
      websocket_server.send (con, reply, websocketpp::frame::opcode::text);
    sem.post();
  };
  bse_server.__iface_ptr__()->__execution_context_mt__().enqueue_mt (handle_wsmsg);
  sem.wait();
}

static void
print_usage (bool help)
{
  if (!help)
    {
      Bse::printout ("beast-sound-engine version %s\n", Bse::version());
      return;
    }
  Bse::printout ("Usage: beast-sound-engine [OPTIONS]\n");
  Bse::printout ("  --help     Print command line help\n");
  Bse::printout ("  --version  Print program version\n");
}

int
main (int argc, char *argv[])
{
  Bse::init_async (&argc, argv, argv[0]); // Bse::cstrings_to_vector (NULL)
  bse_server = Bse::init_server_instance();

  // parse arguments
  bool seen_dashdash = false;
  std::vector<std::string> words;
  for (size_t i = 0; i < argc; i++)
    if (!argv[i])
      continue;
    else if (argv[i][0] == '-' && argv[i][1] == '-' && argv[i][2] == 0)
      seen_dashdash = true;
    else if (!seen_dashdash && argv[i][0] == '-')
      {
        const char *arg = argv[i] + 1 + (argv[i][1] == '-');
        const char *eq = strchr (arg, '=');
        const std::string arg_name = !eq ? arg : std::string (arg, eq - arg);
        if (arg_name == "version")
          {
            print_usage (false);
            return 0;
          }
        else if (arg_name == "h" || arg_name == "help")
          {
            print_usage (true);
            return 0;
          }
        else
          {
            Bse::printerr ("%s: invalid argument: %s\n", argv[0], argv[i]);
            print_usage (true);
            return 1;
          }
      }
    else
      words.push_back (argv[i]);

  const int BEAST_AUDIO_ENGINE_PORT = 27239;    // 0x3ea67 % 32768

  // setup websocket and run asio loop
  websocket_server.set_validate_handler (&ws_validate_connection);
  websocket_server.set_open_handler (&ws_open_connection);
  websocket_server.set_message_handler (&ws_message);
  websocket_server.init_asio();
  websocket_server.clear_access_channels (websocketpp::log::alevel::all);
  websocket_server.set_reuse_addr (true);
  namespace IP = boost::asio::ip;
  IP::tcp::endpoint endpoint_local = IP::tcp::endpoint (IP::address::from_string ("127.0.0.1"), BEAST_AUDIO_ENGINE_PORT);
  websocket_server.listen (endpoint_local);
  websocket_server.start_accept();

  using namespace Bse::AnsiColors;
  auto B1 = color (BOLD);
  auto B0 = color (BOLD_OFF);
  Bse::printout ("%sLISTEN:%s ws://localhost:%d/\n", B1, B0, BEAST_AUDIO_ENGINE_PORT);

  websocket_server.run();

  return 0;
}

/* Dumb echo test:
   var WebSocket = require ('ws'), c = 0; ws = new WebSocket("ws://localhost:27239/", 'auth123'); ws.onopen=e=>ws.send("Hello!");
   ws.onmessage=e=>{if(++c % 1000 == 0) console.log(e.data, c); ws.send("YO"); }; setTimeout(e=>{ws.close();console.log(c/10);},10000);
 */
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id: ctrans.hpp 39 2005-04-10 20:39:53Z pavlenko $

#ifndef CTRANS_HPP
#define CTRANS_HPP

#include <algorithm>

#include <mapnik/box2d.hpp>
#include <mapnik/vertex.hpp>
#include <mapnik/coord_array.hpp>
#include <mapnik/proj_transform.hpp>

namespace mapnik {
typedef coord_array<coord2d> CoordinateArray;

template <typename Transform,typename Geometry>
struct MAPNIK_DECL coord_transform
{
    coord_transform(Transform const& t, Geometry& geom)
        : t_(t), geom_(geom) {}

    unsigned  vertex(double *x , double *y) const
    {
        unsigned command = geom_.vertex(x,y);
        t_.forward(x,y);
        return command;
    }

    void rewind (unsigned pos)
    {
        geom_.rewind(pos);
    }

private:
    Transform const& t_;
    Geometry& geom_;
};

template <typename Transform,typename Geometry>
struct MAPNIK_DECL coord_transform2
{
    typedef std::size_t size_type;
    typedef typename Geometry::value_type value_type;

    coord_transform2(Transform const& t,
                     Geometry const& geom,
                     proj_transform const& prj_trans)
        : t_(t),
        geom_(geom),
        prj_trans_(prj_trans)  {}

    unsigned vertex(double * x , double  * y) const
    {
        unsigned command(SEG_MOVETO);
        bool ok = false;
        bool skipped_points = false;
        while (!ok)
        {
            command = geom_.vertex(x,y);
            double z=0;
            ok = prj_trans_.backward(*x,*y,z);
            if (!ok) {
                skipped_points = true;
            }
            ok = ok || (command == SEG_END);
        }
        if (skipped_points && (command == SEG_LINETO))
        {
            command = SEG_MOVETO;
        }
        t_.forward(x,y);
        return command;
    }

    /*unsigned  vertex(double * x , double  * y) const
    {
        unsigned command = geom_.vertex(x,y);
        double z=0;
        prj_trans_.backward(*x,*y,z);
        t_.forward(x,y);
        return command;
    }*/

    void rewind (unsigned pos)
    {
        geom_.rewind(pos);
    }

    Geometry const& geom() const
    {
        return geom_;
    }

private:
    Transform const& t_;
    Geometry const& geom_;
    proj_transform const& prj_trans_;
};

template <typename Transform,typename Geometry>
struct MAPNIK_DECL coord_transform3
{
    coord_transform3(Transform const& t,
                     Geometry const& geom,
                     proj_transform const& prj_trans,
                     int dx, int dy)
        : t_(t),
        geom_(geom),
        prj_trans_(prj_trans),
        dx_(dx), dy_(dy) {}

    unsigned  vertex(double * x , double  * y) const
    {
        unsigned command = geom_.vertex(x,y);
        double z=0;
        prj_trans_.backward(*x,*y,z);
        t_.forward(x,y);
        *x+=dx_;
        *y+=dy_;
        return command;
    }

    void rewind (unsigned pos)
    {
        geom_.rewind(pos);
    }

private:
    Transform const& t_;
    Geometry const& geom_;
    proj_transform const& prj_trans_;
    int dx_;
    int dy_;
};

class CoordTransform
{
private:
    int width_;
    int height_;
    double sx_;
    double sy_;
    box2d<double> extent_;
    double offset_x_;
    double offset_y_;
public:
    CoordTransform(int width,int height,const box2d<double>& extent,
                   double offset_x = 0, double offset_y = 0)
        :width_(width),height_(height),extent_(extent),offset_x_(offset_x),offset_y_(offset_y)
    {
        sx_ = (double(width_))/extent_.width();
        sy_ = (double(height_))/extent_.height();
    }

    inline int width() const
    {
        return width_;
    }

    inline int height() const
    {
        return height_;
    }

    inline double scale_x() const
    {
        return sx_;
    }

    inline double scale_y() const
    {
        return sy_;
    }

    inline void forward(double * x, double * y) const
    {
        *x = (*x - extent_.minx()) * sx_ - offset_x_;
        *y = (extent_.maxy() - *y) * sy_ - offset_y_;
    }

    inline void backward(double * x, double * y) const
    {
        *x = extent_.minx() + (*x + offset_x_)/sx_;
        *y = extent_.maxy() - (*y + offset_y_)/sy_;
    }

    inline coord2d& forward(coord2d& c) const
    {
        forward(&c.x,&c.y);
        return c;
    }

    inline coord2d& backward(coord2d& c) const
    {
        backward(&c.x,&c.y);
        return c;
    }

    inline box2d<double> forward(const box2d<double>& e,proj_transform const& prj_trans) const
    {
        double x0 = e.minx();
        double y0 = e.miny();
        double x1 = e.maxx();
        double y1 = e.maxy();
        double z = 0.0;
        prj_trans.backward(x0,y0,z);
        forward(&x0,&y0);
        prj_trans.backward(x1,y1,z);
        forward(&x1,&y1);
        return box2d<double>(x0,y0,x1,y1);
    }

    inline box2d<double> forward(const box2d<double>& e) const
    {
        double x0 = e.minx();
        double y0 = e.miny();
        double x1 = e.maxx();
        double y1 = e.maxy();
        forward(&x0,&y0);
        forward(&x1,&y1);
        return box2d<double>(x0,y0,x1,y1);
    }

    inline box2d<double> backward(const box2d<double>& e,proj_transform const& prj_trans) const
    {
        double x0 = e.minx();
        double y0 = e.miny();
        double x1 = e.maxx();
        double y1 = e.maxy();
        double z = 0.0;
        backward(&x0,&y0);
        prj_trans.forward(x0,y0,z);
        backward(&x1,&y1);
        prj_trans.forward(x1,y1,z);
        return box2d<double>(x0,y0,x1,y1);
    }

    inline box2d<double> backward(const box2d<double>& e) const
    {
        double x0 = e.minx();
        double y0 = e.miny();
        double x1 = e.maxx();
        double y1 = e.maxy();
        backward(&x0,&y0);
        backward(&x1,&y1);
        return box2d<double>(x0,y0,x1,y1);
    }

    inline CoordinateArray& forward(CoordinateArray& coords) const
    {
        for (unsigned i=0;i<coords.size();++i)
        {
            forward(coords[i]);
        }
        return coords;
    }

    inline CoordinateArray& backward(CoordinateArray& coords) const
    {
        for (unsigned i=0;i<coords.size();++i)
        {
            backward(coords[i]);
        }
        return coords;
    }
    inline box2d<double> const& extent() const
    {
        return extent_;
    }
};
}

#endif //CTRANS_HPP
<commit_msg>code cleanup<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
//$Id$

#ifndef CTRANS_HPP
#define CTRANS_HPP

#include <algorithm>

#include <mapnik/box2d.hpp>
#include <mapnik/vertex.hpp>
#include <mapnik/coord_array.hpp>
#include <mapnik/proj_transform.hpp>

namespace mapnik
{

typedef coord_array<coord2d> CoordinateArray;

template <typename Transform, typename Geometry>
struct MAPNIK_DECL coord_transform
{
    coord_transform(Transform const& t, Geometry& geom)
        : t_(t), geom_(geom) {}

    unsigned vertex(double *x, double *y) const
    {
        unsigned command = geom_.vertex(x, y);
        t_.forward(x, y);
        return command;
    }

    void rewind(unsigned pos)
    {
        geom_.rewind(pos);
    }

private:
    Transform const& t_;
    Geometry& geom_;
};

template <typename Transform, typename Geometry>
struct MAPNIK_DECL coord_transform2
{
    typedef std::size_t size_type;
    typedef typename Geometry::value_type value_type;

    coord_transform2(Transform const& t,
                     Geometry const& geom,
                     proj_transform const& prj_trans)
        : t_(t),
        geom_(geom),
        prj_trans_(prj_trans)  {}

    unsigned vertex(double *x, double *y) const
    {
        unsigned command = SEG_MOVETO;
        bool ok = false;
        bool skipped_points = false;
        double z = 0;
        while (!ok && command != SEG_END)
        {
            command = geom_.vertex(x, y);
            ok = prj_trans_.backward(*x, *y, z);
            if (!ok) {
                skipped_points = true;
            }
        }
        if (skipped_points && (command == SEG_LINETO))
        {
            command = SEG_MOVETO;
        }
        t_.forward(x, y);
        return command;
    }

    void rewind(unsigned pos)
    {
        geom_.rewind(pos);
    }

    Geometry const& geom() const
    {
        return geom_;
    }

private:
    Transform const& t_;
    Geometry const& geom_;
    proj_transform const& prj_trans_;
};

template <typename Transform, typename Geometry>
struct MAPNIK_DECL coord_transform3
{
    coord_transform3(Transform const& t,
                     Geometry const& geom,
                     proj_transform const& prj_trans,
                     int dx, int dy)
        : t_(t),
        geom_(geom),
        prj_trans_(prj_trans),
        dx_(dx), dy_(dy) {}

    unsigned vertex(double *x, double *y) const
    {
        unsigned command = geom_.vertex(x, y);
        double z = 0;
        prj_trans_.backward(*x, *y, z);
        t_.forward(x, y);
        *x += dx_;
        *y += dy_;
        return command;
    }

    void rewind(unsigned pos)
    {
        geom_.rewind(pos);
    }

private:
    Transform const& t_;
    Geometry const& geom_;
    proj_transform const& prj_trans_;
    int dx_;
    int dy_;
};

class CoordTransform
{
private:
    int width_;
    int height_;
    double sx_;
    double sy_;
    box2d<double> extent_;
    double offset_x_;
    double offset_y_;

public:
    CoordTransform(int width, int height, const box2d<double>& extent,
                   double offset_x = 0, double offset_y = 0)
        : width_(width), height_(height), extent_(extent),
        offset_x_(offset_x), offset_y_(offset_y)
    {
        sx_ = double(width_) / extent_.width();
        sy_ = double(height_) / extent_.height();
    }

    inline int width() const
    {
        return width_;
    }

    inline int height() const
    {
        return height_;
    }

    inline double scale_x() const
    {
        return sx_;
    }

    inline double scale_y() const
    {
        return sy_;
    }

    inline void forward(double *x, double *y) const
    {
        *x = (*x - extent_.minx()) * sx_ - offset_x_;
        *y = (extent_.maxy() - *y) * sy_ - offset_y_;
    }

    inline void backward(double *x, double *y) const
    {
        *x = extent_.minx() + (*x + offset_x_) / sx_;
        *y = extent_.maxy() - (*y + offset_y_) / sy_;
    }

    inline coord2d& forward(coord2d& c) const
    {
        forward(&c.x, &c.y);
        return c;
    }

    inline coord2d& backward(coord2d& c) const
    {
        backward(&c.x, &c.y);
        return c;
    }

    inline box2d<double> forward(const box2d<double>& e,
                                 proj_transform const& prj_trans) const
    {
        double x0 = e.minx();
        double y0 = e.miny();
        double x1 = e.maxx();
        double y1 = e.maxy();
        double z = 0.0;
        prj_trans.backward(x0, y0, z);
        forward(&x0, &y0);
        prj_trans.backward(x1, y1, z);
        forward(&x1, &y1);
        return box2d<double>(x0, y0, x1, y1);
    }

    inline box2d<double> forward(const box2d<double>& e) const
    {
        double x0 = e.minx();
        double y0 = e.miny();
        double x1 = e.maxx();
        double y1 = e.maxy();
        forward(&x0, &y0);
        forward(&x1, &y1);
        return box2d<double>(x0, y0, x1, y1);
    }

    inline box2d<double> backward(const box2d<double>& e,
                                  proj_transform const& prj_trans) const
    {
        double x0 = e.minx();
        double y0 = e.miny();
        double x1 = e.maxx();
        double y1 = e.maxy();
        double z = 0.0;
        backward(&x0, &y0);
        prj_trans.forward(x0, y0, z);
        backward(&x1, &y1);
        prj_trans.forward(x1, y1, z);
        return box2d<double>(x0, y0, x1, y1);
    }

    inline box2d<double> backward(const box2d<double>& e) const
    {
        double x0 = e.minx();
        double y0 = e.miny();
        double x1 = e.maxx();
        double y1 = e.maxy();
        backward(&x0, &y0);
        backward(&x1, &y1);
        return box2d<double>(x0, y0, x1, y1);
    }

    inline CoordinateArray& forward(CoordinateArray& coords) const
    {
        for (unsigned i = 0; i < coords.size(); ++i)
        {
            forward(coords[i]);
        }
        return coords;
    }

    inline CoordinateArray& backward(CoordinateArray& coords) const
    {
        for (unsigned i = 0; i < coords.size(); ++i)
        {
            backward(coords[i]);
        }
        return coords;
    }

    inline box2d<double> const& extent() const
    {
        return extent_;
    }
};
}

#endif //CTRANS_HPP
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_MARKER_HPP
#define MAPNIK_MARKER_HPP

// mapnik
#include <mapnik/image.hpp>
#include <mapnik/svg/svg_storage.hpp>
#include <mapnik/svg/svg_path_adapter.hpp>
#include <mapnik/util/variant.hpp>

#pragma GCC diagnostic push
#include <mapnik/warning_ignore_agg.hpp>
#include "agg_array.h"
#pragma GCC diagnostic pop

// stl
#include <deque>
#include <memory>

namespace mapnik
{

struct image_any;
namespace svg { struct path_attributes; }

using svg::svg_path_adapter;

using svg_attribute_type = std::deque<svg::path_attributes>;
using svg_storage_type = svg::svg_storage<svg::svg_path_storage, svg_attribute_type>;
using svg_path_ptr = std::shared_ptr<svg_storage_type>;
using image_ptr = std::shared_ptr<image_any>;

struct marker_rgba8
{
public:
    marker_rgba8()
        : bitmap_data_(4,4,true,true)
    {
        // create default OGC 4x4 black pixel
        bitmap_data_.set(0xff000000);
    }

    explicit marker_rgba8(image_rgba8 const& data)
        : bitmap_data_(data) {}

    explicit marker_rgba8(image_rgba8 && data) noexcept
        : bitmap_data_(std::move(data)) {}

    box2d<double> bounding_box() const
    {
        std::size_t _width = bitmap_data_.width();
        std::size_t _height = bitmap_data_.height();
        return box2d<double>(static_cast<double>(0), static_cast<double>(0), static_cast<double>(_width), static_cast<double>(_height));
    }

    inline double width() const
    {
        return static_cast<double>(bitmap_data_.width());
    }

    inline double height() const
    {
        return static_cast<double>(bitmap_data_.height());
    }

    image_rgba8 const& get_data() const
    {
        return bitmap_data_;
    }

private:
    image_rgba8 bitmap_data_;
};

struct marker_svg
{
public:
    marker_svg() = default;

    explicit marker_svg(mapnik::svg_path_ptr data) noexcept
        : vector_data_(data) {}

    inline box2d<double> bounding_box() const
    {
        return vector_data_->bounding_box();
    }

    inline double width() const
    {
        return vector_data_->bounding_box().width();
    }
    inline double height() const
    {
        return vector_data_->bounding_box().height();
    }

    inline mapnik::svg_path_ptr get_data() const
    {
        return vector_data_;
    }

    inline std::tuple<double,double> dimensions() const
    {
        return std::make_tuple(vector_data_->width(), vector_data_->height());
    }
private:
    mapnik::svg_path_ptr vector_data_;

};

struct marker_null
{
public:
    inline box2d<double> bounding_box() const
    {
        return box2d<double>();
    }
    inline double width() const
    {
        return 0;
    }
    inline double height() const
    {
        return 0;
    }
};

using marker_base = util::variant<marker_null,
                                  marker_rgba8,
                                  marker_svg>;
namespace detail {

struct get_marker_bbox_visitor
{
    template <typename T>
    box2d<double> operator()(T & data) const
    {
        return data.bounding_box();
    }
};

struct get_marker_width_visitor
{
    template <typename T>
    double operator()(T const& data) const
    {
        return data.width();
    }
};

struct get_marker_height_visitor
{
    template <typename T>
    double operator()(T const& data) const
    {
        return data.height();
    }
};

} // end detail ns

struct marker : marker_base
{
    marker() = default;

    template <typename T>
    marker(T && _data)
        noexcept(std::is_nothrow_constructible<marker_base, T && >::value)
        : marker_base(std::forward<T>(_data)) {}

    double width() const
    {
        return util::apply_visitor(detail::get_marker_width_visitor(),*this);
    }

    double height() const
    {
        return util::apply_visitor(detail::get_marker_height_visitor(),*this);
    }

    box2d<double> bounding_box() const
    {
        return util::apply_visitor(detail::get_marker_bbox_visitor(),*this);
    }
};

} // end mapnik ns

#endif // MAPNIK_MARKER_HPP
<commit_msg>libc++ implementation of std::deque<T> needs T to be complete<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_MARKER_HPP
#define MAPNIK_MARKER_HPP

// mapnik
#include <mapnik/image.hpp>
#include <mapnik/svg/svg_storage.hpp>
#include <mapnik/svg/svg_path_adapter.hpp>
#include <mapnik/svg/svg_path_attributes.hpp>
#include <mapnik/util/variant.hpp>

// stl
#include <deque>
#include <memory>

namespace mapnik
{

struct image_any;

using svg::svg_path_adapter;
using svg_attribute_type = std::deque<svg::path_attributes>;
using svg_storage_type = svg::svg_storage<svg::svg_path_storage, svg_attribute_type>;
using svg_path_ptr = std::shared_ptr<svg_storage_type>;
using image_ptr = std::shared_ptr<image_any>;

struct marker_rgba8
{
public:
    marker_rgba8()
        : bitmap_data_(4,4,true,true)
    {
        // create default OGC 4x4 black pixel
        bitmap_data_.set(0xff000000);
    }

    explicit marker_rgba8(image_rgba8 const& data)
        : bitmap_data_(data) {}

    explicit marker_rgba8(image_rgba8 && data) noexcept
        : bitmap_data_(std::move(data)) {}

    box2d<double> bounding_box() const
    {
        std::size_t _width = bitmap_data_.width();
        std::size_t _height = bitmap_data_.height();
        return box2d<double>(static_cast<double>(0), static_cast<double>(0), static_cast<double>(_width), static_cast<double>(_height));
    }

    inline double width() const
    {
        return static_cast<double>(bitmap_data_.width());
    }

    inline double height() const
    {
        return static_cast<double>(bitmap_data_.height());
    }

    image_rgba8 const& get_data() const
    {
        return bitmap_data_;
    }

private:
    image_rgba8 bitmap_data_;
};

struct marker_svg
{
public:
    marker_svg() = default;

    explicit marker_svg(mapnik::svg_path_ptr data) noexcept
        : vector_data_(data) {}

    inline box2d<double> bounding_box() const
    {
        return vector_data_->bounding_box();
    }

    inline double width() const
    {
        return vector_data_->bounding_box().width();
    }
    inline double height() const
    {
        return vector_data_->bounding_box().height();
    }

    inline mapnik::svg_path_ptr get_data() const
    {
        return vector_data_;
    }

    inline std::tuple<double,double> dimensions() const
    {
        return std::make_tuple(vector_data_->width(), vector_data_->height());
    }
private:
    mapnik::svg_path_ptr vector_data_;

};

struct marker_null
{
public:
    inline box2d<double> bounding_box() const
    {
        return box2d<double>();
    }
    inline double width() const
    {
        return 0;
    }
    inline double height() const
    {
        return 0;
    }
};

using marker_base = util::variant<marker_null,
                                  marker_rgba8,
                                  marker_svg>;
namespace detail {

struct get_marker_bbox_visitor
{
    template <typename T>
    box2d<double> operator()(T & data) const
    {
        return data.bounding_box();
    }
};

struct get_marker_width_visitor
{
    template <typename T>
    double operator()(T const& data) const
    {
        return data.width();
    }
};

struct get_marker_height_visitor
{
    template <typename T>
    double operator()(T const& data) const
    {
        return data.height();
    }
};

} // end detail ns

struct marker : marker_base
{
    marker() = default;

    template <typename T>
    marker(T && _data)
        noexcept(std::is_nothrow_constructible<marker_base, T && >::value)
        : marker_base(std::forward<T>(_data)) {}

    double width() const
    {
        return util::apply_visitor(detail::get_marker_width_visitor(),*this);
    }

    double height() const
    {
        return util::apply_visitor(detail::get_marker_height_visitor(),*this);
    }

    box2d<double> bounding_box() const
    {
        return util::apply_visitor(detail::get_marker_bbox_visitor(),*this);
    }
};

} // end mapnik ns

#endif // MAPNIK_MARKER_HPP
<|endoftext|>


<commit_before>// Copyright 2018 Google LLC
//
// 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 "google/cloud/log.h"
#include "google/cloud/internal/getenv.h"
#include <array>
#include <cstdint>
#include <ctime>
#include <iomanip>

namespace google {
namespace cloud {
inline namespace GOOGLE_CLOUD_CPP_NS {

static_assert(sizeof(Severity) <= sizeof(int),
              "Expected Severity to fit in an integer");

static_assert(static_cast<int>(Severity::GCP_LS_LOWEST) <
                  static_cast<int>(Severity::GCP_LS_HIGHEST),
              "Expect LOWEST severity to be smaller than HIGHEST severity");

namespace {
struct Timestamp {
  explicit Timestamp(std::chrono::system_clock::time_point const& tp) {
    auto const tt = std::chrono::system_clock::to_time_t(tp);
#if defined(_WIN32)
    gmtime_s(&tm, &tt);
#else
    gmtime_r(&tt, &tm);
#endif
    auto const ss = tp - std::chrono::system_clock::from_time_t(tt);
    nanos = static_cast<std::int32_t>(
        std::chrono::duration_cast<std::chrono::nanoseconds>(ss).count());
  }
  std::tm tm;
  std::int32_t nanos;
};

std::ostream& operator<<(std::ostream& os, Timestamp const& ts) {
  auto const prev = os.fill(' ');
  auto constexpr kTmYearOffset = 1900;
  os << std::setw(4) << ts.tm.tm_year + kTmYearOffset;
  os.fill('0');
  os << '-' << std::setw(2) << ts.tm.tm_mon + 1;
  os << '-' << std::setw(2) << ts.tm.tm_mday;
  os << 'T' << std::setw(2) << ts.tm.tm_hour;
  os << ':' << std::setw(2) << ts.tm.tm_min;
  os << ':' << std::setw(2) << ts.tm.tm_sec;
  // NOLINTNEXTLINE(readability-magic-numbers)
  os << '.' << std::setw(9) << ts.nanos << 'Z';
  os.fill(prev);
  return os;
}

auto constexpr kSeverityCount = static_cast<int>(Severity::GCP_LS_HIGHEST) + 1;

// Double braces needed to workaround a clang-3.8 bug.
std::array<char const*, kSeverityCount> constexpr kSeverityNames{{
    "TRACE",
    "DEBUG",
    "INFO",
    "NOTICE",
    "WARNING",
    "ERROR",
    "CRITICAL",
    "ALERT",
    "FATAL",
}};
}  // namespace

std::ostream& operator<<(std::ostream& os, Severity x) {
  auto index = static_cast<int>(x);
  return os << kSeverityNames[index];
}

std::ostream& operator<<(std::ostream& os, LogRecord const& rhs) {
  return os << Timestamp{rhs.timestamp} << " [" << rhs.severity << "] "
            << rhs.message << " (" << rhs.filename << ':' << rhs.lineno << ')';
}

LogSink::LogSink()
    : empty_(true),
      minimum_severity_(static_cast<int>(Severity::GCP_LS_LOWEST_ENABLED)),
      next_id_(0),
      clog_backend_id_(0) {}

LogSink& LogSink::Instance() {
  static auto* const kInstance = [] {
    auto* p = new LogSink;
    if (internal::GetEnv("GOOGLE_CLOUD_CPP_ENABLE_CLOG").has_value()) {
      p->EnableStdClogImpl();
    }
    return p;
  }();
  return *kInstance;
}

// NOLINTNEXTLINE(google-runtime-int)
long LogSink::AddBackend(std::shared_ptr<LogBackend> backend) {
  std::unique_lock<std::mutex> lk(mu_);
  return AddBackendImpl(std::move(backend));
}

// NOLINTNEXTLINE(google-runtime-int)
void LogSink::RemoveBackend(long id) {
  std::unique_lock<std::mutex> lk(mu_);
  RemoveBackendImpl(id);
}

void LogSink::ClearBackends() {
  std::unique_lock<std::mutex> lk(mu_);
  backends_.clear();
  clog_backend_id_ = 0;
  empty_.store(backends_.empty());
}

std::size_t LogSink::BackendCount() const {
  std::unique_lock<std::mutex> lk(mu_);
  return backends_.size();
}

void LogSink::Log(LogRecord log_record) {
  // Make a copy of the backends because calling user-defined functions while
  // holding a lock is a bad idea: the application may change the backends while
  // we are holding this lock, and soon deadlock occurs.
  auto copy = [this]() {
    std::unique_lock<std::mutex> lk(mu_);
    return backends_;
  }();
  if (copy.empty()) {
    return;
  }
  // In general, we just give each backend a const-reference and the backends
  // must make a copy if needed.  But if there is only one backend we can give
  // the backend an opportunity to optimize things by transferring ownership of
  // the LogRecord to it.
  if (copy.size() == 1) {
    copy.begin()->second->ProcessWithOwnership(std::move(log_record));
    return;
  }
  for (auto& kv : copy) {
    kv.second->Process(log_record);
  }
}

namespace {
class StdClogBackend : public LogBackend {
 public:
  StdClogBackend() = default;

  void Process(LogRecord const& lr) override {
    std::clog << lr << "\n";
    if (lr.severity >= Severity::GCP_LS_WARNING) {
      std::clog << std::flush;
    }
  }
  void ProcessWithOwnership(LogRecord lr) override { Process(lr); }
};
}  // namespace

void LogSink::EnableStdClogImpl() {
  std::unique_lock<std::mutex> lk(mu_);
  if (clog_backend_id_ != 0) {
    return;
  }
  clog_backend_id_ = AddBackendImpl(std::make_shared<StdClogBackend>());
}

void LogSink::DisableStdClogImpl() {
  std::unique_lock<std::mutex> lk(mu_);
  if (clog_backend_id_ == 0) {
    return;
  }
  RemoveBackendImpl(clog_backend_id_);
  clog_backend_id_ = 0;
}

// NOLINTNEXTLINE(google-runtime-int)
long LogSink::AddBackendImpl(std::shared_ptr<LogBackend> backend) {
  auto const id = ++next_id_;
  backends_.emplace(id, std::move(backend));
  empty_.store(backends_.empty());
  return id;
}

// NOLINTNEXTLINE(google-runtime-int)
void LogSink::RemoveBackendImpl(long id) {
  auto it = backends_.find(id);
  if (backends_.end() == it) {
    return;
  }
  backends_.erase(it);
  empty_.store(backends_.empty());
}

}  // namespace GOOGLE_CLOUD_CPP_NS
}  // namespace cloud
}  // namespace google
<commit_msg>refactor: use absl::Time for the google/cloud/log.h timestamp (#4690)<commit_after>// Copyright 2018 Google LLC
//
// 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 "google/cloud/log.h"
#include "google/cloud/internal/getenv.h"
#include "absl/time/time.h"
#include <array>

namespace google {
namespace cloud {
inline namespace GOOGLE_CLOUD_CPP_NS {

static_assert(sizeof(Severity) <= sizeof(int),
              "Expected Severity to fit in an integer");

static_assert(static_cast<int>(Severity::GCP_LS_LOWEST) <
                  static_cast<int>(Severity::GCP_LS_HIGHEST),
              "Expect LOWEST severity to be smaller than HIGHEST severity");

namespace {
struct Timestamp {
  explicit Timestamp(std::chrono::system_clock::time_point const& tp)
      : t(absl::FromChrono(tp)) {}
  absl::Time t;
};

std::ostream& operator<<(std::ostream& os, Timestamp const& ts) {
  auto constexpr kFormat = "%E4Y-%m-%dT%H:%M:%E9SZ";
  return os << absl::FormatTime(kFormat, ts.t, absl::UTCTimeZone());
}

auto constexpr kSeverityCount = static_cast<int>(Severity::GCP_LS_HIGHEST) + 1;

// Double braces needed to workaround a clang-3.8 bug.
std::array<char const*, kSeverityCount> constexpr kSeverityNames{{
    "TRACE",
    "DEBUG",
    "INFO",
    "NOTICE",
    "WARNING",
    "ERROR",
    "CRITICAL",
    "ALERT",
    "FATAL",
}};
}  // namespace

std::ostream& operator<<(std::ostream& os, Severity x) {
  auto index = static_cast<int>(x);
  return os << kSeverityNames[index];
}

std::ostream& operator<<(std::ostream& os, LogRecord const& rhs) {
  return os << Timestamp{rhs.timestamp} << " [" << rhs.severity << "] "
            << rhs.message << " (" << rhs.filename << ':' << rhs.lineno << ')';
}

LogSink::LogSink()
    : empty_(true),
      minimum_severity_(static_cast<int>(Severity::GCP_LS_LOWEST_ENABLED)),
      next_id_(0),
      clog_backend_id_(0) {}

LogSink& LogSink::Instance() {
  static auto* const kInstance = [] {
    auto* p = new LogSink;
    if (internal::GetEnv("GOOGLE_CLOUD_CPP_ENABLE_CLOG").has_value()) {
      p->EnableStdClogImpl();
    }
    return p;
  }();
  return *kInstance;
}

// NOLINTNEXTLINE(google-runtime-int)
long LogSink::AddBackend(std::shared_ptr<LogBackend> backend) {
  std::unique_lock<std::mutex> lk(mu_);
  return AddBackendImpl(std::move(backend));
}

// NOLINTNEXTLINE(google-runtime-int)
void LogSink::RemoveBackend(long id) {
  std::unique_lock<std::mutex> lk(mu_);
  RemoveBackendImpl(id);
}

void LogSink::ClearBackends() {
  std::unique_lock<std::mutex> lk(mu_);
  backends_.clear();
  clog_backend_id_ = 0;
  empty_.store(backends_.empty());
}

std::size_t LogSink::BackendCount() const {
  std::unique_lock<std::mutex> lk(mu_);
  return backends_.size();
}

void LogSink::Log(LogRecord log_record) {
  // Make a copy of the backends because calling user-defined functions while
  // holding a lock is a bad idea: the application may change the backends while
  // we are holding this lock, and soon deadlock occurs.
  auto copy = [this]() {
    std::unique_lock<std::mutex> lk(mu_);
    return backends_;
  }();
  if (copy.empty()) {
    return;
  }
  // In general, we just give each backend a const-reference and the backends
  // must make a copy if needed.  But if there is only one backend we can give
  // the backend an opportunity to optimize things by transferring ownership of
  // the LogRecord to it.
  if (copy.size() == 1) {
    copy.begin()->second->ProcessWithOwnership(std::move(log_record));
    return;
  }
  for (auto& kv : copy) {
    kv.second->Process(log_record);
  }
}

namespace {
class StdClogBackend : public LogBackend {
 public:
  StdClogBackend() = default;

  void Process(LogRecord const& lr) override {
    std::clog << lr << "\n";
    if (lr.severity >= Severity::GCP_LS_WARNING) {
      std::clog << std::flush;
    }
  }
  void ProcessWithOwnership(LogRecord lr) override { Process(lr); }
};
}  // namespace

void LogSink::EnableStdClogImpl() {
  std::unique_lock<std::mutex> lk(mu_);
  if (clog_backend_id_ != 0) {
    return;
  }
  clog_backend_id_ = AddBackendImpl(std::make_shared<StdClogBackend>());
}

void LogSink::DisableStdClogImpl() {
  std::unique_lock<std::mutex> lk(mu_);
  if (clog_backend_id_ == 0) {
    return;
  }
  RemoveBackendImpl(clog_backend_id_);
  clog_backend_id_ = 0;
}

// NOLINTNEXTLINE(google-runtime-int)
long LogSink::AddBackendImpl(std::shared_ptr<LogBackend> backend) {
  auto const id = ++next_id_;
  backends_.emplace(id, std::move(backend));
  empty_.store(backends_.empty());
  return id;
}

// NOLINTNEXTLINE(google-runtime-int)
void LogSink::RemoveBackendImpl(long id) {
  auto it = backends_.find(id);
  if (backends_.end() == it) {
    return;
  }
  backends_.erase(it);
  empty_.store(backends_.empty());
}

}  // namespace GOOGLE_CLOUD_CPP_NS
}  // namespace cloud
}  // namespace google
<|endoftext|>


<commit_before>#ifndef NN_RELU_HPP
#define NN_RELU_HPP

#include <math.h>
#include "map.hpp"

namespace nnlib
{

/// Rectified linear activation function.
template <typename T = double>
class ReLU : public Map<T>
{
public:
	ReLU(T leak = 0.1) :
		m_leak(leak)
	{}

	ReLU(const ReLU &module) :
		m_leak(module.m_leak)
	{}

	ReLU(const Serialized &node) :
		m_leak(node.get<T>("leak"))
	{}

	ReLU &operator=(const ReLU &module)
	{
		m_leak = module.m_leak;
		return *this;
	}

	/// Save to a serialized node.
	virtual void save(Serialized &node) const override
	{
		Map<T>::save(node);
		node.set("leak", m_leak);
	}

	/// Get the "leak" for this ReLU. 0 if non-leaky.
	T leak() const
	{
		return m_leak;
	}

	/// Set the "leak" for this ReLU. 0 <= leak < 1.
	ReLU &leak(T leak)
	{
		NNAssertGreaterThanOrEquals(leak, 0, "Expected positive leak!");
		NNAssertLessThan(leak, 1, "Expected leak to be a percentage!");
		m_leak = leak;
		return *this;
	}

	/// Single element forward.
	virtual T forwardOne(const T &x) override
	{
		return x > 0 ? x : m_leak * x;
	}

	/// Single element backward.
	virtual T backwardOne(const T &x, const T &y) override
	{
		return x > 0 ? 1 : m_leak;
	}

private:
	T m_leak;
};

}

NNRegisterType(ReLU, Module);

#endif
<commit_msg>Added an assert to ReLU constructor.<commit_after>#ifndef NN_RELU_HPP
#define NN_RELU_HPP

#include <math.h>
#include "map.hpp"

namespace nnlib
{

/// Rectified linear activation function.
template <typename T = double>
class ReLU : public Map<T>
{
public:
	ReLU(T leak = 0.1) :
		m_leak(leak)
	{
		NNAssertGreaterThanOrEquals(leak, 0, "Expected positive leak!");
		NNAssertLessThan(leak, 1, "Expected leak to be a percentage!");
	}

	ReLU(const ReLU &module) :
		m_leak(module.m_leak)
	{}

	ReLU(const Serialized &node) :
		m_leak(node.get<T>("leak"))
	{}

	ReLU &operator=(const ReLU &module)
	{
		m_leak = module.m_leak;
		return *this;
	}

	/// Save to a serialized node.
	virtual void save(Serialized &node) const override
	{
		Map<T>::save(node);
		node.set("leak", m_leak);
	}

	/// Get the "leak" for this ReLU. 0 if non-leaky.
	T leak() const
	{
		return m_leak;
	}

	/// Set the "leak" for this ReLU. 0 <= leak < 1.
	ReLU &leak(T leak)
	{
		NNAssertGreaterThanOrEquals(leak, 0, "Expected positive leak!");
		NNAssertLessThan(leak, 1, "Expected leak to be a percentage!");
		m_leak = leak;
		return *this;
	}

	/// Single element forward.
	virtual T forwardOne(const T &x) override
	{
		return x > 0 ? x : m_leak * x;
	}

	/// Single element backward.
	virtual T backwardOne(const T &x, const T &y) override
	{
		return x > 0 ? 1 : m_leak;
	}

private:
	T m_leak;
};

}

NNRegisterType(ReLU, Module);

#endif
<|endoftext|>


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

BGSLibrary is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

BGSLibrary is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with BGSLibrary.  If not, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************************
*
* GrimsonGMM.cpp
*
* Purpose: Implementation of the Gaussian mixture model (GMM) background
*		  		 subtraction described in:
*	  			 "Adaptive background mixture models for real-time tracking"
* 						by Chris Stauffer and W.E.L Grimson
*
* Author: Donovan Parks, September 2007
*
* This code is based on code by Z. Zivkovic's written for his enhanced GMM
* background subtraction algorithm:
*
*	"Improved adaptive Gausian mixture model for background subtraction"
*		Z.Zivkovic
*		International Conference Pattern Recognition, UK, August, 2004
*
*
* "Efficient Adaptive Density Estimapion per Image Pixel for the
*			Task of Background Subtraction"
*		Z.Zivkovic, F. van der Heijden
*		Pattern Recognition Letters, vol. 27, no. 7, pages 773-780, 2006.
*
* Zivkovic's code can be obtained at: www.zoranz.net
******************************************************************************/

#include "GrimsonGMM.h"

using namespace Algorithms::BackgroundSubtraction;

int compareGMM(const void* _gmm1, const void* _gmm2)
{
	GMM gmm1 = *(GMM*)_gmm1;
	GMM gmm2 = *(GMM*)_gmm2;

	if(gmm1.significants < gmm2.significants)
		return 1;
	else if(gmm1.significants == gmm2.significants)
		return 0;
	else
		return -1;
}

GrimsonGMM::GrimsonGMM()
{
	m_modes = NULL;
}

GrimsonGMM::~GrimsonGMM()
{
	if(m_modes != NULL)
		delete[] m_modes;
}

void GrimsonGMM::Initalize(const BgsParams& param)
{
	m_params = (GrimsonParams&)param;

	// Tbf - the threshold
	m_bg_threshold = 0.75f;	// 1-cf from the paper

	// Tgenerate - the threshold
	m_variance = 36.0f;		// sigma for the new mode

	// GMM for each pixel
	m_modes = new GMM[m_params.Size()*m_params.MaxModes()];

	// used modes per pixel
	m_modes_per_pixel = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 1);

	m_background = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 3);
}

RgbImage* GrimsonGMM::Background()
{
	return &m_background;
}

void GrimsonGMM::InitModel(const RgbImage& data)
{
	m_modes_per_pixel.Clear();

	for(unsigned int i = 0; i < m_params.Size()*m_params.MaxModes(); ++i)
	{
		m_modes[i].weight = 0;
		m_modes[i].variance = 0;
		m_modes[i].muR = 0;
		m_modes[i].muG = 0;
		m_modes[i].muB = 0;
		m_modes[i].significants = 0;
	}
}

void GrimsonGMM::Update(int frame_num, const RgbImage& data,  const BwImage& update_mask)
{
	// it doesn't make sense to have conditional updates in the GMM framework
}

void GrimsonGMM::SubtractPixel(long posPixel, const RgbPixel& pixel, unsigned char& numModes,
																	unsigned char& low_threshold, unsigned char& high_threshold)
{
	// calculate distances to the modes (+ sort???)
	// here we need to go in descending order!!!
	long pos;
	bool bFitsPDF=false;
	bool bBackgroundLow=false;
	bool bBackgroundHigh=false;

	float fOneMinAlpha = 1-m_params.Alpha();

	float totalWeight = 0.0f;

	// calculate number of Gaussians to include in the background model
	int backgroundGaussians = 0;
	double sum = 0.0;
	for(int i = 0; i < numModes; ++i)
	{
		if(sum < m_bg_threshold)
		{
			backgroundGaussians++;
			sum += m_modes[posPixel+i].weight;
		}
		else
		{
			break;
		}
	}

	// update all distributions and check for match with current pixel
	for (int iModes=0; iModes < numModes; iModes++)
	{
		pos=posPixel+iModes;
		float weight = m_modes[pos].weight;

		// fit not found yet
		if (!bFitsPDF)
		{
			//check if it belongs to some of the modes
			//calculate distance
			float var = m_modes[pos].variance;
			float muR = m_modes[pos].muR;
			float muG = m_modes[pos].muG;
			float muB = m_modes[pos].muB;

			float dR=muR - pixel(0);
			float dG=muG - pixel(1);
			float dB=muB - pixel(2);

			// calculate the squared distance
			float dist = (dR*dR + dG*dG + dB*dB);

			if(dist < m_params.HighThreshold()*var && iModes < backgroundGaussians)
				bBackgroundHigh = true;

			// a match occurs when the pixel is within sqrt(fTg) standard deviations of the distribution
			if(dist < m_params.LowThreshold()*var)
			{
				bFitsPDF=true;

				// check if this Gaussian is part of the background model
				if(iModes < backgroundGaussians)
					bBackgroundLow = true;

				//update distribution
				float k = m_params.Alpha()/weight;
				weight = fOneMinAlpha*weight + m_params.Alpha();
				m_modes[pos].weight = weight;
				m_modes[pos].muR = muR - k*(dR);
				m_modes[pos].muG = muG - k*(dG);
				m_modes[pos].muB = muB - k*(dB);

				//limit the variance
				float sigmanew = var + k*(dist-var);
				m_modes[pos].variance = sigmanew < 4 ? 4 : sigmanew > 5*m_variance ? 5*m_variance : sigmanew;
				m_modes[pos].significants = m_modes[pos].weight / sqrt(m_modes[pos].variance);
			}
			else
			{
				weight = fOneMinAlpha*weight;
				if (weight < 0.0)
				{
					weight=0.0;
					numModes--;
				}

				m_modes[pos].weight = weight;
				m_modes[pos].significants = m_modes[pos].weight / sqrt(m_modes[pos].variance);
			}
		}
		else
		{
			weight = fOneMinAlpha*weight;
			if (weight < 0.0)
			{
				weight=0.0;
				numModes--;
			}
			m_modes[pos].weight = weight;
			m_modes[pos].significants = m_modes[pos].weight / sqrt(m_modes[pos].variance);
		}

		totalWeight += weight;
	}

	// renormalize weights so they add to one
	double invTotalWeight = 1.0 / totalWeight;
	for (int iLocal = 0; iLocal < numModes; iLocal++)
	{
		m_modes[posPixel + iLocal].weight *= (float)invTotalWeight;
		m_modes[posPixel + iLocal].significants = m_modes[posPixel + iLocal].weight
																								/ sqrt(m_modes[posPixel + iLocal].variance);
	}

	// Sort significance values so they are in desending order.
	qsort(&m_modes[posPixel],  numModes, sizeof(GMM), compareGMM);

	// make new mode if needed and exit
	if (!bFitsPDF)
	{
		if (numModes < m_params.MaxModes())
		{
			numModes++;
		}
		else
		{
			// the weakest mode will be replaced
		}

		pos = posPixel + numModes-1;

		m_modes[pos].muR = pixel.ch[0];
		m_modes[pos].muG = pixel.ch[1];
		m_modes[pos].muB = pixel.ch[2];
		m_modes[pos].variance = m_variance;
		m_modes[pos].significants = 0;			// will be set below

    if (numModes==1)
			m_modes[pos].weight = 1;
		else
			m_modes[pos].weight = m_params.Alpha();

		//renormalize weights
		int iLocal;
		float sum = 0.0;
		for (iLocal = 0; iLocal < numModes; iLocal++)
		{
			sum += m_modes[posPixel+ iLocal].weight;
		}

		double invSum = 1.0/sum;
		for (iLocal = 0; iLocal < numModes; iLocal++)
		{
			m_modes[posPixel + iLocal].weight *= (float)invSum;
			m_modes[posPixel + iLocal].significants = m_modes[posPixel + iLocal].weight
																								/ sqrt(m_modes[posPixel + iLocal].variance);

		}
	}

	// Sort significance values so they are in desending order.
	qsort(&(m_modes[posPixel]), numModes, sizeof(GMM), compareGMM);

	if(bBackgroundLow)
	{
		low_threshold = BACKGROUND;
	}
	else
	{
		low_threshold = FOREGROUND;
	}

	if(bBackgroundHigh)
	{
		high_threshold = BACKGROUND;
	}
	else
	{
		high_threshold = FOREGROUND;
	}
}

///////////////////////////////////////////////////////////////////////////////
//Input:
//  data - a pointer to the data of a RGB image of the same size
//Output:
//  output - a pointer to the data of a gray value image of the same size
//					(the memory should already be reserved)
//					values: 255-foreground, 125-shadow, 0-background
///////////////////////////////////////////////////////////////////////////////
void GrimsonGMM::Subtract(int frame_num, const RgbImage& data,
														BwImage& low_threshold_mask, BwImage& high_threshold_mask)
{
	unsigned char low_threshold, high_threshold;
	long posPixel;

	// update each pixel of the image
	for(unsigned int r = 0; r < m_params.Height(); ++r)
	{
		for(unsigned int c = 0; c < m_params.Width(); ++c)
		{
			// update model + background subtract
			posPixel=(r*m_params.Width()+c)*m_params.MaxModes();

			SubtractPixel(posPixel, data(r,c), m_modes_per_pixel(r,c), low_threshold, high_threshold);

			low_threshold_mask(r,c) = low_threshold;
			high_threshold_mask(r,c) = high_threshold;

			m_background(r,c,0) = (unsigned char)m_modes[posPixel].muR;
			m_background(r,c,1) = (unsigned char)m_modes[posPixel].muG;
			m_background(r,c,2) = (unsigned char)m_modes[posPixel].muB;
		}
	}
}

<commit_msg>Update GrimsonGMM.cpp<commit_after>/*
This file is part of BGSLibrary.

BGSLibrary is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

BGSLibrary is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with BGSLibrary.  If not, see <http://www.gnu.org/licenses/>.
*/
/****************************************************************************
*
* GrimsonGMM.cpp
*
* Purpose: Implementation of the Gaussian mixture model (GMM) background
*		  		 subtraction described in:
*	  			 "Adaptive background mixture models for real-time tracking"
* 						by Chris Stauffer and W.E.L Grimson
*
* Author: Donovan Parks, September 2007
*
* This code is based on code by Z. Zivkovic's written for his enhanced GMM
* background subtraction algorithm:
*
*	"Improved adaptive Gausian mixture model for background subtraction"
*		Z.Zivkovic
*		International Conference Pattern Recognition, UK, August, 2004
*
*
* "Efficient Adaptive Density Estimapion per Image Pixel for the
*			Task of Background Subtraction"
*		Z.Zivkovic, F. van der Heijden
*		Pattern Recognition Letters, vol. 27, no. 7, pages 773-780, 2006.
*
* Zivkovic's code can be obtained at: www.zoranz.net
******************************************************************************/

#include "GrimsonGMM.h"

using namespace Algorithms::BackgroundSubtraction;

int compareGMM(const void* _gmm1, const void* _gmm2)
{
	GMM gmm1 = *(GMM*)_gmm1;
	GMM gmm2 = *(GMM*)_gmm2;

	if(gmm1.significants < gmm2.significants)
		return 1;
	else if(gmm1.significants == gmm2.significants)
		return 0;
	else
		return -1;
}

GrimsonGMM::GrimsonGMM()
{
	m_modes = NULL;
}

GrimsonGMM::~GrimsonGMM()
{
	delete[] m_modes;
}

void GrimsonGMM::Initalize(const BgsParams& param)
{
	m_params = (GrimsonParams&)param;

	// Tbf - the threshold
	m_bg_threshold = 0.75f;	// 1-cf from the paper

	// Tgenerate - the threshold
	m_variance = 36.0f;		// sigma for the new mode

	// GMM for each pixel
	m_modes = new GMM[m_params.Size()*m_params.MaxModes()];

	// used modes per pixel
	m_modes_per_pixel = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 1);

	m_background = cvCreateImage(cvSize(m_params.Width(), m_params.Height()), IPL_DEPTH_8U, 3);
}

RgbImage* GrimsonGMM::Background()
{
	return &m_background;
}

void GrimsonGMM::InitModel(const RgbImage& data)
{
	m_modes_per_pixel.Clear();

	for(unsigned int i = 0; i < m_params.Size()*m_params.MaxModes(); ++i)
	{
		m_modes[i].weight = 0;
		m_modes[i].variance = 0;
		m_modes[i].muR = 0;
		m_modes[i].muG = 0;
		m_modes[i].muB = 0;
		m_modes[i].significants = 0;
	}
}

void GrimsonGMM::Update(int frame_num, const RgbImage& data,  const BwImage& update_mask)
{
	// it doesn't make sense to have conditional updates in the GMM framework
}

void GrimsonGMM::SubtractPixel(long posPixel, const RgbPixel& pixel, unsigned char& numModes,
																	unsigned char& low_threshold, unsigned char& high_threshold)
{
	// calculate distances to the modes (+ sort???)
	// here we need to go in descending order!!!
	long pos;
	bool bFitsPDF=false;
	bool bBackgroundLow=false;
	bool bBackgroundHigh=false;

	float fOneMinAlpha = 1-m_params.Alpha();

	float totalWeight = 0.0f;

	// calculate number of Gaussians to include in the background model
	int backgroundGaussians = 0;
	double sum = 0.0;
	for(int i = 0; i < numModes; ++i)
	{
		if(sum < m_bg_threshold)
		{
			backgroundGaussians++;
			sum += m_modes[posPixel+i].weight;
		}
		else
		{
			break;
		}
	}

	// update all distributions and check for match with current pixel
	for (int iModes=0; iModes < numModes; iModes++)
	{
		pos=posPixel+iModes;
		float weight = m_modes[pos].weight;

		// fit not found yet
		if (!bFitsPDF)
		{
			//check if it belongs to some of the modes
			//calculate distance
			float var = m_modes[pos].variance;
			float muR = m_modes[pos].muR;
			float muG = m_modes[pos].muG;
			float muB = m_modes[pos].muB;

			float dR=muR - pixel(0);
			float dG=muG - pixel(1);
			float dB=muB - pixel(2);

			// calculate the squared distance
			float dist = (dR*dR + dG*dG + dB*dB);

			if(dist < m_params.HighThreshold()*var && iModes < backgroundGaussians)
				bBackgroundHigh = true;

			// a match occurs when the pixel is within sqrt(fTg) standard deviations of the distribution
			if(dist < m_params.LowThreshold()*var)
			{
				bFitsPDF=true;

				// check if this Gaussian is part of the background model
				if(iModes < backgroundGaussians)
					bBackgroundLow = true;

				//update distribution
				float k = m_params.Alpha()/weight;
				weight = fOneMinAlpha*weight + m_params.Alpha();
				m_modes[pos].weight = weight;
				m_modes[pos].muR = muR - k*(dR);
				m_modes[pos].muG = muG - k*(dG);
				m_modes[pos].muB = muB - k*(dB);

				//limit the variance
				float sigmanew = var + k*(dist-var);
				m_modes[pos].variance = sigmanew < 4 ? 4 : sigmanew > 5*m_variance ? 5*m_variance : sigmanew;
				m_modes[pos].significants = m_modes[pos].weight / sqrt(m_modes[pos].variance);
			}
			else
			{
				weight = fOneMinAlpha*weight;
				if (weight < 0.0)
				{
					weight=0.0;
					numModes--;
				}

				m_modes[pos].weight = weight;
				m_modes[pos].significants = m_modes[pos].weight / sqrt(m_modes[pos].variance);
			}
		}
		else
		{
			weight = fOneMinAlpha*weight;
			if (weight < 0.0)
			{
				weight=0.0;
				numModes--;
			}
			m_modes[pos].weight = weight;
			m_modes[pos].significants = m_modes[pos].weight / sqrt(m_modes[pos].variance);
		}

		totalWeight += weight;
	}

	// renormalize weights so they add to one
	double invTotalWeight = 1.0 / totalWeight;
	for (int iLocal = 0; iLocal < numModes; iLocal++)
	{
		m_modes[posPixel + iLocal].weight *= (float)invTotalWeight;
		m_modes[posPixel + iLocal].significants = m_modes[posPixel + iLocal].weight
																								/ sqrt(m_modes[posPixel + iLocal].variance);
	}

	// Sort significance values so they are in desending order.
	qsort(&m_modes[posPixel],  numModes, sizeof(GMM), compareGMM);

	// make new mode if needed and exit
	if (!bFitsPDF)
	{
		if (numModes < m_params.MaxModes())
		{
			numModes++;
		}
		else
		{
			// the weakest mode will be replaced
		}

		pos = posPixel + numModes-1;

		m_modes[pos].muR = pixel.ch[0];
		m_modes[pos].muG = pixel.ch[1];
		m_modes[pos].muB = pixel.ch[2];
		m_modes[pos].variance = m_variance;
		m_modes[pos].significants = 0;			// will be set below

    if (numModes==1)
			m_modes[pos].weight = 1;
		else
			m_modes[pos].weight = m_params.Alpha();

		//renormalize weights
		int iLocal;
		float sum = 0.0;
		for (iLocal = 0; iLocal < numModes; iLocal++)
		{
			sum += m_modes[posPixel+ iLocal].weight;
		}

		double invSum = 1.0/sum;
		for (iLocal = 0; iLocal < numModes; iLocal++)
		{
			m_modes[posPixel + iLocal].weight *= (float)invSum;
			m_modes[posPixel + iLocal].significants = m_modes[posPixel + iLocal].weight
																								/ sqrt(m_modes[posPixel + iLocal].variance);

		}
	}

	// Sort significance values so they are in desending order.
	qsort(&(m_modes[posPixel]), numModes, sizeof(GMM), compareGMM);

	if(bBackgroundLow)
	{
		low_threshold = BACKGROUND;
	}
	else
	{
		low_threshold = FOREGROUND;
	}

	if(bBackgroundHigh)
	{
		high_threshold = BACKGROUND;
	}
	else
	{
		high_threshold = FOREGROUND;
	}
}

///////////////////////////////////////////////////////////////////////////////
//Input:
//  data - a pointer to the data of a RGB image of the same size
//Output:
//  output - a pointer to the data of a gray value image of the same size
//					(the memory should already be reserved)
//					values: 255-foreground, 125-shadow, 0-background
///////////////////////////////////////////////////////////////////////////////
void GrimsonGMM::Subtract(int frame_num, const RgbImage& data,
														BwImage& low_threshold_mask, BwImage& high_threshold_mask)
{
	unsigned char low_threshold, high_threshold;
	long posPixel;

	// update each pixel of the image
	for(unsigned int r = 0; r < m_params.Height(); ++r)
	{
		for(unsigned int c = 0; c < m_params.Width(); ++c)
		{
			// update model + background subtract
			posPixel=(r*m_params.Width()+c)*m_params.MaxModes();

			SubtractPixel(posPixel, data(r,c), m_modes_per_pixel(r,c), low_threshold, high_threshold);

			low_threshold_mask(r,c) = low_threshold;
			high_threshold_mask(r,c) = high_threshold;

			m_background(r,c,0) = (unsigned char)m_modes[posPixel].muR;
			m_background(r,c,1) = (unsigned char)m_modes[posPixel].muG;
			m_background(r,c,2) = (unsigned char)m_modes[posPixel].muB;
		}
	}
}

<|endoftext|>


<commit_before>//
// Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//

//
// bench.cpp : spdlog benchmarks
//
#include "spdlog/async.h"
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/daily_file_sink.h"
#include "spdlog/sinks/null_sink.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include "spdlog/spdlog.h"
#include "utils.h"
#include <atomic>
#include <cstdlib> // EXIT_FAILURE
#include <iostream>
#include <memory>
#include <string>
#include <thread>

using namespace std;
using namespace std::chrono;
using namespace spdlog;
using namespace spdlog::sinks;
using namespace utils;

void bench(int howmany, std::shared_ptr<spdlog::logger> log);
void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count);

int main(int argc, char *argv[])
{

    int queue_size = 1000000;
    int howmany = 1000000;
    int threads = 10;
    int file_size = 30 * 1024 * 1024;
    int rotating_files = 5;

    try
    {

        if (argc > 1)
            howmany = atoi(argv[1]);
        if (argc > 2)
            threads = atoi(argv[2]);
        if (argc > 3)
            queue_size = atoi(argv[3]);

        cout << "*******************************************************************************\n";
        cout << "Single thread, " << format(howmany) << " iterations" << endl;
        cout << "*******************************************************************************\n";

        auto basic_st = spdlog::basic_logger_mt("basic_st", "logs/basic_st.log", true);
        bench(howmany, basic_st);

        auto rotating_st = spdlog::rotating_logger_st("rotating_st", "logs/rotating_st.log", file_size, rotating_files);
        bench(howmany, rotating_st);

        auto daily_st = spdlog::daily_logger_st("daily_st", "logs/daily_st.log");
        bench(howmany, daily_st);

        bench(howmany, spdlog::create<null_sink_st>("null_st"));

        cout << "\n*******************************************************************************\n";
        cout << threads << " threads sharing same logger, " << format(howmany) << " iterations" << endl;
        cout << "*******************************************************************************\n";

        auto basic_mt = spdlog::basic_logger_mt("basic_mt", "logs/basic_mt.log", true);
        bench_mt(howmany, basic_mt, threads);

        auto rotating_mt = spdlog::rotating_logger_mt("rotating_mt", "logs/rotating_mt.log", file_size, rotating_files);
        bench_mt(howmany, rotating_mt, threads);

        auto daily_mt = spdlog::daily_logger_mt("daily_mt", "logs/daily_mt.log");
        bench_mt(howmany, daily_mt, threads);
        bench(howmany, spdlog::create<null_sink_st>("null_mt"));

        cout << "\n*******************************************************************************\n";
        cout << "async logging.. " << threads << " threads sharing same logger, " << format(howmany) << " iterations " << endl;
        cout << "*******************************************************************************\n";

        for (int i = 0; i < 3; ++i)
        {
            spdlog::init_thread_pool(queue_size, 1);
            auto as = spdlog::basic_logger_mt<spdlog::async_factory>("async", "logs/basic_async.log", true);
            bench_mt(howmany, as, threads);
            spdlog::drop("async");
        }
    }
    catch (std::exception &ex)
    {
        std::cerr << "Error: " << ex.what() << std::endl;
        perror("Last error");
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

void bench(int howmany, std::shared_ptr<spdlog::logger> log)
{
    using std::chrono::high_resolution_clock;
    cout << log->name() << "...\t\t" << flush;
    auto start = high_resolution_clock::now();
    for (auto i = 0; i < howmany; ++i)
    {
        log->info("Hello logger: msg number {}", i);
    }

    auto delta = high_resolution_clock::now() - start;
    auto delta_d = duration_cast<duration<double>>(delta).count();
    cout << "Elapsed: " << delta_d << "\t" << format(int(howmany / delta_d)) << "/sec" << endl;
}

void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count)
{
    using std::chrono::high_resolution_clock;
    cout << log->name() << "...\t\t" << flush;
    vector<thread> threads;
    auto start = high_resolution_clock::now();
    for (int t = 0; t < thread_count; ++t)
    {
        threads.push_back(std::thread([&]() {
            for (int j = 0; j < howmany / thread_count; j++)
            {
                log->info("Hello logger: msg number {}", j);
            }
        }));
    }

    for (auto &t : threads)
    {
        t.join();
    };

    auto delta = high_resolution_clock::now() - start;
    auto delta_d = duration_cast<duration<double>>(delta).count();
    cout << "Elapsed: " << delta_d << "\t" << format(int(howmany / delta_d)) << "/sec" << endl;
}
<commit_msg>bench fix<commit_after>//
// Copyright(c) 2015 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//

//
// bench.cpp : spdlog benchmarks
//
#include "spdlog/async.h"
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/daily_file_sink.h"
#include "spdlog/sinks/null_sink.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include "spdlog/spdlog.h"
#include "utils.h"
#include <atomic>
#include <cstdlib> // EXIT_FAILURE
#include <iostream>
#include <memory>
#include <string>
#include <thread>

using namespace std;
using namespace std::chrono;
using namespace spdlog;
using namespace spdlog::sinks;
using namespace utils;

void bench(int howmany, std::shared_ptr<spdlog::logger> log);
void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count);

int main(int argc, char *argv[])
{

    int howmany = 1000000;
    int queue_size = howmany + 2;
    int threads = 10;
    int file_size = 30 * 1024 * 1024;
    int rotating_files = 5;

    try
    {

        if (argc > 1)
            howmany = atoi(argv[1]);
        if (argc > 2)
            threads = atoi(argv[2]);
        if (argc > 3)
            queue_size = atoi(argv[3]);

        cout << "*******************************************************************************\n";
        cout << "Single thread, " << format(howmany) << " iterations" << endl;
        cout << "*******************************************************************************\n";

        auto basic_st = spdlog::basic_logger_mt("basic_st", "logs/basic_st.log", true);
        bench(howmany, basic_st);

        auto rotating_st = spdlog::rotating_logger_st("rotating_st", "logs/rotating_st.log", file_size, rotating_files);
        bench(howmany, rotating_st);

        auto daily_st = spdlog::daily_logger_st("daily_st", "logs/daily_st.log");
        bench(howmany, daily_st);

        bench(howmany, spdlog::create<null_sink_st>("null_st"));

        cout << "\n*******************************************************************************\n";
        cout << threads << " threads sharing same logger, " << format(howmany) << " iterations" << endl;
        cout << "*******************************************************************************\n";

        auto basic_mt = spdlog::basic_logger_mt("basic_mt", "logs/basic_mt.log", true);
        bench_mt(howmany, basic_mt, threads);

        auto rotating_mt = spdlog::rotating_logger_mt("rotating_mt", "logs/rotating_mt.log", file_size, rotating_files);
        bench_mt(howmany, rotating_mt, threads);

        auto daily_mt = spdlog::daily_logger_mt("daily_mt", "logs/daily_mt.log");
        bench_mt(howmany, daily_mt, threads);
        bench(howmany, spdlog::create<null_sink_st>("null_mt"));

        cout << "\n*******************************************************************************\n";
        cout << "async logging.. " << threads << " threads sharing same logger, " << format(howmany) << " iterations " << endl;
        cout << "*******************************************************************************\n";

        for (int i = 0; i < 3; ++i)
        {
            spdlog::init_thread_pool(queue_size, 1);
            auto as = spdlog::basic_logger_mt<spdlog::async_factory>("async", "logs/basic_async.log", true);
            bench_mt(howmany, as, threads);
            spdlog::drop("async");
        }
    }
    catch (std::exception &ex)
    {
        std::cerr << "Error: " << ex.what() << std::endl;
        perror("Last error");
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

void bench(int howmany, std::shared_ptr<spdlog::logger> log)
{
    using std::chrono::high_resolution_clock;
    cout << log->name() << "...\t\t" << flush;
    auto start = high_resolution_clock::now();
    for (auto i = 0; i < howmany; ++i)
    {
        log->info("Hello logger: msg number {}", i);
    }

    auto delta = high_resolution_clock::now() - start;
    auto delta_d = duration_cast<duration<double>>(delta).count();
    cout << "Elapsed: " << delta_d << "\t" << format(int(howmany / delta_d)) << "/sec" << endl;
}

void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count)
{
    using std::chrono::high_resolution_clock;
    cout << log->name() << "...\t\t" << flush;
    vector<thread> threads;
    auto start = high_resolution_clock::now();
    for (int t = 0; t < thread_count; ++t)
    {
        threads.push_back(std::thread([&]() {
            for (int j = 0; j < howmany / thread_count; j++)
            {
                log->info("Hello logger: msg number {}", j);
            }
        }));
    }

    for (auto &t : threads)
    {
        t.join();
    };

    auto delta = high_resolution_clock::now() - start;
    auto delta_d = duration_cast<duration<double>>(delta).count();
    cout << "Elapsed: " << delta_d << "\t" << format(int(howmany / delta_d)) << "/sec" << endl;
}
<|endoftext|>


<commit_before>
#include <gloperate/rendering/ColorGradientPreparation.h>

#include <cppexpose/reflection/AbstractProperty.h>

#include <gloperate/rendering/AbstractColorGradient.h>
#include <gloperate/rendering/ColorGradientList.h>

namespace gloperate
{

ColorGradientPreparation::ColorGradientPreparation(const ColorGradientList & gradients, const std::pair<std::uint32_t, std::uint32_t> & iconSize)
: ColorGradientPreparation(gradients, iconSize, {})
{
}

ColorGradientPreparation::ColorGradientPreparation(const ColorGradientList & gradients, const std::pair<std::uint32_t, std::uint32_t> & iconSize, const std::set<std::string> & whitelist)
: m_gradients(gradients)
, m_iconSize(iconSize)
, m_whitelist(whitelist)
{
}

const ColorGradientList & ColorGradientPreparation::gradients() const
{
    return m_gradients;
}

const std::pair<std::uint32_t, std::uint32_t> & ColorGradientPreparation::iconSize() const
{
    return m_iconSize;
}

std::vector<std::string> ColorGradientPreparation::names() const
{
    std::vector<std::string> result;

    fillNames(result);

    return result;
}

void ColorGradientPreparation::fillNames(std::vector<std::string> & names) const
{
    names.clear();

    for (const auto & pair : m_gradients.gradients())
    {
        if (!m_whitelist.empty() && m_whitelist.count(pair.first) == 0)
        {
            continue;
        }

        names.push_back(pair.first);
    }
}

std::vector<std::vector<unsigned char>> ColorGradientPreparation::pixmaps() const
{
    std::vector<std::vector<unsigned char>> result;

    fillPixmaps(result);

    return result;
}

void ColorGradientPreparation::fillPixmaps(std::vector<std::vector<unsigned char>> & pixmaps) const
{
    pixmaps.clear();

    for (const auto & pair : m_gradients.gradients())
    {
        if (!m_whitelist.empty() && m_whitelist.count(pair.first) == 0)
        {
            continue;
        }

        const AbstractColorGradient * gradient = pair.second;

        std::vector<unsigned char> gradientData(m_iconSize.first * m_iconSize.second * sizeof(std::uint32_t));

        for (size_t i = 0; i < m_iconSize.second; ++i)
        {
            gradient->fillPixelData(gradientData.data()+i*m_iconSize.first*sizeof(std::uint32_t), m_iconSize.first);
        }

        pixmaps.push_back(gradientData);
    }
}

void ColorGradientPreparation::configureProperty(cppexpose::AbstractProperty * property) const
{
    property->setOption("choices", cppexpose::Variant::arrayFromValues(names()));
    property->setOption("pixmapSize", cppexpose::Variant::fromValue(iconSize()));
    property->setOption("pixmaps", cppexpose::Variant::arrayFromValues(pixmaps()));
}

} // namespace gloperate
<commit_msg>Adjust to changed interface in cppexpose<commit_after>
#include <gloperate/rendering/ColorGradientPreparation.h>

#include <cppexpose/reflection/AbstractProperty.h>

#include <gloperate/rendering/AbstractColorGradient.h>
#include <gloperate/rendering/ColorGradientList.h>

namespace gloperate
{

ColorGradientPreparation::ColorGradientPreparation(const ColorGradientList & gradients, const std::pair<std::uint32_t, std::uint32_t> & iconSize)
: ColorGradientPreparation(gradients, iconSize, {})
{
}

ColorGradientPreparation::ColorGradientPreparation(const ColorGradientList & gradients, const std::pair<std::uint32_t, std::uint32_t> & iconSize, const std::set<std::string> & whitelist)
: m_gradients(gradients)
, m_iconSize(iconSize)
, m_whitelist(whitelist)
{
}

const ColorGradientList & ColorGradientPreparation::gradients() const
{
    return m_gradients;
}

const std::pair<std::uint32_t, std::uint32_t> & ColorGradientPreparation::iconSize() const
{
    return m_iconSize;
}

std::vector<std::string> ColorGradientPreparation::names() const
{
    std::vector<std::string> result;

    fillNames(result);

    return result;
}

void ColorGradientPreparation::fillNames(std::vector<std::string> & names) const
{
    names.clear();

    for (const auto & pair : m_gradients.gradients())
    {
        if (!m_whitelist.empty() && m_whitelist.count(pair.first) == 0)
        {
            continue;
        }

        names.push_back(pair.first);
    }
}

std::vector<std::vector<unsigned char>> ColorGradientPreparation::pixmaps() const
{
    std::vector<std::vector<unsigned char>> result;

    fillPixmaps(result);

    return result;
}

void ColorGradientPreparation::fillPixmaps(std::vector<std::vector<unsigned char>> & pixmaps) const
{
    pixmaps.clear();

    for (const auto & pair : m_gradients.gradients())
    {
        if (!m_whitelist.empty() && m_whitelist.count(pair.first) == 0)
        {
            continue;
        }

        const AbstractColorGradient * gradient = pair.second;

        std::vector<unsigned char> gradientData(m_iconSize.first * m_iconSize.second * sizeof(std::uint32_t));

        for (size_t i = 0; i < m_iconSize.second; ++i)
        {
            gradient->fillPixelData(gradientData.data()+i*m_iconSize.first*sizeof(std::uint32_t), m_iconSize.first);
        }

        pixmaps.push_back(gradientData);
    }
}

void ColorGradientPreparation::configureProperty(cppexpose::AbstractProperty * property) const
{
    property->setOption("choices", cppexpose::Variant::fromVector(names()));
    property->setOption("pixmapSize", cppexpose::Variant::fromValue(iconSize()));
    property->setOption("pixmaps", cppexpose::Variant::fromVector(pixmaps()));
}

} // namespace gloperate
<|endoftext|>