<commit_before>// This file is part of Poseidon.
// Copyleft 2020, LH_Mouse. All wrongs reserved.

#ifndef POSEIDON_UTILITIES_HPP_
#define POSEIDON_UTILITIES_HPP_

#include "fwd.hpp"
#include "static/async_logger.hpp"
#include "core/abstract_timer.hpp"
#include "static/timer_driver.hpp"
#include "core/abstract_async_job.hpp"
#include "core/promise.hpp"
#include "core/future.hpp"
#include "static/worker_pool.hpp"
#include <asteria/utilities.hpp>
#include <cstdio>

namespace poseidon {

using ::asteria::utf8_encode;
using ::asteria::utf8_decode;
using ::asteria::utf16_encode;
using ::asteria::utf16_decode;

using ::asteria::format_string;
using ::asteria::weaken_enum;
using ::asteria::generate_random_seed;
using ::asteria::format_errno;

template<typename... ParamsT>
ROCKET_NOINLINE
bool
do_xlog_format(Log_Level level, const char* file, long line, const char* func,
               const char* templ, const ParamsT&... params)
noexcept
  try {
    // Compose the message.
    ::rocket::tinyfmt_str fmt;
    format(fmt, templ, params...);  // ADL intended
    auto text = fmt.extract_string();

    // Push a new log entry.
    Async_Logger::enqueue(level, file, line, func, ::std::move(text));
    return true;
  }
  catch(exception& stdex) {
    // Ignore this exception, but print a message.
    ::std::fprintf(stderr,
        "WARNING: %s: could not format log: %s\n[exception `%s` thrown from '%s:%ld'\n",
        func, stdex.what(), typeid(stdex).name(), file, line);
    return false;
  }

// Note the format string must be a string literal.
#define POSEIDON_XLOG_(level, ...)  \
    (::poseidon::Async_Logger::is_enabled(level) &&  \
         ::poseidon::do_xlog_format(level, __FILE__, __LINE__, __func__,  \
                                    "" __VA_ARGS__))

#define POSEIDON_LOG_FATAL(...)   POSEIDON_XLOG_(::poseidon::log_level_fatal,  __VA_ARGS__)
#define POSEIDON_LOG_ERROR(...)   POSEIDON_XLOG_(::poseidon::log_level_error,  __VA_ARGS__)
#define POSEIDON_LOG_WARN(...)    POSEIDON_XLOG_(::poseidon::log_level_warn,   __VA_ARGS__)
#define POSEIDON_LOG_INFO(...)    POSEIDON_XLOG_(::poseidon::log_level_info,   __VA_ARGS__)
#define POSEIDON_LOG_DEBUG(...)   POSEIDON_XLOG_(::poseidon::log_level_debug,  __VA_ARGS__)
#define POSEIDON_LOG_TRACE(...)   POSEIDON_XLOG_(::poseidon::log_level_trace,  __VA_ARGS__)

template<typename... ParamsT>
[[noreturn]] ROCKET_NOINLINE
bool
do_xthrow_format(const char* file, long line, const char* func,
                 const char* templ, const ParamsT&... params)
  {
    // Compose the message.
    ::rocket::tinyfmt_str fmt;
    format(fmt, templ, params...);  // ADL intended
    auto text = fmt.extract_string();

    // Push a new log entry.
    static constexpr auto level = log_level_warn;
    if(Async_Logger::is_enabled(level))
      Async_Logger::enqueue(level, file, line, func, "POSEIDON_THROW: " + text);

    // Throw the exception.
    ::rocket::sprintf_and_throw<::std::runtime_error>(
        "%s: %s\n[thrown from '%s:%ld']",
        func, text.c_str(), file, line);
  }

#define POSEIDON_THROW(...)  \
    (::poseidon::do_xthrow_format(__FILE__, __LINE__, __func__,  \
                                  "" __VA_ARGS__))

// Creates an asynchronous timer. The timer function will be called by
// the timer thread, so thread safety must be taken into account.
template<typename FuncT>
rcptr<Abstract_Timer>
create_async_timer(int64_t next, int64_t period, FuncT&& func)
  {
    // This is the concrete timer class.
    struct Concrete_Timer : Abstract_Timer
      {
        typename ::std::decay<FuncT>::type m_func;

        explicit
        Concrete_Timer(int64_t next, int64_t period, FuncT&& func)
          : Abstract_Timer(next, period),
            m_func(::std::forward<FuncT>(func))
          { }

        void
        do_on_async_timer(int64_t now)
        override
          { this->m_func(now);  }
      };

    // Allocate an abstract timer and insert it.
    auto timer = ::rocket::make_unique<Concrete_Timer>(next, period,
                                           ::std::forward<FuncT>(func));
    return Timer_Driver::insert(::std::move(timer));
  }

// Creates a one-shot timer. The timer is deleted after being triggered.
template<typename FuncT>
rcptr<Abstract_Timer>
create_async_timer_oneshot(int64_t next, FuncT&& func)
  {
    return noadl::create_async_timer(next, 0, ::std::forward<FuncT>(func));
  }

// Creates a periodic timer.
template<typename FuncT>
rcptr<Abstract_Timer>
create_async_timer_periodic(int64_t period, FuncT&& func)
  {
    return noadl::create_async_timer(period, period, ::std::forward<FuncT>(func));
  }

// Enqueues an asynchronous job and returns a future to its result.
// Functions with the same key will always be delivered to the same worker.
template<typename FuncT>
futp<typename ::std::result_of<FuncT ()>::type>
enqueue_async_job_keyed(uintptr_t key, FuncT&& func)
  {
    // // This is the concrete function class.
    struct Concrete_Async_Job : Abstract_Async_Job
      {
        prom<typename ::std::result_of<FuncT ()>::type> m_prom;
        typename ::std::decay<FuncT>::type m_func;

        explicit
        Concrete_Async_Job(uintptr_t key, FuncT&& func)
          : Abstract_Async_Job(key),
            m_func(::std::forward<FuncT>(func))
          { }

        void
        do_execute()
        override
          { this->m_prom.set_value(this->m_func());  }

        void
        do_set_exception(const ::std::exception_ptr& eptr)
        override
          { this->m_prom.set_exception(eptr);  }
      };

    // Allocate a function object.
    auto async = ::rocket::make_unique<Concrete_Async_Job>(key,
                                           ::std::forward<FuncT>(func));
    auto futr = async->m_prom.future();
    Worker_Pool::insert(::std::move(async));
    return futr;
  }

// Enqueues an asynchronous job and returns a future to its result.
// The function is delivered to a random worker.
template<typename FuncT>
futp<typename ::std::result_of<FuncT ()>::type>
enqueue_async_job_random(FuncT&& func)
  {
    // // This is the concrete function class.
    struct Concrete_Async_Job : Abstract_Async_Job
      {
        prom<typename ::std::result_of<FuncT ()>::type> m_prom;
        typename ::std::decay<FuncT>::type m_func;

        explicit
        Concrete_Async_Job(FuncT&& func)
          : Abstract_Async_Job(reinterpret_cast<uintptr_t>(this)),
            m_func(::std::forward<FuncT>(func))
          { }

        void
        do_execute()
        override
          { this->m_prom.set_value(this->m_func());  }

        void
        do_set_exception(const ::std::exception_ptr& eptr)
        override
          { this->m_prom.set_exception(eptr);  }
      };

    // Allocate a function object.
    auto async = ::rocket::make_unique<Concrete_Async_Job>(
                                           ::std::forward<FuncT>(func));
    auto futr = async->m_prom.future();
    Worker_Pool::insert(::std::move(async));
    return futr;
  }

}  // namespace asteria

#endif
<commit_msg>utilities: Reformat<commit_after>// This file is part of Poseidon.
// Copyleft 2020, LH_Mouse. All wrongs reserved.

#ifndef POSEIDON_UTILITIES_HPP_
#define POSEIDON_UTILITIES_HPP_

#include "fwd.hpp"
#include "static/async_logger.hpp"
#include "core/abstract_timer.hpp"
#include "static/timer_driver.hpp"
#include "core/abstract_async_job.hpp"
#include "core/promise.hpp"
#include "core/future.hpp"
#include "static/worker_pool.hpp"
#include <asteria/utilities.hpp>
#include <cstdio>

namespace poseidon {

using ::asteria::utf8_encode;
using ::asteria::utf8_decode;
using ::asteria::utf16_encode;
using ::asteria::utf16_decode;

using ::asteria::format_string;
using ::asteria::weaken_enum;
using ::asteria::generate_random_seed;
using ::asteria::format_errno;

template<typename... ParamsT>
ROCKET_NOINLINE
bool
do_xlog_format(Log_Level level, const char* file, long line, const char* func,
               const char* templ, const ParamsT&... params)
noexcept
  try {
    // Compose the message.
    ::rocket::tinyfmt_str fmt;
    format(fmt, templ, params...);  // ADL intended
    auto text = fmt.extract_string();

    // Push a new log entry.
    Async_Logger::enqueue(level, file, line, func, ::std::move(text));
    return true;
  }
  catch(exception& stdex) {
    // Ignore this exception, but print a message.
    ::std::fprintf(stderr,
        "WARNING: %s: could not format log: %s\n[exception `%s` thrown from '%s:%ld'\n",
        func, stdex.what(), typeid(stdex).name(), file, line);
    return false;
  }

// Note the format string must be a string literal.
#define POSEIDON_XLOG_(level, ...)  \
    (::poseidon::Async_Logger::is_enabled(level) &&  \
         ::poseidon::do_xlog_format(level, __FILE__, __LINE__, __func__,  \
                                    "" __VA_ARGS__))

#define POSEIDON_LOG_FATAL(...)   POSEIDON_XLOG_(::poseidon::log_level_fatal,  __VA_ARGS__)
#define POSEIDON_LOG_ERROR(...)   POSEIDON_XLOG_(::poseidon::log_level_error,  __VA_ARGS__)
#define POSEIDON_LOG_WARN(...)    POSEIDON_XLOG_(::poseidon::log_level_warn,   __VA_ARGS__)
#define POSEIDON_LOG_INFO(...)    POSEIDON_XLOG_(::poseidon::log_level_info,   __VA_ARGS__)
#define POSEIDON_LOG_DEBUG(...)   POSEIDON_XLOG_(::poseidon::log_level_debug,  __VA_ARGS__)
#define POSEIDON_LOG_TRACE(...)   POSEIDON_XLOG_(::poseidon::log_level_trace,  __VA_ARGS__)

template<typename... ParamsT>
[[noreturn]] ROCKET_NOINLINE
bool
do_xthrow_format(const char* file, long line, const char* func,
                 const char* templ, const ParamsT&... params)
  {
    // Compose the message.
    ::rocket::tinyfmt_str fmt;
    format(fmt, templ, params...);  // ADL intended
    auto text = fmt.extract_string();

    // Push a new log entry.
    static constexpr auto level = log_level_warn;
    if(Async_Logger::is_enabled(level))
      Async_Logger::enqueue(level, file, line, func, "POSEIDON_THROW: " + text);

    // Throw the exception.
    ::rocket::sprintf_and_throw<::std::runtime_error>(
        "%s: %s\n[thrown from '%s:%ld']",
        func, text.c_str(), file, line);
  }

#define POSEIDON_THROW(...)  \
    (::poseidon::do_xthrow_format(__FILE__, __LINE__, __func__,  \
                                  "" __VA_ARGS__))

// Creates an asynchronous timer. The timer function will be called by
// the timer thread, so thread safety must be taken into account.
template<typename FuncT>
rcptr<Abstract_Timer>
create_async_timer(int64_t next, int64_t period, FuncT&& func)
  {
    // This is the concrete timer class.
    struct Concrete_Timer : Abstract_Timer
      {
        typename ::std::decay<FuncT>::type m_func;

        explicit
        Concrete_Timer(int64_t next, int64_t period, FuncT&& func)
          : Abstract_Timer(next, period),
            m_func(::std::forward<FuncT>(func))
          { }

        void
        do_on_async_timer(int64_t now)
        override
          { this->m_func(now);  }
      };

    // Allocate an abstract timer and insert it.
    auto timer = ::rocket::make_unique<Concrete_Timer>(next, period,
                                           ::std::forward<FuncT>(func));
    return Timer_Driver::insert(::std::move(timer));
  }

// Creates a one-shot timer. The timer is deleted after being triggered.
template<typename FuncT>
rcptr<Abstract_Timer>
create_async_timer_oneshot(int64_t next, FuncT&& func)
  {
    return noadl::create_async_timer(next, 0, ::std::forward<FuncT>(func));
  }

// Creates a periodic timer.
template<typename FuncT>
rcptr<Abstract_Timer>
create_async_timer_periodic(int64_t period, FuncT&& func)
  {
    return noadl::create_async_timer(period, period, ::std::forward<FuncT>(func));
  }

// Enqueues an asynchronous job and returns a future to its result.
// Functions with the same key will always be delivered to the same worker.
template<typename FuncT>
futp<typename ::std::result_of<FuncT ()>::type>
enqueue_async_job_keyed(uintptr_t key, FuncT&& func)
  {
    // // This is the concrete function class.
    struct Concrete_Async_Job : Abstract_Async_Job
      {
        prom<typename ::std::result_of<FuncT ()>::type> m_prom;
        typename ::std::decay<FuncT>::type m_func;

        explicit
        Concrete_Async_Job(uintptr_t key, FuncT&& func)
          : Abstract_Async_Job(key),
            m_func(::std::forward<FuncT>(func))
          { }

        void
        do_execute()
        override
          { this->m_prom.set_value(this->m_func());  }

        void
        do_set_exception(const ::std::exception_ptr& eptr)
        override
          { this->m_prom.set_exception(eptr);  }
      };

    // Allocate a function object.
    auto async = ::rocket::make_unique<Concrete_Async_Job>(key,
                                               ::std::forward<FuncT>(func));
    auto futr = async->m_prom.future();
    Worker_Pool::insert(::std::move(async));
    return futr;
  }

// Enqueues an asynchronous job and returns a future to its result.
// The function is delivered to a random worker.
template<typename FuncT>
futp<typename ::std::result_of<FuncT ()>::type>
enqueue_async_job_random(FuncT&& func)
  {
    // // This is the concrete function class.
    struct Concrete_Async_Job : Abstract_Async_Job
      {
        prom<typename ::std::result_of<FuncT ()>::type> m_prom;
        typename ::std::decay<FuncT>::type m_func;

        explicit
        Concrete_Async_Job(FuncT&& func)
          : Abstract_Async_Job(reinterpret_cast<uintptr_t>(this)),
            m_func(::std::forward<FuncT>(func))
          { }

        void
        do_execute()
        override
          { this->m_prom.set_value(this->m_func());  }

        void
        do_set_exception(const ::std::exception_ptr& eptr)
        override
          { this->m_prom.set_exception(eptr);  }
      };

    // Allocate a function object.
    auto async = ::rocket::make_unique<Concrete_Async_Job>(
                                               ::std::forward<FuncT>(func));
    auto futr = async->m_prom.future();
    Worker_Pool::insert(::std::move(async));
    return futr;
  }

}  // namespace asteria

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ppapi/cpp/paint_manager.h"

#include "ppapi/c/pp_errors.h"
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/logging.h"
#include "ppapi/cpp/module.h"

namespace pp {

PaintManager::PaintManager()
    : instance_(NULL),
      client_(NULL),
      is_always_opaque_(false),
      callback_factory_(NULL) {
  // Set the callback object outside of the initializer list to avoid a
  // compiler warning about using "this" in an initializer list.
  callback_factory_.Initialize(this);
}

PaintManager::PaintManager(Instance* instance,
                           Client* client,
                           bool is_always_opaque)
    : instance_(instance),
      client_(client),
      is_always_opaque_(is_always_opaque),
      callback_factory_(NULL) {
  // Set the callback object outside of the initializer list to avoid a
  // compiler warning about using "this" in an initializer list.
  callback_factory_.Initialize(this);

  // You can not use a NULL client pointer.
  PP_DCHECK(client);
}

PaintManager::~PaintManager() {
}

void PaintManager::Initialize(Instance* instance,
                              Client* client,
                              bool is_always_opaque) {
  PP_DCHECK(!instance_ && !client_);  // Can't initialize twice.
  instance_ = instance;
  client_ = client;
  is_always_opaque_ = is_always_opaque;
}

void PaintManager::SetSize(const Size& new_size) {
  if (new_size == graphics_.size())
    return;

  graphics_ = Graphics2D(new_size, is_always_opaque_);
  if (graphics_.is_null())
    return;
  instance_->BindGraphics(graphics_);

  manual_callback_pending_ = false;
  flush_pending_ = false;
  callback_factory_.CancelAll();

  Invalidate();
}

void PaintManager::Invalidate() {
  // You must call SetDevice before using.
  PP_DCHECK(!graphics_.is_null());

  EnsureCallbackPending();
  aggregator_.InvalidateRect(Rect(graphics_.size()));
}

void PaintManager::InvalidateRect(const Rect& rect) {
  // You must call SetDevice before using.
  PP_DCHECK(!graphics_.is_null());

  // Clip the rect to the device area.
  Rect clipped_rect = rect.Intersect(Rect(graphics_.size()));
  if (clipped_rect.IsEmpty())
    return;  // Nothing to do.

  EnsureCallbackPending();
  aggregator_.InvalidateRect(clipped_rect);
}

void PaintManager::ScrollRect(const Rect& clip_rect, const Point& amount) {
  // You must call SetDevice before using.
  PP_DCHECK(!graphics_.is_null());

  EnsureCallbackPending();
  aggregator_.ScrollRect(clip_rect, amount);
}

void PaintManager::EnsureCallbackPending() {
  // The best way for us to do the next update is to get a notification that
  // a previous one has completed. So if we're already waiting for one, we
  // don't have to do anything differently now.
  if (flush_pending_)
    return;

  // If no flush is pending, we need to do a manual call to get back to the
  // main thread. We may have one already pending, or we may need to schedule.
  if (manual_callback_pending_)
    return;

  Module::Get()->core()->CallOnMainThread(
      0,
      callback_factory_.NewCallback(&PaintManager::OnManualCallbackComplete),
      0);
  manual_callback_pending_ = true;
}

void PaintManager::DoPaint() {
  PP_DCHECK(aggregator_.HasPendingUpdate());

  // Make a copy of the pending update and clear the pending update flag before
  // actually painting. A plugin might cause invalidates in its Paint code, and
  // we want those to go to the *next* paint.
  PaintAggregator::PaintUpdate update = aggregator_.GetPendingUpdate();
  aggregator_.ClearPendingUpdate();

  // Apply any scroll before asking the client to paint.
  if (update.has_scroll)
    graphics_.Scroll(update.scroll_rect, update.scroll_delta);

  if (!client_->OnPaint(graphics_, update.paint_rects, update.paint_bounds))
    return;  // Nothing was painted, don't schedule a flush.

  int32_t result = graphics_.Flush(
      callback_factory_.NewCallback(&PaintManager::OnFlushComplete));

  // If you trigger this assertion, then your plugin has called Flush()
  // manually. When using the PaintManager, you should not call Flush, it will
  // handle that for you because it needs to know when it can do the next paint
  // by implementing the flush callback.
  //
  // Another possible cause of this assertion is re-using devices. If you
  // use one device, swap it with another, then swap it back, we won't know
  // that we've already scheduled a Flush on the first device. It's best to not
  // re-use devices in this way.
  PP_DCHECK(result != PP_ERROR_INPROGRESS);

  if (result == PP_ERROR_WOULDBLOCK) {
    flush_pending_ = true;
  } else {
    PP_DCHECK(result == PP_OK);  // Catch all other errors in debug mode.
  }
}

void PaintManager::OnFlushComplete(int32_t) {
  PP_DCHECK(flush_pending_);
  flush_pending_ = false;

  // If more paints were enqueued while we were waiting for the flush to
  // complete, execute them now.
  if (aggregator_.HasPendingUpdate())
    DoPaint();
}

void PaintManager::OnManualCallbackComplete(int32_t) {
  PP_DCHECK(manual_callback_pending_);
  manual_callback_pending_ = false;

  // Just because we have a manual callback doesn't mean there are actually any
  // invalid regions. Even though we only schedule this callback when something
  // is pending, a Flush callback could have come in before this callback was
  // executed and that could have cleared the queue.
  if (aggregator_.HasPendingUpdate())
    DoPaint();
}

}  // namespace pp
<commit_msg>Fix some bugs in paint manager. Some of the class members were not getting initialized in the constructor.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ppapi/cpp/paint_manager.h"

#include "ppapi/c/pp_errors.h"
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/logging.h"
#include "ppapi/cpp/module.h"

namespace pp {

PaintManager::PaintManager()
    : instance_(NULL),
      client_(NULL),
      is_always_opaque_(false),
      callback_factory_(NULL),
      manual_callback_pending_(false),
      flush_pending_(false) {
  // Set the callback object outside of the initializer list to avoid a
  // compiler warning about using "this" in an initializer list.
  callback_factory_.Initialize(this);
}

PaintManager::PaintManager(Instance* instance,
                           Client* client,
                           bool is_always_opaque)
    : instance_(instance),
      client_(client),
      is_always_opaque_(is_always_opaque),
      callback_factory_(NULL),
      manual_callback_pending_(false),
      flush_pending_(false) {
  // Set the callback object outside of the initializer list to avoid a
  // compiler warning about using "this" in an initializer list.
  callback_factory_.Initialize(this);

  // You can not use a NULL client pointer.
  PP_DCHECK(client);
}

PaintManager::~PaintManager() {
}

void PaintManager::Initialize(Instance* instance,
                              Client* client,
                              bool is_always_opaque) {
  PP_DCHECK(!instance_ && !client_);  // Can't initialize twice.
  instance_ = instance;
  client_ = client;
  is_always_opaque_ = is_always_opaque;
}

void PaintManager::SetSize(const Size& new_size) {
  if (new_size == graphics_.size())
    return;

  graphics_ = Graphics2D(new_size, is_always_opaque_);
  if (graphics_.is_null())
    return;
  instance_->BindGraphics(graphics_);

  manual_callback_pending_ = false;
  flush_pending_ = false;
  callback_factory_.CancelAll();

  Invalidate();
}

void PaintManager::Invalidate() {
  // You must call SetDevice before using.
  PP_DCHECK(!graphics_.is_null());

  EnsureCallbackPending();
  aggregator_.InvalidateRect(Rect(graphics_.size()));
}

void PaintManager::InvalidateRect(const Rect& rect) {
  // You must call SetDevice before using.
  PP_DCHECK(!graphics_.is_null());

  // Clip the rect to the device area.
  Rect clipped_rect = rect.Intersect(Rect(graphics_.size()));
  if (clipped_rect.IsEmpty())
    return;  // Nothing to do.

  EnsureCallbackPending();
  aggregator_.InvalidateRect(clipped_rect);
}

void PaintManager::ScrollRect(const Rect& clip_rect, const Point& amount) {
  // You must call SetDevice before using.
  PP_DCHECK(!graphics_.is_null());

  EnsureCallbackPending();
  aggregator_.ScrollRect(clip_rect, amount);
}

void PaintManager::EnsureCallbackPending() {
  // The best way for us to do the next update is to get a notification that
  // a previous one has completed. So if we're already waiting for one, we
  // don't have to do anything differently now.
  if (flush_pending_)
    return;

  // If no flush is pending, we need to do a manual call to get back to the
  // main thread. We may have one already pending, or we may need to schedule.
  if (manual_callback_pending_)
    return;

  Module::Get()->core()->CallOnMainThread(
      0,
      callback_factory_.NewCallback(&PaintManager::OnManualCallbackComplete),
      0);
  manual_callback_pending_ = true;
}

void PaintManager::DoPaint() {
  PP_DCHECK(aggregator_.HasPendingUpdate());

  // Make a copy of the pending update and clear the pending update flag before
  // actually painting. A plugin might cause invalidates in its Paint code, and
  // we want those to go to the *next* paint.
  PaintAggregator::PaintUpdate update = aggregator_.GetPendingUpdate();
  aggregator_.ClearPendingUpdate();

  // Apply any scroll before asking the client to paint.
  if (update.has_scroll)
    graphics_.Scroll(update.scroll_rect, update.scroll_delta);

  if (!client_->OnPaint(graphics_, update.paint_rects, update.paint_bounds))
    return;  // Nothing was painted, don't schedule a flush.

  int32_t result = graphics_.Flush(
      callback_factory_.NewCallback(&PaintManager::OnFlushComplete));

  // If you trigger this assertion, then your plugin has called Flush()
  // manually. When using the PaintManager, you should not call Flush, it will
  // handle that for you because it needs to know when it can do the next paint
  // by implementing the flush callback.
  //
  // Another possible cause of this assertion is re-using devices. If you
  // use one device, swap it with another, then swap it back, we won't know
  // that we've already scheduled a Flush on the first device. It's best to not
  // re-use devices in this way.
  PP_DCHECK(result != PP_ERROR_INPROGRESS);

  if (result == PP_ERROR_WOULDBLOCK) {
    flush_pending_ = true;
  } else {
    PP_DCHECK(result == PP_OK);  // Catch all other errors in debug mode.
  }
}

void PaintManager::OnFlushComplete(int32_t) {
  PP_DCHECK(flush_pending_);
  flush_pending_ = false;

  // If more paints were enqueued while we were waiting for the flush to
  // complete, execute them now.
  if (aggregator_.HasPendingUpdate())
    DoPaint();
}

void PaintManager::OnManualCallbackComplete(int32_t) {
  PP_DCHECK(manual_callback_pending_);
  manual_callback_pending_ = false;

  // Just because we have a manual callback doesn't mean there are actually any
  // invalid regions. Even though we only schedule this callback when something
  // is pending, a Flush callback could have come in before this callback was
  // executed and that could have cleared the queue.
  if (aggregator_.HasPendingUpdate() && !flush_pending_)
    DoPaint();
}

}  // namespace pp
<|endoftext|>


<commit_before>#include "main.hpp"

int main()
{
	std::ofstream out("log.txt");
	std::streambuf *coutbuf = std::cout.rdbuf();
	std::cout.rdbuf(out.rdbuf());

	fn::Coord::width = 800; fn::Coord::height = 600;
	fn::Coord::baseWidth = 800; fn::Coord::baseHeight = 600;
	sf::RenderWindow window(sf::VideoMode(800, 600), "", sf::Style::None);
	window.setMouseCursorVisible(false);
	sf::RectangleShape windowBorder(sf::Vector2f(798, 598));
	windowBorder.setPosition(1, 1); windowBorder.setFillColor(sf::Color(40, 40, 40)); windowBorder.setOutlineColor(sf::Color::White); windowBorder.setOutlineThickness(1);
	sf::Vertex linetop[] = { sf::Vertex(sf::Vector2f(0, 60)), sf::Vertex(sf::Vector2f(800, 60)) };
	sf::Vertex linemiddle[] = { sf::Vertex(sf::Vector2f(0, 450)), sf::Vertex(sf::Vector2f(800, 450)) };
	sf::Vertex linebottom[] = { sf::Vertex(sf::Vector2f(0, 550)), sf::Vertex(sf::Vector2f(800, 550)) };

	sf::Event sfevent;
	GUI::Container gui(&sfevent, &window, 800, 600);
	GUI::WidgetContainer* mainContainer = gui.createWidgetContainer("main", 1, 0, 0, 800, 600, GUI::ContainerMovement::Fixed, 0, 0);
	GUI::WidgetContainer* infoContainer = gui.createWidgetContainer("info", 1, 0, 60, 800, 390, GUI::ContainerMovement::Fixed, 0, 0);
	GUI::WidgetContainer* stgsContainer = gui.createWidgetContainer("stgs", 1, 0, 60, 800, 390, GUI::ContainerMovement::Fixed, 0, 0);
	GUI::WidgetContainer* logsContainer = gui.createWidgetContainer("logs", 1, 0, 450, 800, 100, GUI::ContainerMovement::Fixed, 0, 0);

	Cursor curs;
	curs.initialize(&window);

	sf::Font font;
	font.loadFromFile("Data/Fonts/weblysleekuil.ttf");

	//Main UI
	gui.createLabel("main", "titleLbl", 10, 10, "Melting Saga Updater", "weblysleekuil.ttf", 32, sf::Color::White);
	gui.createLabel("main", "updaterVerLbl", 400, 10, "Updater : <Nightly> v1.0.5", "weblysleekuil.ttf", 12, sf::Color::White);
	gui.createLabel("main", "updaterVerLbl", 400, 30, "Game : <Nightly> v0.0.1", "weblysleekuil.ttf", 12, sf::Color::White);
	gui.createCheckbox("main", "settingsBtn", 700, 15, "SETTINGS", false);
	gui.createButton("main", "quitBtn", 750, 15, true, true, "QUIT");
	gui.createButton("main", "updateBtn", 600, 560, true, true, "GREY");
	gui.createLoadingBar("main", "updateBar", 10, 560, "UPDATER");
	gui.createLabel("main", "updateBarLbl", 300, 560, "80%", "weblysleekuil.ttf", 24, sf::Color::White);

	//Infos UI
	gui.createLabel("info", "updateInfosTitleLbl", 10, 10, "Update Informations : ", "weblysleekuil.ttf", 24, sf::Color::Cyan);
	gui.createLabel("info", "updateInfosContLbl", 30, 45, "", "weblysleekuil.ttf", 16, sf::Color::White);
	std::ifstream changelogFile("changelog.txt");
	std::string updateContent((std::istreambuf_iterator<char>(changelogFile)),
		std::istreambuf_iterator<char>());
	GUI::Widget::getWidgetByID<GUI::Label>("updateInfosContLbl")->setComplexText(updateContent);
	infoContainer->addScrollBar();
	gui.createScrollBar("info", "updateScrollBar", 790, 0, 400, 50, false, infoContainer, "V2");
	GUI::Widget::getWidgetByID<GUI::ScrollBar>("updateScrollBar")->computeDynamicScroll();

	//Settings UI
	gui.createLabel("stgs", "settingsTitleLbl", 10, 10, "Settings : ", "weblysleekuil.ttf", 24, sf::Color::Cyan);

	//Logs UI
	gui.createLabel("logs", "logsTitleLbl", 10, 10, "Logs : ", "weblysleekuil.ttf", 24, sf::Color::Cyan);
	gui.createLabel("logs", "logsContLbl", 10, 45, "lolibork", "weblysleekuil.ttf", 16, sf::Color::White);
	GUI::Widget::getWidgetByID<GUI::Label>("logsContLbl")->setComplexText("<color:255,255,255>Connection to MeSa Server : 132.14.88.22:9022 [ "
		"<color:0,255,0>Done"
		"<color:255,255,255> ]\n"
		"GET : changelog.txt 200 OK [ "
		"<color:0,255,0>Done"
		"<color:255,255,255> ]\n");

	GUI::ButtonEvent* appQuitBool = GUI::Widget::getWidgetByID<GUI::Button>("quitBtn")->getHook();
	bool* appSettingsBool = GUI::Widget::getWidgetByID<GUI::Checkbox>("settingsBtn")->getHook();
	GUI::Widget::getWidgetByID<GUI::Button>("updateBtn")->setText("Update", "weblysleekuil.ttf", sf::Color::White, 18, true, 0, -3);
	GUI::Widget::getWidgetByID<GUI::LoadingBar>("updateBar")->fill(80, 2);
	sf::Vector2i grabbedOffset;

	bool grabbedWindow = false;
	while (window.isOpen())
	{
		while (window.pollEvent(sfevent))
		{
			if (sfevent.type == sf::Event::Closed)
				window.close();
			else if (sfevent.type == sf::Event::KeyPressed)
			{
				if (sfevent.key.code == sf::Keyboard::Escape)
					window.close();
			}
			else if (sfevent.type == sf::Event::MouseButtonPressed)
			{
				if (sf::Mouse::getPosition().y - window.getPosition().y < 60 && sf::Mouse::getPosition().x - window.getPosition().x < 680)
				{
					if (sfevent.mouseButton.button == sf::Mouse::Left)
					{
						grabbedOffset = window.getPosition() - sf::Mouse::getPosition();
						grabbedWindow = true;
					}
				}
			}
			else if (sfevent.type == sf::Event::MouseButtonReleased)
			{
				if (sfevent.mouseButton.button == sf::Mouse::Left)
					grabbedWindow = false;
			}
			else if (sfevent.type == sf::Event::MouseMoved)
			{
				if (grabbedWindow)
					window.setPosition(sf::Mouse::getPosition() + grabbedOffset);
			}
		}

		gui.updateAllContainer();
		curs.update();
		if (*appQuitBool == GUI::ButtonEvent::Pressed) {window.close();}
		if (*appSettingsBool) { gui.getContainerByContainerName("info")->setDisplayed(false); gui.getContainerByContainerName("stgs")->setDisplayed(true); }
		else { gui.getContainerByContainerName("info")->setDisplayed(true); gui.getContainerByContainerName("stgs")->setDisplayed(false); }

		window.clear(sf::Color(40, 40, 40));
		window.draw(windowBorder);
		gui.drawAllContainer(&window);
		window.draw(linetop, 2, sf::Lines); window.draw(linemiddle, 2, sf::Lines); window.draw(linebottom, 2, sf::Lines);
		window.draw(*curs.getSprite());
		window.display();
	}
}<commit_msg>Removed double scrollbar<commit_after>#include "main.hpp"

int main()
{
	std::ofstream out("log.txt");
	std::streambuf *coutbuf = std::cout.rdbuf();
	std::cout.rdbuf(out.rdbuf());

	fn::Coord::width = 800; fn::Coord::height = 600;
	fn::Coord::baseWidth = 800; fn::Coord::baseHeight = 600;
	sf::RenderWindow window(sf::VideoMode(800, 600), "", sf::Style::None);
	window.setMouseCursorVisible(false);
	sf::RectangleShape windowBorder(sf::Vector2f(798, 598));
	windowBorder.setPosition(1, 1); windowBorder.setFillColor(sf::Color(40, 40, 40)); windowBorder.setOutlineColor(sf::Color::White); windowBorder.setOutlineThickness(1);
	sf::Vertex linetop[] = { sf::Vertex(sf::Vector2f(0, 60)), sf::Vertex(sf::Vector2f(800, 60)) };
	sf::Vertex linemiddle[] = { sf::Vertex(sf::Vector2f(0, 450)), sf::Vertex(sf::Vector2f(800, 450)) };
	sf::Vertex linebottom[] = { sf::Vertex(sf::Vector2f(0, 550)), sf::Vertex(sf::Vector2f(800, 550)) };

	sf::Event sfevent;
	GUI::Container gui(&sfevent, &window, 800, 600);
	GUI::WidgetContainer* mainContainer = gui.createWidgetContainer("main", 1, 0, 0, 800, 600, GUI::ContainerMovement::Fixed, 0, 0);
	GUI::WidgetContainer* infoContainer = gui.createWidgetContainer("info", 1, 0, 60, 800, 390, GUI::ContainerMovement::Fixed, 0, 0);
	GUI::WidgetContainer* stgsContainer = gui.createWidgetContainer("stgs", 1, 0, 60, 800, 390, GUI::ContainerMovement::Fixed, 0, 0);
	GUI::WidgetContainer* logsContainer = gui.createWidgetContainer("logs", 1, 0, 450, 800, 100, GUI::ContainerMovement::Fixed, 0, 0);

	Cursor curs;
	curs.initialize(&window);

	sf::Font font;
	font.loadFromFile("Data/Fonts/weblysleekuil.ttf");

	//Main UI
	gui.createLabel("main", "titleLbl", 10, 10, "Melting Saga Updater", "weblysleekuil.ttf", 32, sf::Color::White);
	gui.createLabel("main", "updaterVerLbl", 400, 10, "Updater : <Nightly> v1.0.5", "weblysleekuil.ttf", 12, sf::Color::White);
	gui.createLabel("main", "updaterVerLbl", 400, 30, "Game : <Nightly> v0.0.1", "weblysleekuil.ttf", 12, sf::Color::White);
	gui.createCheckbox("main", "settingsBtn", 700, 15, "SETTINGS", false);
	gui.createButton("main", "quitBtn", 750, 15, true, true, "QUIT");
	gui.createButton("main", "updateBtn", 600, 560, true, true, "GREY");
	gui.createLoadingBar("main", "updateBar", 10, 560, "UPDATER");
	gui.createLabel("main", "updateBarLbl", 300, 560, "80%", "weblysleekuil.ttf", 24, sf::Color::White);

	//Infos UI
	gui.createLabel("info", "updateInfosTitleLbl", 10, 10, "Update Informations : ", "weblysleekuil.ttf", 24, sf::Color::Cyan);
	gui.createLabel("info", "updateInfosContLbl", 30, 45, "", "weblysleekuil.ttf", 16, sf::Color::White);
	std::ifstream changelogFile("changelog.txt");
	std::string updateContent((std::istreambuf_iterator<char>(changelogFile)),
		std::istreambuf_iterator<char>());
	GUI::Widget::getWidgetByID<GUI::Label>("updateInfosContLbl")->setComplexText(updateContent);
	infoContainer->addScrollBar();

	//Settings UI
	gui.createLabel("stgs", "settingsTitleLbl", 10, 10, "Settings : ", "weblysleekuil.ttf", 24, sf::Color::Cyan);

	//Logs UI
	gui.createLabel("logs", "logsTitleLbl", 10, 10, "Logs : ", "weblysleekuil.ttf", 24, sf::Color::Cyan);
	gui.createLabel("logs", "logsContLbl", 10, 45, "lolibork", "weblysleekuil.ttf", 16, sf::Color::White);
	GUI::Widget::getWidgetByID<GUI::Label>("logsContLbl")->setComplexText("<color:255,255,255>Connection to MeSa Server : 132.14.88.22:9022 [ "
		"<color:0,255,0>Done"
		"<color:255,255,255> ]\n"
		"GET : changelog.txt 200 OK [ "
		"<color:0,255,0>Done"
		"<color:255,255,255> ]\n");

	GUI::ButtonEvent* appQuitBool = GUI::Widget::getWidgetByID<GUI::Button>("quitBtn")->getHook();
	bool* appSettingsBool = GUI::Widget::getWidgetByID<GUI::Checkbox>("settingsBtn")->getHook();
	GUI::Widget::getWidgetByID<GUI::Button>("updateBtn")->setText("Update", "weblysleekuil.ttf", sf::Color::White, 18, true, 0, -3);
	GUI::Widget::getWidgetByID<GUI::LoadingBar>("updateBar")->fill(80, 2);
	sf::Vector2i grabbedOffset;

	bool grabbedWindow = false;
	while (window.isOpen())
	{
		while (window.pollEvent(sfevent))
		{
			if (sfevent.type == sf::Event::Closed)
				window.close();
			else if (sfevent.type == sf::Event::KeyPressed)
			{
				if (sfevent.key.code == sf::Keyboard::Escape)
					window.close();
			}
			else if (sfevent.type == sf::Event::MouseButtonPressed)
			{
				if (sf::Mouse::getPosition().y - window.getPosition().y < 60 && sf::Mouse::getPosition().x - window.getPosition().x < 680)
				{
					if (sfevent.mouseButton.button == sf::Mouse::Left)
					{
						grabbedOffset = window.getPosition() - sf::Mouse::getPosition();
						grabbedWindow = true;
					}
				}
			}
			else if (sfevent.type == sf::Event::MouseButtonReleased)
			{
				if (sfevent.mouseButton.button == sf::Mouse::Left)
					grabbedWindow = false;
			}
			else if (sfevent.type == sf::Event::MouseMoved)
			{
				if (grabbedWindow)
					window.setPosition(sf::Mouse::getPosition() + grabbedOffset);
			}
		}

		gui.updateAllContainer();
		curs.update();
		if (*appQuitBool == GUI::ButtonEvent::Pressed) {window.close();}
		if (*appSettingsBool) { gui.getContainerByContainerName("info")->setDisplayed(false); gui.getContainerByContainerName("stgs")->setDisplayed(true); }
		else { gui.getContainerByContainerName("info")->setDisplayed(true); gui.getContainerByContainerName("stgs")->setDisplayed(false); }

		window.clear(sf::Color(40, 40, 40));
		window.draw(windowBorder);
		gui.drawAllContainer(&window);
		window.draw(linetop, 2, sf::Lines); window.draw(linemiddle, 2, sf::Lines); window.draw(linebottom, 2, sf::Lines);
		window.draw(*curs.getSprite());
		window.display();
	}
}<|endoftext|>


<commit_before>/*
 * This is part of the FL library, a C++ Bayesian filtering library
 * (https://github.com/filtering-library)
 *
 * Copyright (c) 2014 Jan Issac (jan.issac@gmail.com)
 * Copyright (c) 2014 Manuel Wuthrich (manuel.wuthrich@gmail.com)
 *
 * Max-Planck Institute for Intelligent Systems, AMD Lab
 * University of Southern California, CLMC Lab
 *
 * This Source Code Form is subject to the terms of the MIT License (MIT).
 * A copy of the license can be found in the LICENSE file distributed with this
 * source code.
 */

/**
 * \file linear_decorrelated_gaussian_observation_model.hpp
 * \date October 2014
 * \author Jan Issac (jan.issac@gmail.com)
 */

#ifndef FL__MODEL__OBSERVATION__LINEAR_DECORRELATED_GAUSSIAN_OBSERVATION_MODEL_HPP
#define FL__MODEL__OBSERVATION__LINEAR_DECORRELATED_GAUSSIAN_OBSERVATION_MODEL_HPP

#include <fl/util/traits.hpp>
#include <fl/util/types.hpp>
#include <fl/util/descriptor.hpp>
#include <fl/distribution/decorrelated_gaussian.hpp>
#include <fl/model/observation/linear_observation_model.hpp>
#include <fl/model/observation/interface/additive_uncorrelated_observation_function.hpp>

namespace fl
{

/**
 * \ingroup observation_models
 */
template <typename Obsrv, typename State>
class LinearDecorrelatedGaussianObservationModel
    : public AdditiveUncorrelatedNoiseModel<DecorrelatedGaussian<Obsrv>>,
      public AdditiveObservationFunction<Obsrv, State, Gaussian<Obsrv>>,
      public Descriptor,
      private internal::LinearModelType
{
public:
    // specify the main type of this model
    typedef internal::AdditiveUncorrelatedNoiseModelType Type;

    typedef AdditiveUncorrelatedNoiseModel<
                DecorrelatedGaussian<Obsrv>
            > AdditiveUncorrelatedInterface;

    typedef AdditiveObservationFunction<
                Obsrv, State, Gaussian<Obsrv>
            > AdditiveObservationFunctionInterface;

    typedef
    typename AdditiveObservationFunctionInterface::NoiseMatrix NoiseMatrix;

    typedef
    typename AdditiveUncorrelatedInterface::NoiseMatrix NoiseDiagonalMatrix;

    /**
     * Observation model sensor matrix \f$H_t\f$ use in
     *
     * \f$ y_t  = H_t x_t + N_t v_t \f$
     */
    typedef Eigen::Matrix<
                typename State::Scalar,
                SizeOf<Obsrv>::Value,
                SizeOf<State>::Value
            > SensorMatrix;

    /**
     * Constructs a linear gaussian observation model
     *
     * \param obsrv_dim     observation dimension if dynamic size
     * \param state_dim     state dimension if dynamic size
     */
    explicit
    LinearDecorrelatedGaussianObservationModel(
        int obsrv_dim = DimensionOf<Obsrv>(),
        int state_dim = DimensionOf<State>())
        : sensor_matrix_(SensorMatrix::Identity(obsrv_dim, state_dim)),
          density_(obsrv_dim)
    {
        assert(obsrv_dim > 0);
        assert(state_dim > 0);
    }

    /**
     * \brief Overridable default destructor
     */
    virtual ~LinearDecorrelatedGaussianObservationModel() { }

    virtual NoiseDiagonalMatrix noise_matrix_diagonal() const
    {
        return density_.square_root();
    }

    virtual NoiseDiagonalMatrix noise_covariance_diagonal() const
    {
        return density_.covariance();
    }

    /**
     * \brief expected_observation
     * \param state
     * \return
     */
    Obsrv expected_observation(const State& state) const override
    {
        return sensor_matrix_ * state;
    }

    Real log_probability(const Obsrv& obsrv, const State& state) const
    {
        density_.mean(expected_observation(state));

        return density_.log_probability(obsrv);
    }

    const SensorMatrix& sensor_matrix() const override
    {
        return sensor_matrix_;
    }

    NoiseMatrix noise_matrix() const override
    {
        return density_.square_root();
    }

    NoiseMatrix noise_covariance() const override
    {
        return density_.covariance();
    }

    int obsrv_dimension() const override
    {
        return sensor_matrix_.rows();
    }

    int noise_dimension() const override
    {
        return density_.square_root().cols();
    }

    int state_dimension() const override
    {
        return sensor_matrix_.cols();
    }

    virtual void sensor_matrix(const SensorMatrix& sensor_mat)
    {
        sensor_matrix_ = sensor_mat;
    }

    virtual void noise_matrix(const NoiseMatrix& noise_mat)
    {
        density_.square_root(noise_mat.diagonal().asDiagonal());
    }

    virtual void noise_covariance(const NoiseMatrix& noise_mat_squared)
    {
        density_.covariance(noise_mat_squared.diagonal().asDiagonal());
    }

    virtual void noise_matrix_diagonal(
        const NoiseDiagonalMatrix& noise_mat)
    {
        density_.square_root(noise_mat);
    }

    virtual void noise_covariance_diagonal(
        const NoiseDiagonalMatrix& noise_mat_squared)
    {
        density_.covariance(noise_mat_squared);
    }

    virtual SensorMatrix create_sensor_matrix() const
    {
        auto H = sensor_matrix();
        H.setIdentity();
        return H;
    }

    virtual NoiseMatrix create_noise_matrix() const
    {
        auto N = noise_matrix();
        N.setIdentity();
        return N;
    }

    virtual std::string name() const
    {
        return "LinearDecorrelatedGaussianObservationModel";
    }

    virtual std::string description() const
    {
        return "Linear observation model with additive decorrelated Gaussian "
               "noise";
    }

private:
    SensorMatrix sensor_matrix_;
    mutable DecorrelatedGaussian<Obsrv> density_;
};

}

#endif
<commit_msg>added diagonal matrix factory functions<commit_after>/*
 * This is part of the FL library, a C++ Bayesian filtering library
 * (https://github.com/filtering-library)
 *
 * Copyright (c) 2014 Jan Issac (jan.issac@gmail.com)
 * Copyright (c) 2014 Manuel Wuthrich (manuel.wuthrich@gmail.com)
 *
 * Max-Planck Institute for Intelligent Systems, AMD Lab
 * University of Southern California, CLMC Lab
 *
 * This Source Code Form is subject to the terms of the MIT License (MIT).
 * A copy of the license can be found in the LICENSE file distributed with this
 * source code.
 */

/**
 * \file linear_decorrelated_gaussian_observation_model.hpp
 * \date October 2014
 * \author Jan Issac (jan.issac@gmail.com)
 */

#ifndef FL__MODEL__OBSERVATION__LINEAR_DECORRELATED_GAUSSIAN_OBSERVATION_MODEL_HPP
#define FL__MODEL__OBSERVATION__LINEAR_DECORRELATED_GAUSSIAN_OBSERVATION_MODEL_HPP

#include <fl/util/traits.hpp>
#include <fl/util/types.hpp>
#include <fl/util/descriptor.hpp>
#include <fl/distribution/decorrelated_gaussian.hpp>
#include <fl/model/observation/linear_observation_model.hpp>
#include <fl/model/observation/interface/additive_uncorrelated_observation_function.hpp>

namespace fl
{

/**
 * \ingroup observation_models
 */
template <typename Obsrv, typename State>
class LinearDecorrelatedGaussianObservationModel
    : public AdditiveUncorrelatedNoiseModel<DecorrelatedGaussian<Obsrv>>,
      public AdditiveObservationFunction<Obsrv, State, Gaussian<Obsrv>>,
      public Descriptor,
      private internal::LinearModelType
{
public:
    // specify the main type of this model
    typedef internal::AdditiveUncorrelatedNoiseModelType Type;

    typedef AdditiveUncorrelatedNoiseModel<
                DecorrelatedGaussian<Obsrv>
            > AdditiveUncorrelatedInterface;

    typedef AdditiveObservationFunction<
                Obsrv, State, Gaussian<Obsrv>
            > AdditiveObservationFunctionInterface;

    typedef
    typename AdditiveObservationFunctionInterface::NoiseMatrix NoiseMatrix;

    typedef
    typename AdditiveUncorrelatedInterface::NoiseMatrix NoiseDiagonalMatrix;

    /**
     * Observation model sensor matrix \f$H_t\f$ use in
     *
     * \f$ y_t  = H_t x_t + N_t v_t \f$
     */
    typedef Eigen::Matrix<
                typename State::Scalar,
                SizeOf<Obsrv>::Value,
                SizeOf<State>::Value
            > SensorMatrix;

    /**
     * Constructs a linear gaussian observation model
     *
     * \param obsrv_dim     observation dimension if dynamic size
     * \param state_dim     state dimension if dynamic size
     */
    explicit
    LinearDecorrelatedGaussianObservationModel(
        int obsrv_dim = DimensionOf<Obsrv>(),
        int state_dim = DimensionOf<State>())
        : sensor_matrix_(SensorMatrix::Identity(obsrv_dim, state_dim)),
          density_(obsrv_dim)
    {
        assert(obsrv_dim > 0);
        assert(state_dim > 0);
    }

    /**
     * \brief Overridable default destructor
     */
    virtual ~LinearDecorrelatedGaussianObservationModel() { }

    /**
     * \brief expected_observation
     * \param state
     * \return
     */
    Obsrv expected_observation(const State& state) const override
    {
        return sensor_matrix_ * state;
    }

    Real log_probability(const Obsrv& obsrv, const State& state) const
    {
        density_.mean(expected_observation(state));

        return density_.log_probability(obsrv);
    }

    const SensorMatrix& sensor_matrix() const override
    {
        return sensor_matrix_;
    }

    NoiseMatrix noise_matrix() const override
    {
        return density_.square_root();
    }

    NoiseMatrix noise_covariance() const override
    {
        return density_.covariance();
    }

    virtual NoiseDiagonalMatrix noise_diagonal_matrix() const
    {
        return density_.square_root();
    }

    virtual NoiseDiagonalMatrix noise_diagonal_covariance() const
    {
        return density_.covariance();
    }

    int obsrv_dimension() const override
    {
        return sensor_matrix_.rows();
    }

    int noise_dimension() const override
    {
        return density_.square_root().cols();
    }

    int state_dimension() const override
    {
        return sensor_matrix_.cols();
    }

    virtual void sensor_matrix(const SensorMatrix& sensor_mat)
    {
        sensor_matrix_ = sensor_mat;
    }

    virtual void noise_matrix(const NoiseMatrix& noise_mat)
    {
        density_.square_root(noise_mat.diagonal().asDiagonal());
    }

    virtual void noise_covariance(const NoiseMatrix& noise_mat_squared)
    {
        density_.covariance(noise_mat_squared.diagonal().asDiagonal());
    }

    virtual void noise_diagonal_matrix(
        const NoiseDiagonalMatrix& noise_mat)
    {
        density_.square_root(noise_mat);
    }

    virtual void noise_diagonal_covariance(
        const NoiseDiagonalMatrix& noise_mat_squared)
    {
        density_.covariance(noise_mat_squared);
    }

    virtual SensorMatrix create_sensor_matrix() const
    {
        auto H = sensor_matrix();
        H.setIdentity();
        return H;
    }

    virtual NoiseMatrix create_noise_matrix() const
    {
        auto N = noise_matrix();
        N.setIdentity();
        return N;
    }

    virtual NoiseMatrix create_noise_covariance() const
    {
        auto C = noise_covariance();
        C.setIdentity();
        return C;
    }

    virtual NoiseMatrix create_noise_diagonal_matrix() const
    {
        auto N = noise_diagonal_matrix();
        N.setIdentity();
        return N;
    }

    virtual NoiseMatrix create_noise_diagonal_covariance() const
    {
        auto C = noise_diagonal_covariance();
        C.setIdentity();
        return C;
    }

    virtual std::string name() const
    {
        return "LinearDecorrelatedGaussianObservationModel";
    }

    virtual std::string description() const
    {
        return "Linear observation model with additive decorrelated Gaussian "
               "noise";
    }

private:
    SensorMatrix sensor_matrix_;
    mutable DecorrelatedGaussian<Obsrv> density_;
};

}

#endif
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** No Commercial Usage
**
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "s60runcontrolfactory.h"

#include "codaruncontrol.h"
#include "s60devicerunconfiguration.h"
#include "s60deployconfiguration.h"
#include "trkruncontrol.h"
#include "qt4symbiantarget.h"

#include <utils/qtcassert.h>

using namespace ProjectExplorer;
using namespace Qt4ProjectManager;
using namespace Qt4ProjectManager::Internal;

S60RunControlFactory::S60RunControlFactory(const QString &mode,
                                           const QString &name,
                                           QObject *parent) :
    IRunControlFactory(parent), m_mode(mode), m_name(name)
{
}

bool S60RunControlFactory::canRun(RunConfiguration *runConfiguration, const QString &mode) const
{
    if (mode != m_mode)
        return false;
    S60DeviceRunConfiguration *rc = qobject_cast<S60DeviceRunConfiguration *>(runConfiguration);
    if (!rc)
        return false;
    S60DeployConfiguration *activeDeployConf = qobject_cast<S60DeployConfiguration *>(rc->qt4Target()->activeDeployConfiguration());
    return activeDeployConf != 0;
}

RunControl* S60RunControlFactory::create(RunConfiguration *runConfiguration, const QString &mode)
{
    S60DeviceRunConfiguration *rc = qobject_cast<S60DeviceRunConfiguration *>(runConfiguration);

    QTC_ASSERT(rc, return 0);
    QTC_ASSERT(mode == m_mode, return 0);

    S60DeployConfiguration *activeDeployConf = qobject_cast<S60DeployConfiguration *>(rc->qt4Target()->activeDeployConfiguration());
    if (!activeDeployConf)
        return 0;

    if (activeDeployConf->communicationChannel() == S60DeployConfiguration::CommunicationTrkSerialConnection)
        return new TrkRunControl(rc, mode);
    return new CodaRunControl(rc, mode);
}

QString S60RunControlFactory::displayName() const
{
    return m_name;
}

RunConfigWidget *S60RunControlFactory::createConfigurationWidget(RunConfiguration* runConfiguration /*S60DeviceRunConfiguration */)
{
    return 0;
}
<commit_msg>Fixed 'unused' warning<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** No Commercial Usage
**
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "s60runcontrolfactory.h"

#include "codaruncontrol.h"
#include "s60devicerunconfiguration.h"
#include "s60deployconfiguration.h"
#include "trkruncontrol.h"
#include "qt4symbiantarget.h"

#include <utils/qtcassert.h>

using namespace ProjectExplorer;
using namespace Qt4ProjectManager;
using namespace Qt4ProjectManager::Internal;

S60RunControlFactory::S60RunControlFactory(const QString &mode,
                                           const QString &name,
                                           QObject *parent) :
    IRunControlFactory(parent), m_mode(mode), m_name(name)
{
}

bool S60RunControlFactory::canRun(RunConfiguration *runConfiguration, const QString &mode) const
{
    if (mode != m_mode)
        return false;
    S60DeviceRunConfiguration *rc = qobject_cast<S60DeviceRunConfiguration *>(runConfiguration);
    if (!rc)
        return false;
    S60DeployConfiguration *activeDeployConf = qobject_cast<S60DeployConfiguration *>(rc->qt4Target()->activeDeployConfiguration());
    return activeDeployConf != 0;
}

RunControl* S60RunControlFactory::create(RunConfiguration *runConfiguration, const QString &mode)
{
    S60DeviceRunConfiguration *rc = qobject_cast<S60DeviceRunConfiguration *>(runConfiguration);

    QTC_ASSERT(rc, return 0);
    QTC_ASSERT(mode == m_mode, return 0);

    S60DeployConfiguration *activeDeployConf = qobject_cast<S60DeployConfiguration *>(rc->qt4Target()->activeDeployConfiguration());
    if (!activeDeployConf)
        return 0;

    if (activeDeployConf->communicationChannel() == S60DeployConfiguration::CommunicationTrkSerialConnection)
        return new TrkRunControl(rc, mode);
    return new CodaRunControl(rc, mode);
}

QString S60RunControlFactory::displayName() const
{
    return m_name;
}

QWidget *S60RunControlFactory::createConfigurationWidget(RunConfiguration *runConfiguration)
{
    Q_UNUSED(runConfiguration);
    return 0;
}
<|endoftext|>


<commit_before>#ifndef __STAN__PROB__DISTRIBUTIONS__UNIVARIATE__CONTINUOUS__UNIFORM_HPP__
#define __STAN__PROB__DISTRIBUTIONS__UNIVARIATE__CONTINUOUS__UNIFORM_HPP__

#include <stan/agrad.hpp>
#include <stan/math/error_handling.hpp>
#include <stan/math/special_functions.hpp>
#include <stan/meta/traits.hpp>
#include <stan/prob/constants.hpp>
#include <stan/prob/traits.hpp>

namespace stan {

  namespace prob {

    // CONTINUOUS, UNIVARIATE DENSITIES
    /**
     * The log of a uniform density for the given
     * y, lower, and upper bound.
     *
     \f{eqnarray*}{
     y &\sim& \mbox{\sf{U}}(\alpha, \beta) \\
     \log (p (y \,|\, \alpha, \beta)) &=& \log \left( \frac{1}{\beta-\alpha} \right) \\
     &=& \log (1) - \log (\beta - \alpha) \\
     &=& -\log (\beta - \alpha) \\
     & & \mathrm{ where } \; y \in [\alpha, \beta], \log(0) \; \mathrm{otherwise}
     \f}
     *
     * @param y A scalar variable.
     * @param alpha Lower bound.
     * @param beta Upper bound.
     * @throw std::invalid_argument if the lower bound is greater than
     *    or equal to the lower bound
     * @tparam T_y Type of scalar.
     * @tparam T_low Type of lower bound.
     * @tparam T_high Type of upper bound.
     */
    template <bool propto,
              typename T_y, typename T_low, typename T_high,
              class Policy>
    typename return_type<T_y,T_low,T_high>::type
    uniform_log(const T_y& y, const T_low& alpha, const T_high& beta,
                const Policy&) {
      static const char* function = "stan::prob::uniform_log(%1%)";

      using stan::math::check_not_nan;
      using stan::math::check_finite;
      using stan::math::check_greater;
      using stan::math::value_of;
      using stan::math::check_consistent_sizes;

      // check if any vectors are zero length
      if (!(stan::length(y)
            && stan::length(alpha)
            && stan::length(beta)))
        return 0.0;

      // set up return value accumulator
      typename return_type<T_y,T_low,T_high>::type logp(0.0);
      if(!check_not_nan(function, y, "Random variable", &logp, Policy()))
        return logp;
      if (!check_finite(function, alpha, "Lower bound parameter", &logp, Policy()))
        return logp;
      if (!check_finite(function, beta, "Upper bound parameter", &logp, Policy()))
        return logp;
      if (!check_greater(function, beta, alpha, "Upper bound parameter",
                         &logp, Policy()))
        return logp;
      if (!(check_consistent_sizes(function,
                                   y,alpha,beta,
				   "Random variable","Lower bound parameter","Upper bound parameter",
                                   &logp, Policy())))
        return logp;

      // check if no variables are involved and prop-to
      if (!include_summand<propto,T_y,T_low,T_high>::value)
	return 0.0;

      VectorView<const T_y> y_vec(y);
      VectorView<const T_low> alpha_vec(alpha);
      VectorView<const T_high> beta_vec(beta);
      size_t N = max_size(y, alpha, beta);

      for (size_t n = 0; n < N; n++) {
	const double y_dbl = value_of(y_vec[n]);
	if (y_dbl < value_of(alpha_vec[n]) || y_dbl > value_of(beta_vec[n]))
	  return LOG_ZERO;
      }

      for (size_t n = 0; n < N; n++) {
	if (include_summand<propto,T_low,T_high>::value)
	  logp -= log(beta_vec[n] - alpha_vec[n]);
      }
      return logp;
    }

    template <bool propto,
              typename T_y, typename T_low, typename T_high>
    inline
    typename return_type<T_y,T_low,T_high>::type
    uniform_log(const T_y& y, const T_low& alpha, const T_high& beta) {
      return uniform_log<propto>(y,alpha,beta,stan::math::default_policy());
    }

    template <typename T_y, typename T_low, typename T_high,
              class Policy>
    inline
    typename return_type<T_y,T_low,T_high>::type
    uniform_log(const T_y& y, const T_low& alpha, const T_high& beta,
                const Policy&) {
      return uniform_log<false>(y,alpha,beta,Policy());
    }

    template <typename T_y, typename T_low, typename T_high>
    inline
    typename return_type<T_y,T_low,T_high>::type
    uniform_log(const T_y& y, const T_low& alpha, const T_high& beta) {
      return uniform_log<false>(y,alpha,beta,stan::math::default_policy());
    }

  }
}
#endif
<commit_msg>evaluated derivatives for uniform<commit_after>#ifndef __STAN__PROB__DISTRIBUTIONS__UNIVARIATE__CONTINUOUS__UNIFORM_HPP__
#define __STAN__PROB__DISTRIBUTIONS__UNIVARIATE__CONTINUOUS__UNIFORM_HPP__

#include <stan/agrad.hpp>
#include <stan/math/error_handling.hpp>
#include <stan/math/special_functions.hpp>
#include <stan/meta/traits.hpp>
#include <stan/prob/constants.hpp>
#include <stan/prob/traits.hpp>

namespace stan {

  namespace prob {

    // CONTINUOUS, UNIVARIATE DENSITIES
    /**
     * The log of a uniform density for the given
     * y, lower, and upper bound.
     *
     \f{eqnarray*}{
     y &\sim& \mbox{\sf{U}}(\alpha, \beta) \\
     \log (p (y \,|\, \alpha, \beta)) &=& \log \left( \frac{1}{\beta-\alpha} \right) \\
     &=& \log (1) - \log (\beta - \alpha) \\
     &=& -\log (\beta - \alpha) \\
     & & \mathrm{ where } \; y \in [\alpha, \beta], \log(0) \; \mathrm{otherwise}
     \f}
     *
     * @param y A scalar variable.
     * @param alpha Lower bound.
     * @param beta Upper bound.
     * @throw std::invalid_argument if the lower bound is greater than
     *    or equal to the lower bound
     * @tparam T_y Type of scalar.
     * @tparam T_low Type of lower bound.
     * @tparam T_high Type of upper bound.
     */
    template <bool propto,
              typename T_y, typename T_low, typename T_high,
              class Policy>
    typename return_type<T_y,T_low,T_high>::type
    uniform_log(const T_y& y, const T_low& alpha, const T_high& beta,
                const Policy&) {
      static const char* function = "stan::prob::uniform_log(%1%)";

      using stan::math::check_not_nan;
      using stan::math::check_finite;
      using stan::math::check_greater;
      using stan::math::value_of;
      using stan::math::check_consistent_sizes;

      // check if any vectors are zero length
      if (!(stan::length(y)
            && stan::length(alpha)
            && stan::length(beta)))
        return 0.0;

      // set up return value accumulator
      double logp(0.0);
      if(!check_not_nan(function, y, "Random variable", &logp, Policy()))
        return logp;
      if (!check_finite(function, alpha, "Lower bound parameter", &logp, Policy()))
        return logp;
      if (!check_finite(function, beta, "Upper bound parameter", &logp, Policy()))
        return logp;
      if (!check_greater(function, beta, alpha, "Upper bound parameter",
                         &logp, Policy()))
        return logp;
      if (!(check_consistent_sizes(function,
                                   y,alpha,beta,
				   "Random variable","Lower bound parameter","Upper bound parameter",
                                   &logp, Policy())))
        return logp;

      // check if no variables are involved and prop-to
      if (!include_summand<propto,T_y,T_low,T_high>::value)
	return 0.0;

      VectorView<const T_y> y_vec(y);
      VectorView<const T_low> alpha_vec(alpha);
      VectorView<const T_high> beta_vec(beta);
      size_t N = max_size(y, alpha, beta);

      for (size_t n = 0; n < N; n++) {
	const double y_dbl = value_of(y_vec[n]);
	if (y_dbl < value_of(alpha_vec[n]) || y_dbl > value_of(beta_vec[n]))
	  return LOG_ZERO;
      }

      DoubleVectorView<include_summand<propto,T_low,T_high>::value,
	is_vector<T_low>::value | is_vector<T_high>::value> inv_beta_minus_alpha(max_size(alpha,beta));
      for (size_t i = 0; i < max_size(alpha,beta); i++)
	if (include_summand<propto,T_low,T_high>::value)
	  inv_beta_minus_alpha[i] = 1.0 / (value_of(beta_vec[i]) - value_of(alpha_vec[i]));
      DoubleVectorView<include_summand<propto,T_low,T_high>::value,
	is_vector<T_low>::value | is_vector<T_high>::value> log_beta_minus_alpha(max_size(alpha,beta));
      for (size_t i = 0; i < max_size(alpha,beta); i++)
	if (include_summand<propto,T_low,T_high>::value)
	  log_beta_minus_alpha[i] = log(value_of(beta_vec[i]) - value_of(alpha_vec[i]));

      agrad::OperandsAndPartials<T_y,T_low,T_high> operands_and_partials(y,alpha,beta);
      for (size_t n = 0; n < N; n++) {
	if (include_summand<propto,T_low,T_high>::value)
	  logp -= log_beta_minus_alpha[n];

	if (!is_constant_struct<T_low>::value)
	  operands_and_partials.d_x2[n] += inv_beta_minus_alpha[n];
	if (!is_constant_struct<T_high>::value)
	  operands_and_partials.d_x3[n] -= inv_beta_minus_alpha[n];
      }
      return operands_and_partials.to_var(logp);
    }

    template <bool propto,
              typename T_y, typename T_low, typename T_high>
    inline
    typename return_type<T_y,T_low,T_high>::type
    uniform_log(const T_y& y, const T_low& alpha, const T_high& beta) {
      return uniform_log<propto>(y,alpha,beta,stan::math::default_policy());
    }

    template <typename T_y, typename T_low, typename T_high,
              class Policy>
    inline
    typename return_type<T_y,T_low,T_high>::type
    uniform_log(const T_y& y, const T_low& alpha, const T_high& beta,
                const Policy&) {
      return uniform_log<false>(y,alpha,beta,Policy());
    }

    template <typename T_y, typename T_low, typename T_high>
    inline
    typename return_type<T_y,T_low,T_high>::type
    uniform_log(const T_y& y, const T_low& alpha, const T_high& beta) {
      return uniform_log<false>(y,alpha,beta,stan::math::default_policy());
    }

  }
}
#endif
<|endoftext|>


<commit_before>#ifndef _SNARKFRONT_DSL_UTILITY_HPP_
#define _SNARKFRONT_DSL_UTILITY_HPP_

#include <array>
#include <cstdint>
#include <iostream>
#include <istream>
#include <ostream>
#include <string>
#include <vector>

#include <snarklib/Util.hpp>

#include <snarkfront/Alg.hpp>
#include <snarkfront/AST.hpp>
#include <snarkfront/BitwiseAST.hpp>
#include <snarkfront/DSL_base.hpp>
#include <snarkfront/HexUtil.hpp>

namespace snarkfront {

////////////////////////////////////////////////////////////////////////////////
// elliptic curve pairing
//

// check if string name is: BN128, Edwards
bool validPairingName(const std::string& name);

// returns true if "BN128"
bool pairingBN128(const std::string& name);

// returns true if "Edwards"
bool pairingEdwards(const std::string& name);

////////////////////////////////////////////////////////////////////////////////
// SHA-2
//

// check if: "1", "224", "256", "384", "512", "512_224", "512_256"
bool validSHA2Name(const std::string& shaBits);

// check if: 1, 224, 256, 384, 512
bool validSHA2Name(const std::size_t shaBits);

// returns true if "SHA256"
bool nameSHA256(const std::string& shaBits);

// returns true if "SHA512"
bool nameSHA512(const std::string& shaBits);

////////////////////////////////////////////////////////////////////////////////
// AES
//

// check if: 128, 192, 256
bool validAESName(const std::size_t aesBits);

////////////////////////////////////////////////////////////////////////////////
// powers of 2
//

template <typename ALG>
std::size_t sizeBits(const AST_Const<ALG>&) {
    typename AST_Const<ALG>::ValueType dummy;
    return sizeBits(dummy);
}

template <typename ALG>
std::size_t sizeBits(const AST_Var<ALG>&) {
    typename AST_Var<ALG>::ValueType dummy;
    return sizeBits(dummy);
}

////////////////////////////////////////////////////////////////////////////////
// convert between hexadecimal ASCII and binary
//

#define DEFN_ASCII_HEX_ARRAY(BITS)                      \
template <typename FR, std::size_t N>                   \
std::string asciiHex(                                   \
    const std::array<uint ## BITS ## _x<FR>, N>& a,     \
    const bool space = false)                           \
{                                                       \
    std::array<uint ## BITS ## _t, N> tmp;              \
    for (std::size_t i = 0; i < N; ++i)                 \
        tmp[i] = a[i]->value();                         \
    return asciiHex(tmp, space);                        \
}

DEFN_ASCII_HEX_ARRAY(8)
DEFN_ASCII_HEX_ARRAY(32)
DEFN_ASCII_HEX_ARRAY(64)

#undef DEFN_ASCII_HEX_ARRAY

#define DEFN_ASCII_HEX_VECTOR(BITS)                 \
template <typename FR, std::size_t N>               \
std::string asciiHex(                               \
    const std::vector<uint ## BITS ## _x<FR>>& a,   \
    const bool space = false)                       \
{                                                   \
    std::vector<uint ## BITS ## _t> tmp;            \
    for (std::size_t i = 0; i < N; ++i)             \
        tmp[i] = a[i]->value();                     \
    return asciiHex(tmp, space);                    \
}

DEFN_ASCII_HEX_VECTOR(8)
DEFN_ASCII_HEX_VECTOR(32)
DEFN_ASCII_HEX_VECTOR(64)

#undef DEFN_ASCII_HEX_VECTOR

////////////////////////////////////////////////////////////////////////////////
// serialize hash digests and preimages
//

#define DEFN_ARRAY_OUT(UINT)                                    \
template <std::size_t N>                                        \
std::ostream& operator<< (                                      \
    std::ostream& os,                                           \
    const std::array<UINT, N>& a)                               \
{                                                               \
    const char *ptr = reinterpret_cast<const char*>(a.data());  \
    if (snarklib::is_big_endian<int>()) {                       \
        for (std::size_t i = 0; i < N; ++i) {                   \
            for (int j = sizeof(UINT) - 1; j >= 0; --j) {       \
                os.put(ptr[i * sizeof(UINT) + j]);              \
            }                                                   \
        }                                                       \
    } else {                                                    \
        os.write(ptr, sizeof(a));                               \
    }                                                           \
    return os;                                                  \
}

DEFN_ARRAY_OUT(std::uint8_t)
DEFN_ARRAY_OUT(std::uint32_t)
DEFN_ARRAY_OUT(std::uint64_t)

#undef DEFN_ARRAY_OUT

#define DEFN_VECTOR_ARRAY_OUT(UINT)                     \
template <std::size_t N>                                \
std::ostream& operator<< (                              \
    std::ostream& os,                                   \
    const std::vector<std::array<UINT, N>>& a)          \
{                                                       \
    os << a.size() << ' ';                              \
    for (const auto& r : a)                             \
        os << r;                                        \
    return os;                                          \
}

DEFN_VECTOR_ARRAY_OUT(std::uint8_t)
DEFN_VECTOR_ARRAY_OUT(std::uint32_t)
DEFN_VECTOR_ARRAY_OUT(std::uint64_t)

#undef DEFN_VECTOR_ARRAY_OUT

#define DEFN_ARRAY_IN(UINT)                                     \
template <std::size_t N>                                        \
std::istream& operator>> (                                      \
    std::istream& is,                                           \
    std::array<UINT, N>& a)                                     \
{                                                               \
    char *ptr = reinterpret_cast<char*>(a.data());              \
    if (snarklib::is_big_endian<int>()) {                       \
        for (std::size_t i = 0; i < N; ++i) {                   \
            for (int j = sizeof(UINT) - 1; j >= 0; --j) {       \
                if (! is.get(ptr[i * sizeof(UINT) + j]))        \
                    return is;                                  \
            }                                                   \
        }                                                       \
    } else {                                                    \
        is.read(ptr, sizeof(a));                                \
    }                                                           \
    return is;                                                  \
}

DEFN_ARRAY_IN(std::uint8_t)
DEFN_ARRAY_IN(std::uint32_t)
DEFN_ARRAY_IN(std::uint64_t)

#undef DEFN_ARRAY_IN

#define DEFN_VECTOR_ARRAY_IN(UINT)              \
template <std::size_t N>                        \
std::istream& operator>> (                      \
    std::istream& is,                           \
    std::vector<std::array<UINT, N>>& a)        \
{                                               \
    std::size_t len = -1;                       \
    if (!(is >> len) || (-1 == len)) return is; \
    char c;                                     \
    if (!is.get(c) || (' ' != c)) return is;    \
    a.resize(len);                              \
    for (auto& r : a)                           \
        if (!(is >> r)) break;                  \
    return is;                                  \
}

DEFN_VECTOR_ARRAY_IN(std::uint8_t)
DEFN_VECTOR_ARRAY_IN(std::uint32_t)
DEFN_VECTOR_ARRAY_IN(std::uint64_t)

#undef DEFN_VECTOR_ARRAY_IN

////////////////////////////////////////////////////////////////////////////////
// lookup table for unsigned integer types
//

template <typename T, typename U, typename VAL, typename BITWISE>
class BitwiseLUT
{
public:
    template <std::size_t N>
    BitwiseLUT(const std::array<VAL, N>& table_elements)
        : m_value(table_elements.begin(),
                  table_elements.end())
    {}

    std::size_t size() const { return m_value.size(); }

    U operator[] (const T& x) const
    {
        const auto N = m_value.size();

        auto sum = BITWISE::_AND(BITWISE::_constant(m_value[0]),
                                 BITWISE::_CMPLMNT(BITWISE::_bitmask(0 != x)));

        for (std::size_t i = 1; i < N - 1; ++i) {
            sum = BITWISE::_ADDMOD(sum,
                                   BITWISE::_AND(
                                       BITWISE::_constant(m_value[i]),
                                       BITWISE::_CMPLMNT(BITWISE::_bitmask(i != x))));
        }

        return BITWISE::ADDMOD(sum,
                               BITWISE::_AND(
                                   BITWISE::_constant(m_value[N - 1]),
                                   BITWISE::_CMPLMNT(BITWISE::_bitmask((N-1) != x))));
    }

private:
    const std::vector<VAL> m_value;
};

template <typename FR> using
array_uint8 = BitwiseLUT<AST_Node<Alg_uint8<FR>>,
                         AST_Op<Alg_uint8<FR>>,
                         std::uint8_t,
                         BitwiseAST<Alg_uint8<FR>>>;

template <typename FR> using
array_uint32 = BitwiseLUT<AST_Node<Alg_uint32<FR>>,
                          AST_Op<Alg_uint32<FR>>,
                          std::uint32_t,
                          BitwiseAST<Alg_uint32<FR>>>;

template <typename FR> using
array_uint64 = BitwiseLUT<AST_Node<Alg_uint64<FR>>,
                          AST_Op<Alg_uint64<FR>>,
                          std::uint64_t,
                          BitwiseAST<Alg_uint64<FR>>>;

} // namespace snarkfront

#endif
<commit_msg>finite field exponentiation<commit_after>#ifndef _SNARKFRONT_DSL_UTILITY_HPP_
#define _SNARKFRONT_DSL_UTILITY_HPP_

#include <array>
#include <cassert>
#include <cstdint>
#include <iostream>
#include <istream>
#include <ostream>
#include <string>
#include <vector>

#include <snarklib/Util.hpp>

#include <snarkfront/Alg.hpp>
#include <snarkfront/AST.hpp>
#include <snarkfront/BitwiseAST.hpp>
#include <snarkfront/DSL_base.hpp>
#include <snarkfront/HexUtil.hpp>

namespace snarkfront {

////////////////////////////////////////////////////////////////////////////////
// elliptic curve pairing
//

// check if string name is: BN128, Edwards
bool validPairingName(const std::string& name);

// returns true if "BN128"
bool pairingBN128(const std::string& name);

// returns true if "Edwards"
bool pairingEdwards(const std::string& name);

////////////////////////////////////////////////////////////////////////////////
// SHA-2
//

// check if: "1", "224", "256", "384", "512", "512_224", "512_256"
bool validSHA2Name(const std::string& shaBits);

// check if: 1, 224, 256, 384, 512
bool validSHA2Name(const std::size_t shaBits);

// returns true if "SHA256"
bool nameSHA256(const std::string& shaBits);

// returns true if "SHA512"
bool nameSHA512(const std::string& shaBits);

////////////////////////////////////////////////////////////////////////////////
// AES
//

// check if: 128, 192, 256
bool validAESName(const std::size_t aesBits);

////////////////////////////////////////////////////////////////////////////////
// powers of 2
//

template <typename ALG>
std::size_t sizeBits(const AST_Const<ALG>&) {
    typename AST_Const<ALG>::ValueType dummy;
    return sizeBits(dummy);
}

template <typename ALG>
std::size_t sizeBits(const AST_Var<ALG>&) {
    typename AST_Var<ALG>::ValueType dummy;
    return sizeBits(dummy);
}

////////////////////////////////////////////////////////////////////////////////
// convert between hexadecimal ASCII and binary
//

#define DEFN_ASCII_HEX_ARRAY(BITS)                      \
template <typename FR, std::size_t N>                   \
std::string asciiHex(                                   \
    const std::array<uint ## BITS ## _x<FR>, N>& a,     \
    const bool space = false)                           \
{                                                       \
    std::array<uint ## BITS ## _t, N> tmp;              \
    for (std::size_t i = 0; i < N; ++i)                 \
        tmp[i] = a[i]->value();                         \
    return asciiHex(tmp, space);                        \
}

DEFN_ASCII_HEX_ARRAY(8)
DEFN_ASCII_HEX_ARRAY(32)
DEFN_ASCII_HEX_ARRAY(64)

#undef DEFN_ASCII_HEX_ARRAY

#define DEFN_ASCII_HEX_VECTOR(BITS)                 \
template <typename FR, std::size_t N>               \
std::string asciiHex(                               \
    const std::vector<uint ## BITS ## _x<FR>>& a,   \
    const bool space = false)                       \
{                                                   \
    std::vector<uint ## BITS ## _t> tmp;            \
    for (std::size_t i = 0; i < N; ++i)             \
        tmp[i] = a[i]->value();                     \
    return asciiHex(tmp, space);                    \
}

DEFN_ASCII_HEX_VECTOR(8)
DEFN_ASCII_HEX_VECTOR(32)
DEFN_ASCII_HEX_VECTOR(64)

#undef DEFN_ASCII_HEX_VECTOR

////////////////////////////////////////////////////////////////////////////////
// serialize hash digests and preimages
//

#define DEFN_ARRAY_OUT(UINT)                                    \
template <std::size_t N>                                        \
std::ostream& operator<< (                                      \
    std::ostream& os,                                           \
    const std::array<UINT, N>& a)                               \
{                                                               \
    const char *ptr = reinterpret_cast<const char*>(a.data());  \
    if (snarklib::is_big_endian<int>()) {                       \
        for (std::size_t i = 0; i < N; ++i) {                   \
            for (int j = sizeof(UINT) - 1; j >= 0; --j) {       \
                os.put(ptr[i * sizeof(UINT) + j]);              \
            }                                                   \
        }                                                       \
    } else {                                                    \
        os.write(ptr, sizeof(a));                               \
    }                                                           \
    return os;                                                  \
}

DEFN_ARRAY_OUT(std::uint8_t)
DEFN_ARRAY_OUT(std::uint32_t)
DEFN_ARRAY_OUT(std::uint64_t)

#undef DEFN_ARRAY_OUT

#define DEFN_VECTOR_ARRAY_OUT(UINT)                     \
template <std::size_t N>                                \
std::ostream& operator<< (                              \
    std::ostream& os,                                   \
    const std::vector<std::array<UINT, N>>& a)          \
{                                                       \
    os << a.size() << ' ';                              \
    for (const auto& r : a)                             \
        os << r;                                        \
    return os;                                          \
}

DEFN_VECTOR_ARRAY_OUT(std::uint8_t)
DEFN_VECTOR_ARRAY_OUT(std::uint32_t)
DEFN_VECTOR_ARRAY_OUT(std::uint64_t)

#undef DEFN_VECTOR_ARRAY_OUT

#define DEFN_ARRAY_IN(UINT)                                     \
template <std::size_t N>                                        \
std::istream& operator>> (                                      \
    std::istream& is,                                           \
    std::array<UINT, N>& a)                                     \
{                                                               \
    char *ptr = reinterpret_cast<char*>(a.data());              \
    if (snarklib::is_big_endian<int>()) {                       \
        for (std::size_t i = 0; i < N; ++i) {                   \
            for (int j = sizeof(UINT) - 1; j >= 0; --j) {       \
                if (! is.get(ptr[i * sizeof(UINT) + j]))        \
                    return is;                                  \
            }                                                   \
        }                                                       \
    } else {                                                    \
        is.read(ptr, sizeof(a));                                \
    }                                                           \
    return is;                                                  \
}

DEFN_ARRAY_IN(std::uint8_t)
DEFN_ARRAY_IN(std::uint32_t)
DEFN_ARRAY_IN(std::uint64_t)

#undef DEFN_ARRAY_IN

#define DEFN_VECTOR_ARRAY_IN(UINT)              \
template <std::size_t N>                        \
std::istream& operator>> (                      \
    std::istream& is,                           \
    std::vector<std::array<UINT, N>>& a)        \
{                                               \
    std::size_t len = -1;                       \
    if (!(is >> len) || (-1 == len)) return is; \
    char c;                                     \
    if (!is.get(c) || (' ' != c)) return is;    \
    a.resize(len);                              \
    for (auto& r : a)                           \
        if (!(is >> r)) break;                  \
    return is;                                  \
}

DEFN_VECTOR_ARRAY_IN(std::uint8_t)
DEFN_VECTOR_ARRAY_IN(std::uint32_t)
DEFN_VECTOR_ARRAY_IN(std::uint64_t)

#undef DEFN_VECTOR_ARRAY_IN

////////////////////////////////////////////////////////////////////////////////
// lookup table for unsigned integer types
//

template <typename T, typename U, typename VAL, typename BITWISE>
class BitwiseLUT
{
public:
    template <std::size_t N>
    BitwiseLUT(const std::array<VAL, N>& table_elements)
        : m_value(table_elements.begin(),
                  table_elements.end())
    {
#ifdef USE_ASSERT
        // empty look up table does not make sense
        assert(N > 0);
#endif
    }

    std::size_t size() const { return m_value.size(); }

    U operator[] (const T& x) const
    {
        const auto N = m_value.size();

        if (1 == N) {
            // returns value if index is 0, else all clear bits
            return BITWISE::AND(BITWISE::_constant(m_value[0]),
                                BITWISE::_CMPLMNT(BITWISE::_bitmask(0 != x)));

        } else {
            auto sum = BITWISE::_AND(BITWISE::_constant(m_value[0]),
                                     BITWISE::_CMPLMNT(BITWISE::_bitmask(0 != x)));

            for (std::size_t i = 1; i < N - 1; ++i) {
                sum = BITWISE::_ADDMOD(sum,
                                       BITWISE::_AND(
                                           BITWISE::_constant(m_value[i]),
                                           BITWISE::_CMPLMNT(BITWISE::_bitmask(i != x))));
            }

            return BITWISE::ADDMOD(sum,
                                   BITWISE::_AND(
                                       BITWISE::_constant(m_value[N - 1]),
                                       BITWISE::_CMPLMNT(BITWISE::_bitmask((N-1) != x))));
        }
    }

private:
    const std::vector<VAL> m_value;
};

template <typename FR> using
array_uint8 = BitwiseLUT<AST_Node<Alg_uint8<FR>>,
                         AST_Op<Alg_uint8<FR>>,
                         std::uint8_t,
                         BitwiseAST<Alg_uint8<FR>>>;

template <typename FR> using
array_uint32 = BitwiseLUT<AST_Node<Alg_uint32<FR>>,
                          AST_Op<Alg_uint32<FR>>,
                          std::uint32_t,
                          BitwiseAST<Alg_uint32<FR>>>;

template <typename FR> using
array_uint64 = BitwiseLUT<AST_Node<Alg_uint64<FR>>,
                          AST_Op<Alg_uint64<FR>>,
                          std::uint64_t,
                          BitwiseAST<Alg_uint64<FR>>>;

////////////////////////////////////////////////////////////////////////////////
// finite field exponentiation
//

template <typename FR>
AST_Op<Alg_Field<FR>> pow(const AST_Node<Alg_Field<FR>>& base,
                          const AST_Node<Alg_bool<FR>>& exponent)
{
    // base * exponent + ~exponent = exponent ? base : one
    return AST_Op<Alg_Field<FR>>(
        Alg_Field<FR>::OpType::ADD,
        new AST_Op<Alg_Field<FR>>(Alg_Field<FR>::OpType::MUL,
                                  base,
                                  _xword(exponent, base)),
        _xword(~exponent, base));
}

template <typename FR>
AST_Op<Alg_Field<FR>>* _pow(const AST_Node<Alg_Field<FR>>& base,
                            const AST_Node<Alg_bool<FR>>& exponent)
{
    // base * exponent + ~exponent = exponent ? base : one
    return new AST_Op<Alg_Field<FR>>(
        Alg_Field<FR>::OpType::ADD,
        new AST_Op<Alg_Field<FR>>(Alg_Field<FR>::OpType::MUL,
                                  base,
                                  _xword(exponent, base)),
        _xword(~exponent, base));
}

template <typename FR>
AST_Op<Alg_Field<FR>> pow(const AST_Node<Alg_Field<FR>>& base,
                          const std::vector<AST_Node<Alg_bool<FR>>>& exponent)
{
    const auto expBits = exponent.size();

#ifdef USE_ASSERT
    // no exponent bits does not make sense
    assert(expBits > 0);
#endif

    if (1 == expBits) {
        return pow(base, exponent[0]);

    } else {
        auto sum = _pow(base, exponent[0]);

        // pow(base, 2)
        auto powbase = new AST_Op<Alg_Field<FR>>(Alg_Field<FR>::OpType::MUL,
                                                 base,
                                                 base);

        for (std::size_t i = 1; i < expBits - 1; ++i) {
            sum = new AST_Op<Alg_Field<FR>>(Alg_Field<FR>::OpType::ADD,
                                            sum,
                                            _pow(powbase, exponent[i]));

            // pow(base, pow(2, i + 1))
            powbase = new AST_Op<Alg_Field<FR>>(Alg_Field<FR>::OpType::MUL,
                                                powbase,
                                                powbase);
        }

        return AST_Op<Alg_Field<FR>>(Alg_Field<FR>::OpType::ADD,
                                     sum,
                                     _pow(powbase, exponent[expBits - 1]));
    }
}

} // namespace snarkfront

#endif
<|endoftext|>


<commit_before>#include "../base/SRC_FIRST.hpp"

#include "text_path.hpp"

#include "../geometry/angles.hpp"

namespace graphics
{
  TextPath::TextPath()
    : m_pv(),
      m_fullLength(0),
      m_pathOffset(0)
  {}

  TextPath::TextPath(TextPath const & src, math::Matrix<double, 3, 3> const & m)
  {
    m_arr.resize(src.m_arr.size());
    for (unsigned i = 0; i < m_arr.size(); ++i)
      m_arr[i] = src.m_arr[i] * m;

    m_fullLength = (m2::PointD(src.m_fullLength, 0) * m).Length(m2::PointD(0, 0) * m);
    m_pathOffset = (m2::PointD(src.m_pathOffset, 0) * m).Length(m2::PointD(0, 0) * m);

    m_pv = PathView(&m_arr[0], m_arr.size());

    /// Fix: Check for reversing only when rotation is active,
    /// otherwise we have some flicker-blit issues for street names on zooming.
    /// @todo Should investigate this stuff.
    if (m(0, 1) != 0.0 && m(1, 0) != 0.0)
      checkReverse();
    else
      setIsReverse(src.isReverse());
  }

  TextPath::TextPath(m2::PointD const * arr, size_t sz, double fullLength, double pathOffset)
    : m_fullLength(fullLength),
      m_pathOffset(pathOffset)
  {
    ASSERT ( sz > 1, () );

    m_arr.resize(sz);
    copy(arr, arr + sz, m_arr.begin());

    m_pv = PathView(&m_arr[0], m_arr.size());

    checkReverse();
  }

  bool TextPath::isReverse() const
  {
    return m_pv.isReverse();
  }

  void TextPath::setIsReverse(bool flag)
  {
    m_pv.setIsReverse(flag);
  }

  void TextPath::checkReverse()
  {
    /* assume, that readable text in path should be ('o' - start draw point):
     *    /   o
     *   /     \
     *  /   or  \
     * o         \
     */

    double const a = ang::AngleTo(m_arr[0], m_arr[m_arr.size() - 1]);

    if (fabs(a) > math::pi / 2.0)
    {
      // if we swap direction, we need to recalculate path offset from the end
      double len = 0.0;
      for (size_t i = 1; i < m_arr.size(); ++i)
        len += m_arr[i-1].Length(m_arr[i]);

      m_pathOffset = m_fullLength - m_pathOffset - len;
      ASSERT ( m_pathOffset >= -1.0E-6, () );
      if (m_pathOffset < 0.0)
        m_pathOffset = 0.0;

      setIsReverse(true);
    }
    else
      setIsReverse(false);
  }

  double TextPath::fullLength() const
  {
    return m_fullLength;
  }

  double TextPath::pathOffset() const
  {
    return m_pathOffset;
  }

  size_t TextPath::size() const
  {
    return m_pv.size();
  }

  m2::PointD TextPath::get(size_t i) const
  {
    return m_pv.get(i);
  }

  m2::PointD TextPath::operator[](size_t i) const
  {
    return get(i);
  }

  PathPoint const TextPath::offsetPoint(PathPoint const & pp, double offset) const
  {
    return m_pv.offsetPoint(pp, offset);
  }

  PivotPoint TextPath::findPivotPoint(PathPoint const & pp, GlyphMetrics const & sym) const
  {
    const PivotPoint ptStart = m_pv.findPivotPoint(pp, sym.m_xOffset - sym.m_width);
    const PivotPoint ptEnd = m_pv.findPivotPoint(pp, sym.m_xOffset + sym.m_width * 2);
    // both start and end are on the same segment, no need to calculate
    if (ptStart.m_pp.m_i == ptEnd.m_pp.m_i)
      return PivotPoint(ptStart.m_angle,
                        PathPoint(ptStart.m_pp.m_i, ptStart.m_angle, (ptStart.m_pp.m_pt + ptEnd.m_pp.m_pt) / 2.0));
    // points are on different segments, average the angle and middle point
    const PivotPoint ptMid = m_pv.findPivotPoint(pp, sym.m_xOffset + sym.m_width / 2.0);
    if ((ptStart.m_pp.m_i != -1) && (ptMid.m_pp.m_i != -1) && (ptEnd.m_pp.m_i != -1))
    {
      const ang::AngleD avgAngle(ang::GetMiddleAngle(ptStart.m_angle.val(), ptEnd.m_angle.val()));

      return PivotPoint(avgAngle,
                        PathPoint(ptMid.m_pp.m_i, ptMid.m_angle,
                                  (ptStart.m_pp.m_pt +
                                   ptMid.m_pp.m_pt + ptMid.m_pp.m_pt + // twice to compensate for long distance
                                   ptEnd.m_pp.m_pt) / 4.0));
    }
    // if some of the pivot points are outside of the path, just take the middle value
    else
      return ptMid;
  }

  PathPoint const TextPath::front() const
  {
    return m_pv.front();
  }
}

<commit_msg>formatting<commit_after>#include "../base/SRC_FIRST.hpp"

#include "text_path.hpp"

#include "../geometry/angles.hpp"

namespace graphics
{
  TextPath::TextPath()
    : m_pv(),
      m_fullLength(0),
      m_pathOffset(0)
  {}

  TextPath::TextPath(TextPath const & src, math::Matrix<double, 3, 3> const & m)
  {
    m_arr.resize(src.m_arr.size());
    for (unsigned i = 0; i < m_arr.size(); ++i)
      m_arr[i] = src.m_arr[i] * m;

    m_fullLength = (m2::PointD(src.m_fullLength, 0) * m).Length(m2::PointD(0, 0) * m);
    m_pathOffset = (m2::PointD(src.m_pathOffset, 0) * m).Length(m2::PointD(0, 0) * m);

    m_pv = PathView(&m_arr[0], m_arr.size());

    /// Fix: Check for reversing only when rotation is active,
    /// otherwise we have some flicker-blit issues for street names on zooming.
    /// @todo Should investigate this stuff.
    if (m(0, 1) != 0.0 && m(1, 0) != 0.0)
      checkReverse();
    else
      setIsReverse(src.isReverse());
  }

  TextPath::TextPath(m2::PointD const * arr, size_t sz, double fullLength, double pathOffset)
    : m_fullLength(fullLength),
      m_pathOffset(pathOffset)
  {
    ASSERT ( sz > 1, () );

    m_arr.resize(sz);
    copy(arr, arr + sz, m_arr.begin());

    m_pv = PathView(&m_arr[0], m_arr.size());

    checkReverse();
  }

  bool TextPath::isReverse() const
  {
    return m_pv.isReverse();
  }

  void TextPath::setIsReverse(bool flag)
  {
    m_pv.setIsReverse(flag);
  }

  void TextPath::checkReverse()
  {
    /* assume, that readable text in path should be ('o' - start draw point):
     *    /   o
     *   /     \
     *  /   or  \
     * o         \
     */

    double const a = ang::AngleTo(m_arr[0], m_arr[m_arr.size() - 1]);

    if (fabs(a) > math::pi / 2.0)
    {
      // if we swap direction, we need to recalculate path offset from the end
      double len = 0.0;
      for (size_t i = 1; i < m_arr.size(); ++i)
        len += m_arr[i-1].Length(m_arr[i]);

      m_pathOffset = m_fullLength - m_pathOffset - len;
      ASSERT ( m_pathOffset >= -1.0E-6, () );
      if (m_pathOffset < 0.0)
        m_pathOffset = 0.0;

      setIsReverse(true);
    }
    else
      setIsReverse(false);
  }

  double TextPath::fullLength() const
  {
    return m_fullLength;
  }

  double TextPath::pathOffset() const
  {
    return m_pathOffset;
  }

  size_t TextPath::size() const
  {
    return m_pv.size();
  }

  m2::PointD TextPath::get(size_t i) const
  {
    return m_pv.get(i);
  }

  m2::PointD TextPath::operator[](size_t i) const
  {
    return get(i);
  }

  PathPoint const TextPath::offsetPoint(PathPoint const & pp, double offset) const
  {
    return m_pv.offsetPoint(pp, offset);
  }

  PivotPoint TextPath::findPivotPoint(PathPoint const & pp, GlyphMetrics const & sym) const
  {
    const PivotPoint ptStart = m_pv.findPivotPoint(pp, sym.m_xOffset - sym.m_width);
    const PivotPoint ptEnd = m_pv.findPivotPoint(pp, sym.m_xOffset + sym.m_width * 2);

    // both start and end are on the same segment, no need to calculate
    if (ptStart.m_pp.m_i == ptEnd.m_pp.m_i)
      return PivotPoint(ptStart.m_angle,
                        PathPoint(ptStart.m_pp.m_i, ptStart.m_angle, (ptStart.m_pp.m_pt + ptEnd.m_pp.m_pt) / 2.0));

    // points are on different segments, average the angle and middle point
    const PivotPoint ptMid = m_pv.findPivotPoint(pp, sym.m_xOffset + sym.m_width / 2.0);
    if ((ptStart.m_pp.m_i != -1) && (ptMid.m_pp.m_i != -1) && (ptEnd.m_pp.m_i != -1))
    {
      const ang::AngleD avgAngle(ang::GetMiddleAngle(ptStart.m_angle.val(), ptEnd.m_angle.val()));

      return PivotPoint(avgAngle,
                        PathPoint(ptMid.m_pp.m_i, ptMid.m_angle,
                                  (ptStart.m_pp.m_pt +
                                   ptMid.m_pp.m_pt + ptMid.m_pp.m_pt + // twice to compensate for long distance
                                   ptEnd.m_pp.m_pt) / 4.0));
    }
    else
    {
      // if some of the pivot points are outside of the path, just take the middle value
      return ptMid;
    }
  }

  PathPoint const TextPath::front() const
  {
    return m_pv.front();
  }
}

<|endoftext|>