<commit_before>/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
  Copyright(C) 2010 Tetsuro IKEDA
  Copyright(C) 2010-2013 Kentoku SHIBA
  Copyright(C) 2011-2013 Kouhei Sutou <kou@clear-code.com>

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

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

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <mrn_mysql.h>
#include <mrn_mysql_compat.h>
#include <mrn_err.h>
#include <mrn_encoding.hpp>
#include <mrn_windows.hpp>
#include <mrn_table.hpp>
#include <mrn_macro.hpp>

MRN_BEGIN_DECLS

struct st_mrn_snip_info
{
  grn_ctx ctx;
  grn_snip *snippet;
  String result_str;
};

static my_bool mrn_snippet_prepare(st_mrn_snip_info *snip_info, UDF_ARGS *args,
                                   char *message, grn_snip **snippet)
{
  unsigned int i;
  CHARSET_INFO *cs;
  grn_ctx *ctx = &snip_info->ctx;
  long long snip_max_len;
  long long snip_max_num;
  long long skip_leading_spaces;
  long long html_escape;
  int flags = GRN_SNIP_COPY_TAG;
  grn_snip_mapping *mapping = NULL;
  grn_rc rc;
  String *result_str = &snip_info->result_str;

  *snippet = NULL;
  snip_max_len = *((long long *) args->args[1]);
  snip_max_num = *((long long *) args->args[2]);

  if (args->arg_type[3] == STRING_RESULT) {
    if (!(cs = get_charset_by_name(args->args[3], MYF(0)))) {
      my_error(ER_UNKNOWN_COLLATION, MYF(0), args->args[3]);
      goto error;
    }
  } else {
    if (!(cs = get_charset(*((long long *) args->args[3]), MYF(0)))) {
      my_error(ER_UNKNOWN_COLLATION, MYF(0), "");
      goto error;
    }
  }
if (mrn::encoding::set(ctx, cs)) {
    goto error;
  }

  if (!(cs->state & (MY_CS_BINSORT | MY_CS_CSSORT))) {
    flags |= GRN_SNIP_NORMALIZE;
  }

  skip_leading_spaces = *((long long *) args->args[4]);
  if (skip_leading_spaces) {
    flags |= GRN_SNIP_SKIP_LEADING_SPACES;
  }

  html_escape = *((long long *) args->args[5]);
  if (html_escape) {
    mapping = (grn_snip_mapping *) -1;
  }

  *snippet = grn_snip_open(ctx, flags, snip_max_len, snip_max_num,
                           "", 0, "", 0, mapping);
  if (ctx->rc) {
    my_printf_error(ER_MRN_ERROR_FROM_GROONGA_NUM,
                    ER_MRN_ERROR_FROM_GROONGA_STR, MYF(0), ctx->errbuf);
    goto error;
  }

  for (i = 8; i < args->arg_count; i += 3) {
    rc = grn_snip_add_cond(ctx, *snippet,
                           args->args[i], args->lengths[i],
                           args->args[i + 1], args->lengths[i + 1],
                           args->args[i + 2], args->lengths[i + 2]);
    if (rc) {
      my_printf_error(ER_MRN_ERROR_FROM_GROONGA_NUM,
                      ER_MRN_ERROR_FROM_GROONGA_STR, MYF(0), ctx->errbuf);
      goto error;
    }
  }

  result_str->set_charset(cs);
  return FALSE;

error:
  if (*snippet) {
    grn_snip_close(ctx, *snippet);
  }
  if (message) {
    strcpy(message, MRN_GET_ERROR_MESSAGE);
  }
  return TRUE;
}

MRN_API my_bool mroonga_snippet_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
  uint i;
  st_mrn_snip_info *snip_info = NULL;
  bool can_open_snippet = TRUE;
  initid->ptr = NULL;
  if (args->arg_count < 11 || (args->arg_count - 11) % 3)
  {
    sprintf(message, "Incorrect number of arguments for mroonga_snippet(): %u",
            args->arg_count);
    goto error;
  }
  if (args->arg_type[0] != STRING_RESULT) {
    strcpy(message, "mroonga_snippet() requires string for 1st argument");
    goto error;
  }
  if (args->arg_type[1] != INT_RESULT) {
    strcpy(message, "mroonga_snippet() requires int for 2nd argument");
    goto error;
  }
  if (args->arg_type[2] != INT_RESULT) {
    strcpy(message, "mroonga_snippet() requires int for 3rd argument");
    goto error;
  }
  if (
    args->arg_type[3] != STRING_RESULT &&
    args->arg_type[3] != INT_RESULT
  ) {
    strcpy(message,
      "mroonga_snippet() requires string or int for 4th argument");
    goto error;
  }
  if (args->arg_type[4] != INT_RESULT) {
    strcpy(message, "mroonga_snippet() requires int for 5th argument");
    goto error;
  }
  if (args->arg_type[5] != INT_RESULT) {
    strcpy(message, "mroonga_snippet() requires int for 6th argument");
    goto error;
  }
  for (i = 6; i < args->arg_count; i++) {
    if (args->arg_type[i] != STRING_RESULT) {
      sprintf(message, "mroonga_snippet() requires string for %uth argument",
              i);
      goto error;
    }
  }
  initid->maybe_null = 1;
  initid->const_item = 1;

  if (!(snip_info = (st_mrn_snip_info *) my_malloc(sizeof(st_mrn_snip_info),
                                                   MYF(MY_WME | MY_ZEROFILL))))
  {
    strcpy(message, "mroonga_snippet() out of memory");
    goto error;
  }
  grn_ctx_init(&snip_info->ctx, 0);
  grn_db_create(&snip_info->ctx, NULL, 0);

  for (i = 1; i < args->arg_count; i++) {
    if (!args->args[i]) {
      can_open_snippet = FALSE;
      break;
    }
  }
  if (can_open_snippet) {
    if (mrn_snippet_prepare(snip_info, args, message, &snip_info->snippet)) {
      goto error;
    }
  }
  initid->ptr = (char *) snip_info;

  return FALSE;

error:
  if (snip_info) {
    grn_obj_close(&snip_info->ctx, grn_ctx_db(&snip_info->ctx));
    grn_ctx_fin(&snip_info->ctx);
    my_free(snip_info, MYF(0));
  }
  return TRUE;
}

MRN_API char *mroonga_snippet(UDF_INIT *initid, UDF_ARGS *args, char *result,
                      unsigned long *length, char *is_null, char *error)
{
  st_mrn_snip_info *snip_info = (st_mrn_snip_info *) initid->ptr;
  grn_ctx *ctx = &snip_info->ctx;
  String *result_str = &snip_info->result_str;
  char *target;
  unsigned int target_length;
  grn_snip *snippet = NULL;
  grn_rc rc;
  unsigned int i, n_results, max_tagged_length, result_length;

  if (!args->args[0]) {
    *is_null = 1;
    return NULL;
  }
  *is_null = 0;
  target = args->args[0];
  target_length = args->lengths[0];

  if (!snip_info->snippet) {
    for (i = 1; i < args->arg_count; i++) {
      if (!args->args[i]) {
        my_printf_error(ER_MRN_INVALID_NULL_VALUE_NUM,
                        ER_MRN_INVALID_NULL_VALUE_STR, MYF(0),
                        "mroonga_snippet() arguments");
        goto error;
      }
    }

    if (mrn_snippet_prepare(snip_info, args, NULL, &snippet)) {
      goto error;
    }
  } else {
    snippet = snip_info->snippet;
  }

  rc = grn_snip_exec(ctx, snippet, target, target_length,
                     &n_results, &max_tagged_length);
  if (rc) {
    my_printf_error(ER_MRN_ERROR_FROM_GROONGA_NUM,
                    ER_MRN_ERROR_FROM_GROONGA_STR, MYF(0), ctx->errbuf);
    goto error;
  }

  result_str->length(0);
  if (result_str->reserve((args->lengths[6] + args->lengths[7] +
                          max_tagged_length) * n_results)) {
    my_error(ER_OUT_OF_RESOURCES, MYF(0), HA_ERR_OUT_OF_MEM);
    goto error;
  }
  for (i = 0; i < n_results; i++) {
    result_str->q_append(args->args[6], args->lengths[6]);
    rc = grn_snip_get_result(ctx, snippet, i,
                             (char *) result_str->ptr() + result_str->length(),
                             &result_length);
    if (rc) {
      my_printf_error(ER_MRN_ERROR_FROM_GROONGA_NUM,
                      ER_MRN_ERROR_FROM_GROONGA_STR, MYF(0), ctx->errbuf);
      goto error;
    }
    result_str->length(result_str->length() + result_length);
    result_str->q_append(args->args[7], args->lengths[7]);
  }

  if (!snip_info->snippet) {
    rc = grn_snip_close(ctx, snippet);
    if (rc) {
      my_printf_error(ER_MRN_ERROR_FROM_GROONGA_NUM,
                      ER_MRN_ERROR_FROM_GROONGA_STR, MYF(0), ctx->errbuf);
      goto error;
    }
  }

  *length = result_str->length();
  return (char *) result_str->ptr();

error:
  *error = 1;
  return NULL;
}

MRN_API void mroonga_snippet_deinit(UDF_INIT *initid)
{
  st_mrn_snip_info *snip_info = (st_mrn_snip_info *) initid->ptr;
  if (snip_info) {
    if (snip_info->snippet) {
      grn_snip_close(&snip_info->ctx, snip_info->snippet);
    }
    snip_info->result_str.free();
    grn_obj_close(&snip_info->ctx, grn_ctx_db(&snip_info->ctx));
    grn_ctx_fin(&snip_info->ctx);
    my_free(snip_info, MYF(0));
  }
}

MRN_END_DECLS
<commit_msg>Fix indent<commit_after>/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
  Copyright(C) 2010 Tetsuro IKEDA
  Copyright(C) 2010-2013 Kentoku SHIBA
  Copyright(C) 2011-2013 Kouhei Sutou <kou@clear-code.com>

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

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

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <mrn_mysql.h>
#include <mrn_mysql_compat.h>
#include <mrn_err.h>
#include <mrn_encoding.hpp>
#include <mrn_windows.hpp>
#include <mrn_table.hpp>
#include <mrn_macro.hpp>

MRN_BEGIN_DECLS

struct st_mrn_snip_info
{
  grn_ctx ctx;
  grn_snip *snippet;
  String result_str;
};

static my_bool mrn_snippet_prepare(st_mrn_snip_info *snip_info, UDF_ARGS *args,
                                   char *message, grn_snip **snippet)
{
  unsigned int i;
  CHARSET_INFO *cs;
  grn_ctx *ctx = &snip_info->ctx;
  long long snip_max_len;
  long long snip_max_num;
  long long skip_leading_spaces;
  long long html_escape;
  int flags = GRN_SNIP_COPY_TAG;
  grn_snip_mapping *mapping = NULL;
  grn_rc rc;
  String *result_str = &snip_info->result_str;

  *snippet = NULL;
  snip_max_len = *((long long *) args->args[1]);
  snip_max_num = *((long long *) args->args[2]);

  if (args->arg_type[3] == STRING_RESULT) {
    if (!(cs = get_charset_by_name(args->args[3], MYF(0)))) {
      my_error(ER_UNKNOWN_COLLATION, MYF(0), args->args[3]);
      goto error;
    }
  } else {
    if (!(cs = get_charset(*((long long *) args->args[3]), MYF(0)))) {
      my_error(ER_UNKNOWN_COLLATION, MYF(0), "");
      goto error;
    }
  }
  if (mrn::encoding::set(ctx, cs)) {
    goto error;
  }

  if (!(cs->state & (MY_CS_BINSORT | MY_CS_CSSORT))) {
    flags |= GRN_SNIP_NORMALIZE;
  }

  skip_leading_spaces = *((long long *) args->args[4]);
  if (skip_leading_spaces) {
    flags |= GRN_SNIP_SKIP_LEADING_SPACES;
  }

  html_escape = *((long long *) args->args[5]);
  if (html_escape) {
    mapping = (grn_snip_mapping *) -1;
  }

  *snippet = grn_snip_open(ctx, flags, snip_max_len, snip_max_num,
                           "", 0, "", 0, mapping);
  if (ctx->rc) {
    my_printf_error(ER_MRN_ERROR_FROM_GROONGA_NUM,
                    ER_MRN_ERROR_FROM_GROONGA_STR, MYF(0), ctx->errbuf);
    goto error;
  }

  for (i = 8; i < args->arg_count; i += 3) {
    rc = grn_snip_add_cond(ctx, *snippet,
                           args->args[i], args->lengths[i],
                           args->args[i + 1], args->lengths[i + 1],
                           args->args[i + 2], args->lengths[i + 2]);
    if (rc) {
      my_printf_error(ER_MRN_ERROR_FROM_GROONGA_NUM,
                      ER_MRN_ERROR_FROM_GROONGA_STR, MYF(0), ctx->errbuf);
      goto error;
    }
  }

  result_str->set_charset(cs);
  return FALSE;

error:
  if (*snippet) {
    grn_snip_close(ctx, *snippet);
  }
  if (message) {
    strcpy(message, MRN_GET_ERROR_MESSAGE);
  }
  return TRUE;
}

MRN_API my_bool mroonga_snippet_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
  uint i;
  st_mrn_snip_info *snip_info = NULL;
  bool can_open_snippet = TRUE;
  initid->ptr = NULL;
  if (args->arg_count < 11 || (args->arg_count - 11) % 3)
  {
    sprintf(message, "Incorrect number of arguments for mroonga_snippet(): %u",
            args->arg_count);
    goto error;
  }
  if (args->arg_type[0] != STRING_RESULT) {
    strcpy(message, "mroonga_snippet() requires string for 1st argument");
    goto error;
  }
  if (args->arg_type[1] != INT_RESULT) {
    strcpy(message, "mroonga_snippet() requires int for 2nd argument");
    goto error;
  }
  if (args->arg_type[2] != INT_RESULT) {
    strcpy(message, "mroonga_snippet() requires int for 3rd argument");
    goto error;
  }
  if (
    args->arg_type[3] != STRING_RESULT &&
    args->arg_type[3] != INT_RESULT
  ) {
    strcpy(message,
      "mroonga_snippet() requires string or int for 4th argument");
    goto error;
  }
  if (args->arg_type[4] != INT_RESULT) {
    strcpy(message, "mroonga_snippet() requires int for 5th argument");
    goto error;
  }
  if (args->arg_type[5] != INT_RESULT) {
    strcpy(message, "mroonga_snippet() requires int for 6th argument");
    goto error;
  }
  for (i = 6; i < args->arg_count; i++) {
    if (args->arg_type[i] != STRING_RESULT) {
      sprintf(message, "mroonga_snippet() requires string for %uth argument",
              i);
      goto error;
    }
  }
  initid->maybe_null = 1;
  initid->const_item = 1;

  if (!(snip_info = (st_mrn_snip_info *) my_malloc(sizeof(st_mrn_snip_info),
                                                   MYF(MY_WME | MY_ZEROFILL))))
  {
    strcpy(message, "mroonga_snippet() out of memory");
    goto error;
  }
  grn_ctx_init(&snip_info->ctx, 0);
  grn_db_create(&snip_info->ctx, NULL, 0);

  for (i = 1; i < args->arg_count; i++) {
    if (!args->args[i]) {
      can_open_snippet = FALSE;
      break;
    }
  }
  if (can_open_snippet) {
    if (mrn_snippet_prepare(snip_info, args, message, &snip_info->snippet)) {
      goto error;
    }
  }
  initid->ptr = (char *) snip_info;

  return FALSE;

error:
  if (snip_info) {
    grn_obj_close(&snip_info->ctx, grn_ctx_db(&snip_info->ctx));
    grn_ctx_fin(&snip_info->ctx);
    my_free(snip_info, MYF(0));
  }
  return TRUE;
}

MRN_API char *mroonga_snippet(UDF_INIT *initid, UDF_ARGS *args, char *result,
                      unsigned long *length, char *is_null, char *error)
{
  st_mrn_snip_info *snip_info = (st_mrn_snip_info *) initid->ptr;
  grn_ctx *ctx = &snip_info->ctx;
  String *result_str = &snip_info->result_str;
  char *target;
  unsigned int target_length;
  grn_snip *snippet = NULL;
  grn_rc rc;
  unsigned int i, n_results, max_tagged_length, result_length;

  if (!args->args[0]) {
    *is_null = 1;
    return NULL;
  }
  *is_null = 0;
  target = args->args[0];
  target_length = args->lengths[0];

  if (!snip_info->snippet) {
    for (i = 1; i < args->arg_count; i++) {
      if (!args->args[i]) {
        my_printf_error(ER_MRN_INVALID_NULL_VALUE_NUM,
                        ER_MRN_INVALID_NULL_VALUE_STR, MYF(0),
                        "mroonga_snippet() arguments");
        goto error;
      }
    }

    if (mrn_snippet_prepare(snip_info, args, NULL, &snippet)) {
      goto error;
    }
  } else {
    snippet = snip_info->snippet;
  }

  rc = grn_snip_exec(ctx, snippet, target, target_length,
                     &n_results, &max_tagged_length);
  if (rc) {
    my_printf_error(ER_MRN_ERROR_FROM_GROONGA_NUM,
                    ER_MRN_ERROR_FROM_GROONGA_STR, MYF(0), ctx->errbuf);
    goto error;
  }

  result_str->length(0);
  if (result_str->reserve((args->lengths[6] + args->lengths[7] +
                          max_tagged_length) * n_results)) {
    my_error(ER_OUT_OF_RESOURCES, MYF(0), HA_ERR_OUT_OF_MEM);
    goto error;
  }
  for (i = 0; i < n_results; i++) {
    result_str->q_append(args->args[6], args->lengths[6]);
    rc = grn_snip_get_result(ctx, snippet, i,
                             (char *) result_str->ptr() + result_str->length(),
                             &result_length);
    if (rc) {
      my_printf_error(ER_MRN_ERROR_FROM_GROONGA_NUM,
                      ER_MRN_ERROR_FROM_GROONGA_STR, MYF(0), ctx->errbuf);
      goto error;
    }
    result_str->length(result_str->length() + result_length);
    result_str->q_append(args->args[7], args->lengths[7]);
  }

  if (!snip_info->snippet) {
    rc = grn_snip_close(ctx, snippet);
    if (rc) {
      my_printf_error(ER_MRN_ERROR_FROM_GROONGA_NUM,
                      ER_MRN_ERROR_FROM_GROONGA_STR, MYF(0), ctx->errbuf);
      goto error;
    }
  }

  *length = result_str->length();
  return (char *) result_str->ptr();

error:
  *error = 1;
  return NULL;
}

MRN_API void mroonga_snippet_deinit(UDF_INIT *initid)
{
  st_mrn_snip_info *snip_info = (st_mrn_snip_info *) initid->ptr;
  if (snip_info) {
    if (snip_info->snippet) {
      grn_snip_close(&snip_info->ctx, snip_info->snippet);
    }
    snip_info->result_str.free();
    grn_obj_close(&snip_info->ctx, grn_ctx_db(&snip_info->ctx));
    grn_ctx_fin(&snip_info->ctx);
    my_free(snip_info, MYF(0));
  }
}

MRN_END_DECLS
<|endoftext|>


<commit_before><commit_msg>Fix crash on material browser open<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Embedded Framework 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 <gtk/gtk.h>
#include <unistd.h>
#include <string>
#include "atom.h"
#include "atom_cef_app.h"
#include "include/cef_app.h"
#include "include/cef_browser.h"
#include "include/cef_frame.h"
#include "include/cef_runnable.h"
#include "client_handler.h"
#include "onig_regexp_extension.h"
#include "io_utils.h"

char* szWorkingDir; // The current working directory

const char* szPath; // The folder the application is in

const char* szPathToOpen; // The file to open

CefRefPtr<ClientHandler> g_handler;

void AppGetSettings(CefSettings& settings, CefRefPtr<CefApp>& app) {
  CefString(&settings.cache_path) = "";
  CefString(&settings.user_agent) = "";
  CefString(&settings.product_version) = "";
  CefString(&settings.locale) = "";
  CefString(&settings.log_file) = "";
  CefString(&settings.javascript_flags) = "";

  settings.remote_debugging_port = 9090;
  settings.log_severity = LOGSEVERITY_ERROR;
}

void destroy(void) {
  CefQuitMessageLoop();
}

void TerminationSignalHandler(int signatl) {
  destroy();
}

// WebViewDelegate::TakeFocus in the test webview delegate.
static gboolean HandleFocus(GtkWidget* widget, GdkEventFocus* focus) {
  if (g_handler.get() && g_handler->GetBrowserHwnd()) {
    // Give focus to the browser window.
    g_handler->GetBrowser()->GetHost()->SetFocus(true);
  }

  return TRUE;
}

int main(int argc, char *argv[]) {
  CefMainArgs main_args(argc, argv);
  szWorkingDir = get_current_dir_name();
  if (szWorkingDir == NULL)
    return -1;

  std::string appDir = io_util_app_directory();
  if (appDir.empty())
    return -1;

  szPath = appDir.c_str();

  std::string pathToOpen;
  if (argc >= 2) {
    if (argv[1][0] != '/') {
      pathToOpen.append(szWorkingDir);
      pathToOpen.append("/");
      pathToOpen.append(argv[1]);
    } else
      pathToOpen.append(argv[1]);
  } else
    pathToOpen.append(szWorkingDir);
  szPathToOpen = pathToOpen.c_str();

  GtkWidget* window;

  gtk_init(&argc, &argv);

  CefSettings settings;
  CefRefPtr<CefApp> app(new AtomCefApp);

  AppGetSettings(settings, app);
  CefInitialize(main_args, settings, app.get());

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW(window), "atom");
  gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);
  gtk_window_maximize(GTK_WINDOW(window));

  g_signal_connect(window, "focus", G_CALLBACK(&HandleFocus), NULL);

  GtkWidget* vbox = gtk_vbox_new(FALSE, 0);

  g_signal_connect(G_OBJECT(window), "destroy",
      G_CALLBACK(gtk_widget_destroyed), &window);
  g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(destroy), NULL);

  // Create the handler.
  g_handler = new ClientHandler();
  g_handler->SetMainHwnd(vbox);
  g_handler->SetWindow(window);

  // Create the browser view.
  CefWindowInfo window_info;
  CefBrowserSettings browserSettings;

  window_info.SetAsChild(vbox);

  std::string path = io_utils_real_app_path("/static/index.html");
  if (path.empty())
    return -1;

  std::string resolved("file://");
  resolved.append(path);
  resolved.append("?bootstrapScript=window-bootstrap");
  resolved.append("&pathToOpen=");
  resolved.append(PathToOpen());

  CefBrowserHost::CreateBrowserSync(window_info, g_handler.get(), resolved,
      browserSettings);

  gtk_container_add(GTK_CONTAINER(window), vbox);
  gtk_widget_show_all(GTK_WIDGET(window));

  GdkPixbuf *pixbuf;
  GError *error = NULL;
  std::string iconPath;
  iconPath.append(szPath);
  iconPath.append("/atom.png");
  pixbuf = gdk_pixbuf_new_from_file(iconPath.c_str(), &error);
  if (pixbuf)
    gtk_window_set_icon(GTK_WINDOW(window), pixbuf);

  // Install an signal handler so we clean up after ourselves.
  signal(SIGINT, TerminationSignalHandler);
  signal(SIGTERM, TerminationSignalHandler);

  CefRunMessageLoop();

  CefShutdown();

  return 0;
}

// Global functions

std::string AppGetWorkingDirectory() {
  return szWorkingDir;
}

std::string AppPath() {
  return szPath;
}

std::string PathToOpen() {
  return szPathToOpen;
}
<commit_msg>Set window icon before showing<commit_after>// Copyright (c) 2011 The Chromium Embedded Framework 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 <gtk/gtk.h>
#include <unistd.h>
#include <string>
#include "atom.h"
#include "atom_cef_app.h"
#include "include/cef_app.h"
#include "include/cef_browser.h"
#include "include/cef_frame.h"
#include "include/cef_runnable.h"
#include "client_handler.h"
#include "onig_regexp_extension.h"
#include "io_utils.h"

char* szWorkingDir; // The current working directory

const char* szPath; // The folder the application is in

const char* szPathToOpen; // The file to open

CefRefPtr<ClientHandler> g_handler;

void AppGetSettings(CefSettings& settings, CefRefPtr<CefApp>& app) {
  CefString(&settings.cache_path) = "";
  CefString(&settings.user_agent) = "";
  CefString(&settings.product_version) = "";
  CefString(&settings.locale) = "";
  CefString(&settings.log_file) = "";
  CefString(&settings.javascript_flags) = "";

  settings.remote_debugging_port = 9090;
  settings.log_severity = LOGSEVERITY_ERROR;
}

void destroy(void) {
  CefQuitMessageLoop();
}

void TerminationSignalHandler(int signatl) {
  destroy();
}

// WebViewDelegate::TakeFocus in the test webview delegate.
static gboolean HandleFocus(GtkWidget* widget, GdkEventFocus* focus) {
  if (g_handler.get() && g_handler->GetBrowserHwnd()) {
    // Give focus to the browser window.
    g_handler->GetBrowser()->GetHost()->SetFocus(true);
  }

  return TRUE;
}

int main(int argc, char *argv[]) {
  CefMainArgs main_args(argc, argv);
  szWorkingDir = get_current_dir_name();
  if (szWorkingDir == NULL)
    return -1;

  std::string appDir = io_util_app_directory();
  if (appDir.empty())
    return -1;

  szPath = appDir.c_str();

  std::string pathToOpen;
  if (argc >= 2) {
    if (argv[1][0] != '/') {
      pathToOpen.append(szWorkingDir);
      pathToOpen.append("/");
      pathToOpen.append(argv[1]);
    } else
      pathToOpen.append(argv[1]);
  } else
    pathToOpen.append(szWorkingDir);
  szPathToOpen = pathToOpen.c_str();

  GtkWidget* window;

  gtk_init(&argc, &argv);

  CefSettings settings;
  CefRefPtr<CefApp> app(new AtomCefApp);

  AppGetSettings(settings, app);
  CefInitialize(main_args, settings, app.get());

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW(window), "atom");
  gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);
  gtk_window_maximize(GTK_WINDOW(window));

  g_signal_connect(window, "focus", G_CALLBACK(&HandleFocus), NULL);

  GtkWidget* vbox = gtk_vbox_new(FALSE, 0);

  g_signal_connect(G_OBJECT(window), "destroy",
      G_CALLBACK(gtk_widget_destroyed), &window);
  g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(destroy), NULL);

  // Create the handler.
  g_handler = new ClientHandler();
  g_handler->SetMainHwnd(vbox);
  g_handler->SetWindow(window);

  // Create the browser view.
  CefWindowInfo window_info;
  CefBrowserSettings browserSettings;

  window_info.SetAsChild(vbox);

  std::string path = io_utils_real_app_path("/static/index.html");
  if (path.empty())
    return -1;

  std::string resolved("file://");
  resolved.append(path);
  resolved.append("?bootstrapScript=window-bootstrap");
  resolved.append("&pathToOpen=");
  resolved.append(PathToOpen());

  CefBrowserHost::CreateBrowserSync(window_info, g_handler.get(), resolved,
      browserSettings);

  gtk_container_add(GTK_CONTAINER(window), vbox);

  GdkPixbuf *pixbuf;
  GError *error = NULL;
  std::string iconPath;
  iconPath.append(szPath);
  iconPath.append("/atom.png");
  pixbuf = gdk_pixbuf_new_from_file(iconPath.c_str(), &error);
  if (pixbuf)
    gtk_window_set_icon(GTK_WINDOW(window), pixbuf);

  gtk_widget_show_all(GTK_WIDGET(window));

  // Install an signal handler so we clean up after ourselves.
  signal(SIGINT, TerminationSignalHandler);
  signal(SIGTERM, TerminationSignalHandler);

  CefRunMessageLoop();

  CefShutdown();

  return 0;
}

// Global functions

std::string AppGetWorkingDirectory() {
  return szWorkingDir;
}

std::string AppPath() {
  return szPath;
}

std::string PathToOpen() {
  return szPathToOpen;
}
<|endoftext|>


<commit_before>#ifndef SILICIUM_REACTIVE_LINUX_INOTIFY_HPP
#define SILICIUM_REACTIVE_LINUX_INOTIFY_HPP

#include <silicium/observable/observer.hpp>
#include <silicium/error_or.hpp>
#include <silicium/exchange.hpp>
#include <silicium/linux/inotify_watch_descriptor.hpp>
#include <silicium/path.hpp>
#include <boost/asio/posix/stream_descriptor.hpp>
#include <boost/swap.hpp>
#include <boost/optional.hpp>
#include <boost/ref.hpp>
#include <dirent.h>

namespace Si
{
	namespace linux
	{
		struct file_notification
		{
			boost::uint32_t mask;
			path name;
		};

		struct inotify_observable
		{
			typedef std::vector<file_notification> element_type;

			inotify_observable() BOOST_NOEXCEPT
			{
			}

			explicit inotify_observable(boost::asio::io_service &io)
				: notifier(Si::make_unique<boost::asio::posix::stream_descriptor>(boost::ref(io)))
			{
				int fd = inotify_init();
				if (fd < 0)
				{
					throw boost::system::system_error(errno, boost::system::posix_category);
				}
				try
				{
					notifier->assign(fd);
				}
				catch (...)
				{
					close(fd);
					throw;
				}
			}

			error_or<watch_descriptor> watch(boost::filesystem::path const &target, boost::uint32_t mask) BOOST_NOEXCEPT
			{
				assert(notifier);
				int const wd = inotify_add_watch(notifier->native_handle(), target.c_str(), mask);
				if (wd < 0)
				{
					return boost::system::error_code(errno, boost::system::posix_category);
				}
				return watch_descriptor(notifier->native_handle(), wd);
			}

			template <class Observer>
			void async_get_one(Observer &&receiver)
			{
				std::size_t const min_buffer_size = sizeof(inotify_event) + NAME_MAX + 1;
				std::size_t const additional_buffer = 8192;
				read_buffer.resize(min_buffer_size + additional_buffer);
				assert(notifier);
				notifier->async_read_some(boost::asio::buffer(read_buffer), [this, receiver](boost::system::error_code error, std::size_t bytes_read) mutable
				{
					if (error)
					{
						if (error == boost::asio::error::operation_aborted)
						{
							return;
						}
						throw std::logic_error("not implemented");
					}
					else
					{
						std::vector<file_notification> changes;
						for (std::size_t i = 0; i < bytes_read; )
						{
							inotify_event const &event = *reinterpret_cast<inotify_event const *>(read_buffer.data() + i);
							changes.emplace_back(file_notification{event.mask, path(event.name + 0, std::find(event.name + 0, event.name + event.len, '\0'))});
							i += sizeof(inotify_event);
							i += event.len;
						}
						std::forward<Observer>(receiver).got_element(std::move(changes));
					}
				});
			}

		private:

			std::unique_ptr<boost::asio::posix::stream_descriptor> notifier;
			std::vector<char> read_buffer;
		};
	}
}

#endif
<commit_msg>move-capture an observer<commit_after>#ifndef SILICIUM_REACTIVE_LINUX_INOTIFY_HPP
#define SILICIUM_REACTIVE_LINUX_INOTIFY_HPP

#include <silicium/observable/observer.hpp>
#include <silicium/error_or.hpp>
#include <silicium/exchange.hpp>
#include <silicium/linux/inotify_watch_descriptor.hpp>
#include <silicium/path.hpp>
#include <boost/asio/posix/stream_descriptor.hpp>
#include <boost/swap.hpp>
#include <boost/optional.hpp>
#include <boost/ref.hpp>
#include <dirent.h>

namespace Si
{
	namespace linux
	{
		struct file_notification
		{
			boost::uint32_t mask;
			path name;
		};

		struct inotify_observable
		{
			typedef std::vector<file_notification> element_type;

			inotify_observable() BOOST_NOEXCEPT
			{
			}

			explicit inotify_observable(boost::asio::io_service &io)
				: notifier(Si::make_unique<boost::asio::posix::stream_descriptor>(boost::ref(io)))
			{
				int fd = inotify_init();
				if (fd < 0)
				{
					throw boost::system::system_error(errno, boost::system::posix_category);
				}
				try
				{
					notifier->assign(fd);
				}
				catch (...)
				{
					close(fd);
					throw;
				}
			}

			error_or<watch_descriptor> watch(boost::filesystem::path const &target, boost::uint32_t mask) BOOST_NOEXCEPT
			{
				assert(notifier);
				int const wd = inotify_add_watch(notifier->native_handle(), target.c_str(), mask);
				if (wd < 0)
				{
					return boost::system::error_code(errno, boost::system::posix_category);
				}
				return watch_descriptor(notifier->native_handle(), wd);
			}

			template <class Observer>
			void async_get_one(Observer &&receiver)
			{
				std::size_t const min_buffer_size = sizeof(inotify_event) + NAME_MAX + 1;
				std::size_t const additional_buffer = 8192;
				read_buffer.resize(min_buffer_size + additional_buffer);
				assert(notifier);
				notifier->async_read_some(
					boost::asio::buffer(read_buffer),
					[this, receiver = std::forward<Observer>(receiver)](boost::system::error_code error, std::size_t bytes_read) mutable
				{
					if (error)
					{
						if (error == boost::asio::error::operation_aborted)
						{
							return;
						}
						throw std::logic_error("not implemented");
					}
					else
					{
						std::vector<file_notification> changes;
						for (std::size_t i = 0; i < bytes_read; )
						{
							inotify_event const &event = *reinterpret_cast<inotify_event const *>(read_buffer.data() + i);
							changes.emplace_back(file_notification{event.mask, path(event.name + 0, std::find(event.name + 0, event.name + event.len, '\0'))});
							i += sizeof(inotify_event);
							i += event.len;
						}
						std::forward<Observer>(receiver).got_element(std::move(changes));
					}
				});
			}

		private:

			std::unique_ptr<boost::asio::posix::stream_descriptor> notifier;
			std::vector<char> read_buffer;
		};
	}
}

#endif
<|endoftext|>


<commit_before>//
//  ScatterPlots.cpp
//  PlaySPLOM
//
//  Created by Chris Sattinger on 12/10/15.
//  Copyright 2015 Chris Sattinger
//
//

#include "ScatterPlots.hpp"
#include <vector>
#include <set>
#include "ofMain.h"
#include "mapping.hpp"

void ScatterPlots::draw() {
    // always set color to white before drawing an FBO to main
    ofSetColor(255, 255, 255);
    plotterFbo.draw(0, 0);

    if (!brush.hoveringBox.isIdentityBox()) {
        ofPushMatrix();
        // unflip opengl so that origin is bottom left, going up
        glTranslated(0, plotterFbo.getHeight(), 0);
        glScalef(1, -1, 1);
        {
            // hovering box
            if (!brush.hoveringBox.isNull()) {
                ofNoFill();
                auto boxFrame = boxFrameAt(brush.hoveringBox);
                ofSetColor(brush.engaged ? engagedFrameColor : hoverFrameColor);
                ofDrawRectangle(boxFrame);
                auto counterPartFrame = boxFrameAt(brush.hoveringBox.n, brush.hoveringBox.m);
                ofDrawRectangle(counterPartFrame);
                // fill the two identity boxes dark with white label
                if (brush.engaged) {
                    ofFill();
                    ofSetColor(inverseBoxColor);
                    auto boxM = boxFrameAt(brush.hoveringBox.m, brush.hoveringBox.m);
                    ofDrawRectangle(boxM);
                    auto boxN = boxFrameAt(brush.hoveringBox.n, brush.hoveringBox.n);
                    ofDrawRectangle(boxN);
                    // labels
                    ofSetColor(inverseTextColor);
                    ofDrawBitmapString(titles[brush.hoveringBox.m], boxM.x + gutter, boxM.y + boxFrame.height / 2);
                    ofDrawBitmapString(titles[brush.hoveringBox.n], boxN.x + gutter, boxN.y + boxFrame.height / 2);
                }
            }
            brush.draw();
            highlightPoints(brush.pointsUnderBrush,
                            brush.engaged ? engagedBrushColor : hoverPointColor,
                            brush.engaged);
        }
        ofPopMatrix();
    }
}

void ScatterPlots::redrawPlotter() {
    plotterFbo.begin();
    ofClear(plotterBackground.r, plotterBackground.b, plotterBackground.g, plotterBackground.a);

    ofPushMatrix();
    ofPushStyle();
    {
        // unflip opengl so that origin is bottom left, going up
        glTranslated(0, plotterFbo.getHeight(), 0);
        glScalef(1, -1, 1);

        // outer border
        ofSetColor(borderColor);
        ofNoFill();
        ofDrawRectangle(frame.x, frame.y, frame.width, frame.height);

        ofSetCircleResolution(pointRadius * 4);
        // auto&& access by reference
        for (auto &box : boxes) {
            if (box.m != box.n) {
              // border
              ofSetColor(borderColor);
              ofNoFill();
              ofDrawRectangle(box.frame);

              ofSetColor(pointColor);
              ofFill();
              ofPushMatrix(); {
                  ofTranslate(box.frame.x, box.frame.y);
                  for (auto &point : box.points) {
                      ofDrawCircle(
                                   point.x * box.frame.width,
                                   point.y * box.frame.height,
                                   pointRadius);
                  }
                  // label each combo box (temporary)
                  char label[20];
                  snprintf(label, sizeof(label), "%d,%d", box.m, box.n);
                  ofSetColor(labelColor);
                  ofDrawBitmapString(label, gutter, gutter);
              } ofPopMatrix();
            } else {
                // identity box: draw the label
                ofSetColor(labelColor);
                ofPushMatrix();
                ofTranslate(box.frame.x, box.frame.y);
                ofDrawBitmapString(titles[box.m], gutter, box.frame.height / 2);
                ofPopMatrix();
            }
        }
    }
    ofPopStyle();
    ofPopMatrix();
    plotterFbo.end();
}

void ScatterPlots::highlightPoints(const set<int> &points, const ofColor &color, bool fill) {
    ofSetColor(color);
    if (fill) {
        ofFill();
    } else {
        ofNoFill();
    }
    ofSetCircleResolution(pointRadius * 4);
    for (auto &box : boxes) {
        if (box.m != box.n) {
            ofPushMatrix(); {
                ofTranslate(box.frame.x, box.frame.y);
                for (auto p : points) {
                    ofDrawCircle(
                                 box.points[p].x * box.frame.width,
                                 box.points[p].y * box.frame.height,
                                 pointRadius);
                }
            } ofPopMatrix();
        }
    }
}

void ScatterPlots::setFrame(ofRectangle rect) {
    frame = rect;
    updateBoxSizes();
    if (plotterFbo.isAllocated()) {
        plotterFbo.clear();
    }
    plotterFbo.allocate(rect.width, rect.height, GL_RGBA);  // 32F_ARB
    redrawPlotter();
}

void ScatterPlots::updateBoxSizes() {
    if (numDimensions > 0) {
        boxWidth = (frame.width - gutter) / numDimensions;
        boxHeight = (frame.height - gutter) / numDimensions;
    } else {
        boxWidth = frame.width - gutter;
        boxHeight = frame.height - gutter;
    }
    if (boxWidth < boxHeight) {
        boxHeight = boxWidth;
    } else {
        boxWidth = boxHeight;
    }
    // center them in the frame
    auto leftMargin = (frame.width -  (boxWidth * numDimensions)) / 2;
    // and move them up the top
    auto bottomMargin = (frame.height -  (boxHeight * numDimensions));
    for (auto &box : boxes) {
        box.frame.x = box.m * boxWidth + gutter + leftMargin;
        box.frame.y = (numDimensions - box.n - 1) * boxHeight + bottomMargin;
        box.frame.width = boxWidth - gutter;
        box.frame.height = boxHeight - gutter;
    }
}

void ScatterPlots::setData(const DataSource& dataSource) {
    numDimensions = dataSource.numDimensions;
    boxes.clear();
    titles = dataSource.titles;

    // create boxes with normalized point sets
    for (int m = 0; m < numDimensions; m++) {
        for (int n = 0; n < numDimensions; n++) {
            Box box = Box(m, n);
            for (auto point : dataSource.points) {
                auto x = linlin(point[m],
                  dataSource.mins[m],
                  dataSource.maxes[m]);
                auto y = linlin(point[n],
                  dataSource.mins[n],
                  dataSource.maxes[n]);
                ofPoint normalizedPoint = ofPoint(x, y);
                box.points.push_back(normalizedPoint);
            }
            boxes.push_back(box);
        }
    }
    updateBoxSizes();
    redrawPlotter();
}

BoxCoordinates ScatterPlots::boxForPoint(int x, int y) {
    // TODO(crucialfelix): calculate don't iterate
    for (auto box : boxes) {
        if (box.frame.inside(x, y)) {
            return BoxCoordinates(box.m, box.n);
        }
    }
    // null
    return BoxCoordinates();
}

ofRectangle ScatterPlots::boxFrameAt(const BoxCoordinates &coords) {
    // TODO(crucialfelix): use a map
    for (auto box : boxes) {
        if (box.m == coords.m && box.n == coords.n) {
            return box.frame;
        }
    }
    return ofRectangle();
}

ofRectangle ScatterPlots::boxFrameAt(int m, int n) {
    // TODO(crucialfelix): use a map
    for (auto box : boxes) {
        if (box.m == m && box.n == n) {
            return box.frame;
        }
    }
    return ofRectangle();
}

vector<ofPoint> ScatterPlots::normalizedPointsAtBox(const BoxCoordinates &coords) {
    // TODO(crucialfelix): use a map
    for (auto box : boxes) {
        if (box.m == coords.m && box.n == coords.n) {
            return box.points;
        }
    }
    // empty set
    return vector<ofPoint>();
}
<commit_msg>remove useless outer border<commit_after>//
//  ScatterPlots.cpp
//  PlaySPLOM
//
//  Created by Chris Sattinger on 12/10/15.
//  Copyright 2015 Chris Sattinger
//
//

#include "ScatterPlots.hpp"
#include <vector>
#include <set>
#include "ofMain.h"
#include "mapping.hpp"

void ScatterPlots::draw() {
    // always set color to white before drawing an FBO to main
    ofSetColor(255, 255, 255);
    plotterFbo.draw(0, 0);

    if (!brush.hoveringBox.isIdentityBox()) {
        ofPushMatrix();
        // unflip opengl so that origin is bottom left, going up
        glTranslated(0, plotterFbo.getHeight(), 0);
        glScalef(1, -1, 1);
        {
            // hovering box
            if (!brush.hoveringBox.isNull()) {
                ofNoFill();
                auto boxFrame = boxFrameAt(brush.hoveringBox);
                ofSetColor(brush.engaged ? engagedFrameColor : hoverFrameColor);
                ofDrawRectangle(boxFrame);
                auto counterPartFrame = boxFrameAt(brush.hoveringBox.n, brush.hoveringBox.m);
                ofDrawRectangle(counterPartFrame);
                // fill the two identity boxes dark with white label
                if (brush.engaged) {
                    ofFill();
                    ofSetColor(inverseBoxColor);
                    auto boxM = boxFrameAt(brush.hoveringBox.m, brush.hoveringBox.m);
                    ofDrawRectangle(boxM);
                    auto boxN = boxFrameAt(brush.hoveringBox.n, brush.hoveringBox.n);
                    ofDrawRectangle(boxN);
                    // labels
                    ofSetColor(inverseTextColor);
                    ofDrawBitmapString(titles[brush.hoveringBox.m], boxM.x + gutter, boxM.y + boxFrame.height / 2);
                    ofDrawBitmapString(titles[brush.hoveringBox.n], boxN.x + gutter, boxN.y + boxFrame.height / 2);
                }
            }
            brush.draw();
            highlightPoints(brush.pointsUnderBrush,
                            brush.engaged ? engagedBrushColor : hoverPointColor,
                            brush.engaged);
        }
        ofPopMatrix();
    }
}

void ScatterPlots::redrawPlotter() {
    plotterFbo.begin();
    ofClear(plotterBackground.r, plotterBackground.b, plotterBackground.g, plotterBackground.a);

    ofPushMatrix();
    ofPushStyle();
    {
        // unflip opengl so that origin is bottom left, going up
        glTranslated(0, plotterFbo.getHeight(), 0);
        glScalef(1, -1, 1);

        ofSetCircleResolution(pointRadius * 4);
        // auto&& access by reference
        for (auto &box : boxes) {
            if (box.m != box.n) {
              // border
              ofSetColor(borderColor);
              ofNoFill();
              ofDrawRectangle(box.frame);

              ofSetColor(pointColor);
              ofFill();
              ofPushMatrix(); {
                  ofTranslate(box.frame.x, box.frame.y);
                  for (auto &point : box.points) {
                      ofDrawCircle(
                                   point.x * box.frame.width,
                                   point.y * box.frame.height,
                                   pointRadius);
                  }
                  // label each combo box (temporary)
                  char label[20];
                  snprintf(label, sizeof(label), "%d,%d", box.m, box.n);
                  ofSetColor(labelColor);
                  ofDrawBitmapString(label, gutter, gutter);
              } ofPopMatrix();
            } else {
                // identity box: draw the label
                ofSetColor(labelColor);
                ofPushMatrix();
                ofTranslate(box.frame.x, box.frame.y);
                ofDrawBitmapString(titles[box.m], gutter, box.frame.height / 2);
                ofPopMatrix();
            }
        }
    }
    ofPopStyle();
    ofPopMatrix();
    plotterFbo.end();
}

void ScatterPlots::highlightPoints(const set<int> &points, const ofColor &color, bool fill) {
    ofSetColor(color);
    if (fill) {
        ofFill();
    } else {
        ofNoFill();
    }
    ofSetCircleResolution(pointRadius * 4);
    for (auto &box : boxes) {
        if (box.m != box.n) {
            ofPushMatrix(); {
                ofTranslate(box.frame.x, box.frame.y);
                for (auto p : points) {
                    ofDrawCircle(
                                 box.points[p].x * box.frame.width,
                                 box.points[p].y * box.frame.height,
                                 pointRadius);
                }
            } ofPopMatrix();
        }
    }
}

void ScatterPlots::setFrame(ofRectangle rect) {
    frame = rect;
    updateBoxSizes();
    if (plotterFbo.isAllocated()) {
        plotterFbo.clear();
    }
    plotterFbo.allocate(rect.width, rect.height, GL_RGBA);  // 32F_ARB
    redrawPlotter();
}

void ScatterPlots::updateBoxSizes() {
    if (numDimensions > 0) {
        boxWidth = (frame.width - gutter) / numDimensions;
        boxHeight = (frame.height - gutter) / numDimensions;
    } else {
        boxWidth = frame.width - gutter;
        boxHeight = frame.height - gutter;
    }
    if (boxWidth < boxHeight) {
        boxHeight = boxWidth;
    } else {
        boxWidth = boxHeight;
    }
    // center them in the frame
    auto leftMargin = (frame.width -  (boxWidth * numDimensions)) / 2;
    // and move them up the top
    auto bottomMargin = (frame.height -  (boxHeight * numDimensions));
    for (auto &box : boxes) {
        box.frame.x = box.m * boxWidth + gutter + leftMargin;
        box.frame.y = (numDimensions - box.n - 1) * boxHeight + bottomMargin;
        box.frame.width = boxWidth - gutter;
        box.frame.height = boxHeight - gutter;
    }
}

void ScatterPlots::setData(const DataSource& dataSource) {
    numDimensions = dataSource.numDimensions;
    boxes.clear();
    titles = dataSource.titles;

    // create boxes with normalized point sets
    for (int m = 0; m < numDimensions; m++) {
        for (int n = 0; n < numDimensions; n++) {
            Box box = Box(m, n);
            for (auto point : dataSource.points) {
                auto x = linlin(point[m],
                  dataSource.mins[m],
                  dataSource.maxes[m]);
                auto y = linlin(point[n],
                  dataSource.mins[n],
                  dataSource.maxes[n]);
                ofPoint normalizedPoint = ofPoint(x, y);
                box.points.push_back(normalizedPoint);
            }
            boxes.push_back(box);
        }
    }
    updateBoxSizes();
    redrawPlotter();
}

BoxCoordinates ScatterPlots::boxForPoint(int x, int y) {
    // TODO(crucialfelix): calculate don't iterate
    for (auto box : boxes) {
        if (box.frame.inside(x, y)) {
            return BoxCoordinates(box.m, box.n);
        }
    }
    // null
    return BoxCoordinates();
}

ofRectangle ScatterPlots::boxFrameAt(const BoxCoordinates &coords) {
    // TODO(crucialfelix): use a map
    for (auto box : boxes) {
        if (box.m == coords.m && box.n == coords.n) {
            return box.frame;
        }
    }
    return ofRectangle();
}

ofRectangle ScatterPlots::boxFrameAt(int m, int n) {
    // TODO(crucialfelix): use a map
    for (auto box : boxes) {
        if (box.m == m && box.n == n) {
            return box.frame;
        }
    }
    return ofRectangle();
}

vector<ofPoint> ScatterPlots::normalizedPointsAtBox(const BoxCoordinates &coords) {
    // TODO(crucialfelix): use a map
    for (auto box : boxes) {
        if (box.m == coords.m && box.n == coords.n) {
            return box.points;
        }
    }
    // empty set
    return vector<ofPoint>();
}
<|endoftext|>


<commit_before>#include "SpiralAnimation.h"

SpiralAnimation::SpiralAnimation(Display &display) : PathAnimation(display) {
//        setRepeatCount(80);
//        setPeriod(40);
//        setFrameCount(200);

	chaserPaths = {
		ChaserPath(new CandyChaser(0, 0, 0), {0, 1, 2, 3, 4, 5, 6, 14, 22, 30, 38, 46, 45, 44, 43, 35} ),
		ChaserPath(new CandyChaser(60, 10, 00), {7, 15, 23, 31, 39, 47, 55, 54, 53, 52, 51, 50, 42, 34, 26, 27} ),
		ChaserPath(new CandyChaser(120, 0, 10), {63, 62, 61, 60, 59, 58, 57, 49, 41, 33, 25, 17, 18, 19, 20, 28} ),
		ChaserPath(new CandyChaser(180, 10, 0), {56, 48, 40, 32, 24, 16, 8, 9, 10, 11, 12, 13, 21, 29, 37, 36} )
	};

	for (ChaserPath cp : chaserPaths) {
	    cp.chaser->setReverse(true);
	}
}
<commit_msg>Spiral outward<commit_after>#include "SpiralAnimation.h"

SpiralAnimation::SpiralAnimation(Display &display) : PathAnimation(display) {
//        setRepeatCount(80);
//        setPeriod(40);
//        setFrameCount(200);

	chaserPaths = {
		ChaserPath(new CandyChaser(0, 0, 0), {0, 1, 2, 3, 4, 5, 6, 14, 22, 30, 38, 46, 45, 44, 43, 35} ),
		ChaserPath(new CandyChaser(60, 10, 00), {7, 15, 23, 31, 39, 47, 55, 54, 53, 52, 51, 50, 42, 34, 26, 27} ),
		ChaserPath(new CandyChaser(120, 0, 10), {63, 62, 61, 60, 59, 58, 57, 49, 41, 33, 25, 17, 18, 19, 20, 28} ),
		ChaserPath(new CandyChaser(180, 10, 0), {56, 48, 40, 32, 24, 16, 8, 9, 10, 11, 12, 13, 21, 29, 37, 36} )
	};

	for (ChaserPath cp : chaserPaths) {
	    cp.chaser->setReverse(false);
	}
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/test/testsupport/metrics/video_metrics.h"

#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/test/testsupport/fileutils.h"
#include "webrtc/test/testsupport/gtest_disable.h"

namespace webrtc {

static const char* kEmptyFileName = "video_metrics_unittest_empty_file.tmp";
static const char* kNonExistingFileName = "video_metrics_unittest_non_existing";
static const int kWidth = 352;
static const int kHeight = 288;

static const int kMissingReferenceFileReturnCode = -1;
static const int kMissingTestFileReturnCode = -2;
static const int kEmptyFileReturnCode = -3;
static const double kPsnrPerfectResult =  48.0;
static const double kSsimPerfectResult = 1.0;

class VideoMetricsTest: public testing::Test {
 protected:
  VideoMetricsTest() {
    video_file_ = webrtc::test::ResourcePath("foreman_cif_short", "yuv");
  }
  virtual ~VideoMetricsTest() {}
  void SetUp() {
    // Create an empty file:
    FILE* dummy = fopen(kEmptyFileName, "wb");
    fclose(dummy);
  }
  void TearDown() {
    remove(kEmptyFileName);
  }
  webrtc::test::QualityMetricsResult psnr_result_;
  webrtc::test::QualityMetricsResult ssim_result_;
  std::string video_file_;
};

// Tests that it is possible to run with the same reference as test file
TEST_F(VideoMetricsTest,
       DISABLED_ON_ANDROID(ReturnsPerfectResultForIdenticalFilesPSNR)) {
  EXPECT_EQ(0, I420PSNRFromFiles(video_file_.c_str(), video_file_.c_str(),
                                 kWidth, kHeight, &psnr_result_));
  EXPECT_EQ(kPsnrPerfectResult, psnr_result_.average);
}

TEST_F(VideoMetricsTest,
       DISABLED_ON_ANDROID(ReturnsPerfectResultForIdenticalFilesSSIM)) {
  EXPECT_EQ(0, I420SSIMFromFiles(video_file_.c_str(), video_file_.c_str(),
                                 kWidth, kHeight, &ssim_result_));
  EXPECT_EQ(kSsimPerfectResult, ssim_result_.average);
}

TEST_F(VideoMetricsTest,
       DISABLED_ON_ANDROID(ReturnsPerfectResultForIdenticalFilesBothMetrics)) {
  EXPECT_EQ(0, I420MetricsFromFiles(video_file_.c_str(), video_file_.c_str(),
                                    kWidth, kHeight, &psnr_result_,
                                    &ssim_result_));
  EXPECT_EQ(kPsnrPerfectResult, psnr_result_.average);
  EXPECT_EQ(kSsimPerfectResult, ssim_result_.average);
}

// Tests that the right return code is given when the reference file is missing.
TEST_F(VideoMetricsTest, DISABLED_ON_ANDROID(MissingReferenceFilePSNR)) {
  EXPECT_EQ(kMissingReferenceFileReturnCode,
            I420PSNRFromFiles(kNonExistingFileName, video_file_.c_str(),
                              kWidth, kHeight, &ssim_result_));
}

TEST_F(VideoMetricsTest, DISABLED_ON_ANDROID(MissingReferenceFileSSIM)) {
  EXPECT_EQ(kMissingReferenceFileReturnCode,
            I420SSIMFromFiles(kNonExistingFileName, video_file_.c_str(),
                              kWidth, kHeight, &ssim_result_));
}

TEST_F(VideoMetricsTest, DISABLED_ON_ANDROID(MissingReferenceFileBothMetrics)) {
  EXPECT_EQ(kMissingReferenceFileReturnCode,
            I420MetricsFromFiles(kNonExistingFileName, video_file_.c_str(),
                                 kWidth, kHeight,
                                 &psnr_result_, &ssim_result_));
}

// Tests that the right return code is given when the test file is missing.
TEST_F(VideoMetricsTest, DISABLED_ON_ANDROID(MissingTestFilePSNR)) {
  EXPECT_EQ(kMissingTestFileReturnCode,
            I420PSNRFromFiles(video_file_.c_str(), kNonExistingFileName,
                              kWidth, kHeight, &ssim_result_));
}

TEST_F(VideoMetricsTest, DISABLED_ON_ANDROID(MissingTestFileSSIM)) {
  EXPECT_EQ(kMissingTestFileReturnCode,
            I420SSIMFromFiles(video_file_.c_str(), kNonExistingFileName,
                              kWidth, kHeight, &ssim_result_));
}

TEST_F(VideoMetricsTest, DISABLED_ON_ANDROID(MissingTestFileBothMetrics)) {
  EXPECT_EQ(kMissingTestFileReturnCode,
            I420MetricsFromFiles(video_file_.c_str(), kNonExistingFileName,
                                 kWidth, kHeight,
                                 &psnr_result_, &ssim_result_));
}

// Tests that the method can be executed with empty files.
TEST_F(VideoMetricsTest, DISABLED_ON_ANDROID(EmptyFilesPSNR)) {
  EXPECT_EQ(kEmptyFileReturnCode,
            I420PSNRFromFiles(kEmptyFileName, video_file_.c_str(),
                              kWidth, kHeight, &ssim_result_));
  EXPECT_EQ(kEmptyFileReturnCode,
            I420PSNRFromFiles(video_file_.c_str(), kEmptyFileName,
                              kWidth, kHeight, &ssim_result_));
}

TEST_F(VideoMetricsTest, DISABLED_ON_ANDROID(EmptyFilesSSIM)) {
  EXPECT_EQ(kEmptyFileReturnCode,
            I420SSIMFromFiles(kEmptyFileName, video_file_.c_str(),
                              kWidth, kHeight, &ssim_result_));
  EXPECT_EQ(kEmptyFileReturnCode,
            I420SSIMFromFiles(video_file_.c_str(), kEmptyFileName,
                              kWidth, kHeight, &ssim_result_));
}

TEST_F(VideoMetricsTest, DISABLED_ON_ANDROID(EmptyFilesBothMetrics)) {
  EXPECT_EQ(kEmptyFileReturnCode,
            I420MetricsFromFiles(kEmptyFileName, video_file_.c_str(),
                                 kWidth, kHeight,
                                 &psnr_result_, &ssim_result_));
  EXPECT_EQ(kEmptyFileReturnCode,
              I420MetricsFromFiles(video_file_.c_str(), kEmptyFileName,
                                   kWidth, kHeight,
                                   &psnr_result_, &ssim_result_));
}

// Dummy test to get at least one test in this executable for Android
// (otherwise gtest will fail execution on Android).
// TODO(kjellander): Remove when the other tests have been fixed for
// Android.
TEST_F(VideoMetricsTest, DummyTest) {
}

}  // namespace webrtc
<commit_msg>Fix metrics_unittests on Android.<commit_after>/*
 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/test/testsupport/metrics/video_metrics.h"

#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/test/testsupport/fileutils.h"

namespace webrtc {

static const char* kNonExistingFileName = "video_metrics_unittest_non_existing";
static const int kWidth = 352;
static const int kHeight = 288;

static const int kMissingReferenceFileReturnCode = -1;
static const int kMissingTestFileReturnCode = -2;
static const int kEmptyFileReturnCode = -3;
static const double kPsnrPerfectResult =  48.0;
static const double kSsimPerfectResult = 1.0;

class VideoMetricsTest: public testing::Test {
 protected:
  VideoMetricsTest() {
    empty_file_ = webrtc::test::OutputPath() +
        "video_metrics_unittest_empty_file.tmp";
    video_file_ = webrtc::test::ResourcePath("foreman_cif_short", "yuv");
  }
  virtual ~VideoMetricsTest() {}
  void SetUp() {
    // Create an empty file:
    FILE* dummy = fopen(empty_file_.c_str(), "wb");
    fclose(dummy);
  }
  void TearDown() {
    remove(empty_file_.c_str());
  }
  webrtc::test::QualityMetricsResult psnr_result_;
  webrtc::test::QualityMetricsResult ssim_result_;
  std::string empty_file_;
  std::string video_file_;
};

// Tests that it is possible to run with the same reference as test file
TEST_F(VideoMetricsTest, ReturnsPerfectResultForIdenticalFilesPSNR) {
  EXPECT_EQ(0, I420PSNRFromFiles(video_file_.c_str(), video_file_.c_str(),
                                 kWidth, kHeight, &psnr_result_));
  EXPECT_EQ(kPsnrPerfectResult, psnr_result_.average);
}

TEST_F(VideoMetricsTest, ReturnsPerfectResultForIdenticalFilesSSIM) {
  EXPECT_EQ(0, I420SSIMFromFiles(video_file_.c_str(), video_file_.c_str(),
                                 kWidth, kHeight, &ssim_result_));
  EXPECT_EQ(kSsimPerfectResult, ssim_result_.average);
}

TEST_F(VideoMetricsTest, ReturnsPerfectResultForIdenticalFilesBothMetrics) {
  EXPECT_EQ(0, I420MetricsFromFiles(video_file_.c_str(), video_file_.c_str(),
                                    kWidth, kHeight, &psnr_result_,
                                    &ssim_result_));
  EXPECT_EQ(kPsnrPerfectResult, psnr_result_.average);
  EXPECT_EQ(kSsimPerfectResult, ssim_result_.average);
}

// Tests that the right return code is given when the reference file is missing.
TEST_F(VideoMetricsTest, MissingReferenceFilePSNR) {
  EXPECT_EQ(kMissingReferenceFileReturnCode,
            I420PSNRFromFiles(kNonExistingFileName, video_file_.c_str(),
                              kWidth, kHeight, &ssim_result_));
}

TEST_F(VideoMetricsTest, MissingReferenceFileSSIM) {
  EXPECT_EQ(kMissingReferenceFileReturnCode,
            I420SSIMFromFiles(kNonExistingFileName, video_file_.c_str(),
                              kWidth, kHeight, &ssim_result_));
}

TEST_F(VideoMetricsTest, MissingReferenceFileBothMetrics) {
  EXPECT_EQ(kMissingReferenceFileReturnCode,
            I420MetricsFromFiles(kNonExistingFileName, video_file_.c_str(),
                                 kWidth, kHeight,
                                 &psnr_result_, &ssim_result_));
}

// Tests that the right return code is given when the test file is missing.
TEST_F(VideoMetricsTest, MissingTestFilePSNR) {
  EXPECT_EQ(kMissingTestFileReturnCode,
            I420PSNRFromFiles(video_file_.c_str(), kNonExistingFileName,
                              kWidth, kHeight, &ssim_result_));
}

TEST_F(VideoMetricsTest, MissingTestFileSSIM) {
  EXPECT_EQ(kMissingTestFileReturnCode,
            I420SSIMFromFiles(video_file_.c_str(), kNonExistingFileName,
                              kWidth, kHeight, &ssim_result_));
}

TEST_F(VideoMetricsTest, MissingTestFileBothMetrics) {
  EXPECT_EQ(kMissingTestFileReturnCode,
            I420MetricsFromFiles(video_file_.c_str(), kNonExistingFileName,
                                 kWidth, kHeight,
                                 &psnr_result_, &ssim_result_));
}

// Tests that the method can be executed with empty files.
TEST_F(VideoMetricsTest, EmptyFilesPSNR) {
  EXPECT_EQ(kEmptyFileReturnCode,
            I420PSNRFromFiles(empty_file_.c_str(), video_file_.c_str(),
                              kWidth, kHeight, &ssim_result_));
  EXPECT_EQ(kEmptyFileReturnCode,
            I420PSNRFromFiles(video_file_.c_str(), empty_file_.c_str(),
                              kWidth, kHeight, &ssim_result_));
}

TEST_F(VideoMetricsTest, EmptyFilesSSIM) {
  EXPECT_EQ(kEmptyFileReturnCode,
            I420SSIMFromFiles(empty_file_.c_str(), video_file_.c_str(),
                              kWidth, kHeight, &ssim_result_));
  EXPECT_EQ(kEmptyFileReturnCode,
            I420SSIMFromFiles(video_file_.c_str(), empty_file_.c_str(),
                              kWidth, kHeight, &ssim_result_));
}

TEST_F(VideoMetricsTest, EmptyFilesBothMetrics) {
  EXPECT_EQ(kEmptyFileReturnCode,
            I420MetricsFromFiles(empty_file_.c_str(), video_file_.c_str(),
                                 kWidth, kHeight,
                                 &psnr_result_, &ssim_result_));
  EXPECT_EQ(kEmptyFileReturnCode,
              I420MetricsFromFiles(video_file_.c_str(), empty_file_.c_str(),
                                   kWidth, kHeight,
                                   &psnr_result_, &ssim_result_));
}

}  // namespace webrtc
<|endoftext|>


<commit_before>//=============================================================================================================
/**
* @file     test_edf2fiff_rwr.cpp
* @author   Simon Heinke <simon.heinke@tu-ilmenau.de>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     August, 2019
*
* @section  LICENSE
*
* Copyright (C) 2019, Simon Heinke and Matti Hamalainen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
*       following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
*       the following disclaimer in the documentation and/or other materials provided with the distribution.
*     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
*       to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* @brief    Converts the EDF file into a Fiff file and tests whether the raw values are identical.
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include <algorithm>

#include <fiff/fiff.h>
#include "../../applications/mne_edf2fiff/edf_raw_data.h"

//*************************************************************************************************************
//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QtTest>

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace FIFFLIB;
using namespace EDF2FIFF;
using namespace Eigen;

//=============================================================================================================
/**
* DECLARE CLASS TestEDF2FIFFRWR
*
* @brief The TestEDF2FIFFRWR class performs an EDF-to-Fiff conversion and compares the converted data with
*        the original data from the EDF file.
*
*/
class TestEDF2FIFFRWR: public QObject
{
    Q_OBJECT

public:
    TestEDF2FIFFRWR();

private slots:
    void initTestCase();
    void testEDF2FiffConversion();
    void testEDFReadAndFiffWrite();
    void testFiffReadingAndValueEquality();
    void cleanupTestCase();

private:
    const float m_fTimesliceSeconds = 10.0f; //read and write in 10 sec chunks
    const float m_fEpsilon = 0.000000001f;

    // files:
    QFile* m_pFileIn;
    QFile* m_pFileOut;  // temporary outfile, to be deleted during cleanup

    // EDF / Fiff containers:
    EDFRawData* m_pEDFRaw;
    FiffRawData* m_pFiffRaw;

    // raw data:
    QVector<MatrixXd> m_vRawChunksFromOriginalEDF;
    QVector<MatrixXd> m_vRawChunksFromWrittenFIFF;
};

//*************************************************************************************************************

TestEDF2FIFFRWR::TestEDF2FIFFRWR()
{

}

//*************************************************************************************************************

void TestEDF2FIFFRWR::initTestCase()
{
    m_pFileIn = new QFile(QDir::currentPath() + "/mne-cpp-test-data/EEG/test_reduced.edf");
    m_pFileOut = new QFile(QDir::currentPath() + "/mne-cpp-test-data/EEG/test_reduced_temporary.fif");

    // initialize EDF raw data
    m_pEDFRaw = new EDFRawData(m_pFileIn);

    QVERIFY(m_pEDFRaw->getInfo().getAllChannelInfos().size() != 0);
}

//*************************************************************************************************************

void TestEDF2FIFFRWR::testEDF2FiffConversion()
{
    // convert to fiff
    m_pFiffRaw = new FiffRawData(m_pEDFRaw->toFiffRawData());

    QVERIFY(m_pEDFRaw->getInfo().getMeasurementChannelInfos().size() == m_pFiffRaw->info.nchan);
    QVERIFY(std::abs(m_pEDFRaw->getInfo().getFrequency() - m_pFiffRaw->info.sfreq) <= m_fEpsilon);  // float-comparisons via '==' are unsafe
    QVERIFY(m_pEDFRaw->getInfo().getSampleCount() == m_pFiffRaw->last_samp - m_pFiffRaw->first_samp);
}

//*************************************************************************************************************

void TestEDF2FIFFRWR::testEDFReadAndFiffWrite()
{
    // set up the reading parameters
    int iTimesliceSamples = static_cast<int>(ceil(m_fTimesliceSeconds * m_pFiffRaw->info.sfreq));

    RowVectorXd cals;
    FiffStream::SPtr outfid = FiffStream::start_writing_raw(*m_pFileOut, m_pFiffRaw->info, cals);

    // write start of Fiff file
    fiff_int_t first = 0;  // EDF files start at index 0
    outfid->write_int(FIFF_FIRST_SAMPLE, &first);

    // read chunks, remember how many samples were already read
    int iSamplesRead = 0;
    while(iSamplesRead < m_pEDFRaw->getInfo().getSampleCount()) {
        int iNextChunkSize = std::min(iTimesliceSamples, m_pEDFRaw->getInfo().getSampleCount() - iSamplesRead);
        // EDF sample indexing starts at 0, simply use samplesRead as argument to read_raw_segment
        MatrixXd data = m_pEDFRaw->read_raw_segment(iSamplesRead, iSamplesRead + iNextChunkSize).cast<double>();
        iSamplesRead += iNextChunkSize;
        outfid->write_raw_buffer(data, cals);
        // copy into vector for later comparison with written Fiff file
        m_vRawChunksFromOriginalEDF.append(data);
    }

    outfid->finish_writing_raw();

    QVERIFY(iSamplesRead == m_pEDFRaw->getInfo().getSampleCount());
}

//*************************************************************************************************************

void TestEDF2FIFFRWR::testFiffReadingAndValueEquality()
{
    // close outfile in case it is still open
    m_pFileOut->close();
    // open again
    FiffRawData writtenFiff(*m_pFileOut);

    // set up the reading parameters
    int iTimesliceSamples = static_cast<int>(ceil(m_fTimesliceSeconds * writtenFiff.info.sfreq));
    // read chunks, remember which is the current sample
    int iCurrentSample = writtenFiff.first_samp;
    while(iCurrentSample < writtenFiff.last_samp) {
        // timeslice_samples - 1 because FiffRawData.read_raw_segment has inclusive index arguments
        int iNextChunkSize = std::min(iTimesliceSamples - 1, writtenFiff.last_samp - iCurrentSample);
        MatrixXd data, times;
        writtenFiff.read_raw_segment(data, times, iCurrentSample, iCurrentSample + iNextChunkSize);
        iCurrentSample += iNextChunkSize + 1;  // + 1 because chunkSize of inclusive index arguments (see above)
        // copy into vector for later comparison with original EDF file
        m_vRawChunksFromWrittenFIFF.append(data);
    }

    // compare chunk vectors
    QVERIFY(m_vRawChunksFromOriginalEDF.size() == m_vRawChunksFromWrittenFIFF.size());
    for(int i = 0; i < m_vRawChunksFromOriginalEDF.size(); ++i) {
        const MatrixXd originalEDFChunk = m_vRawChunksFromOriginalEDF[i];
        const MatrixXd writtenFiffChunk = m_vRawChunksFromWrittenFIFF[i];

        if(originalEDFChunk.cols() != writtenFiffChunk.cols() || originalEDFChunk.rows() != writtenFiffChunk.rows()) {
            QFAIL("Found a chunk with mismatching dimensions ...");
        }
        // compare every single raw value
        for(int r = 0; r < originalEDFChunk.rows(); ++r) {
            for(int c = 0; c < originalEDFChunk.cols(); ++c) {
                if(std::abs(originalEDFChunk(r, c) - writtenFiffChunk(r, c)) > static_cast<double>(m_fEpsilon)) {  // double-comparisons via '==' are unsafe
                    QFAIL("Found some non-identical raw values ...");
                }
            }
        }
    }
}

//*************************************************************************************************************

void TestEDF2FIFFRWR::cleanupTestCase()
{
    // destroy containers
    delete m_pFiffRaw;
    delete m_pEDFRaw;

    // close files
    m_pFileOut->close();
    m_pFileIn->close();

    // remove temporary outfile
    m_pFileOut->remove();

    // destroy filehandles
    delete m_pFileOut;
    delete m_pFileIn;
}

//*************************************************************************************************************
//=============================================================================================================
// MAIN
//=============================================================================================================

QTEST_APPLESS_MAIN(TestEDF2FIFFRWR)
#include "test_edf2fiff_rwr.moc"
<commit_msg>fix edf2fiff test<commit_after>//=============================================================================================================
/**
* @file     test_edf2fiff_rwr.cpp
* @author   Simon Heinke <simon.heinke@tu-ilmenau.de>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     August, 2019
*
* @section  LICENSE
*
* Copyright (C) 2019, Simon Heinke and Matti Hamalainen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
*       following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
*       the following disclaimer in the documentation and/or other materials provided with the distribution.
*     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
*       to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* @brief    Converts the EDF file into a Fiff file and tests whether the raw values are identical.
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include <algorithm>

#include <fiff/fiff.h>
#include "../../applications/mne_edf2fiff/edf_raw_data.h"

#include <utils/generics/applicationlogger.h>

//*************************************************************************************************************
//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QtTest>
#include <QProcess>

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace FIFFLIB;
using namespace EDF2FIFF;
using namespace Eigen;

//=============================================================================================================
/**
* DECLARE CLASS TestEDF2FIFFRWR
*
* @brief The TestEDF2FIFFRWR class performs an EDF-to-Fiff conversion and compares the converted data with
*        the original data from the EDF file.
*
*/
class TestEDF2FIFFRWR: public QObject
{
    Q_OBJECT

public:
    TestEDF2FIFFRWR();

private slots:
    void initTestCase();
    void testEDF2FiffConversion();
    void testEDFReadAndFiffWrite();
    void testFiffReadingAndValueEquality();
    void cleanupTestCase();

private:
    const float m_fTimesliceSeconds = 10.0f; //read and write in 10 sec chunks
    const float m_fEpsilon = 0.000000001f;

    // files:
    QFile* m_pFileIn;
    QFile* m_pFileOut;  // temporary outfile, to be deleted during cleanup

    // EDF / Fiff containers:
    EDFRawData* m_pEDFRaw;
    FiffRawData* m_pFiffRaw;

    // raw data:
    QVector<MatrixXd> m_vRawChunksFromOriginalEDF;
    QVector<MatrixXd> m_vRawChunksFromWrittenFIFF;
};

//*************************************************************************************************************

TestEDF2FIFFRWR::TestEDF2FIFFRWR()
{

}

//*************************************************************************************************************

void TestEDF2FIFFRWR::initTestCase()
{
    qInstallMessageHandler(UTILSLIB::ApplicationLogger::customLogWriter);

    m_pFileIn = new QFile(QCoreApplication::applicationDirPath() + "/mne-cpp-test-data/EEG/test_reduced.edf");
    m_pFileOut = new QFile(QCoreApplication::applicationDirPath() + "/mne-cpp-test-data/EEG/test_reduced_temporary.fif");

    // initialize EDF raw data
    m_pEDFRaw = new EDFRawData(m_pFileIn);

    QVERIFY(m_pEDFRaw->getInfo().getAllChannelInfos().size() != 0);
}

//*************************************************************************************************************

void TestEDF2FIFFRWR::testEDF2FiffConversion()
{
    // convert to fiff
    m_pFiffRaw = new FiffRawData(m_pEDFRaw->toFiffRawData());

    QVERIFY(m_pEDFRaw->getInfo().getMeasurementChannelInfos().size() == m_pFiffRaw->info.nchan);
    QVERIFY(std::abs(m_pEDFRaw->getInfo().getFrequency() - m_pFiffRaw->info.sfreq) <= m_fEpsilon);  // float-comparisons via '==' are unsafe
    QVERIFY(m_pEDFRaw->getInfo().getSampleCount() == m_pFiffRaw->last_samp - m_pFiffRaw->first_samp);
}

//*************************************************************************************************************

void TestEDF2FIFFRWR::testEDFReadAndFiffWrite()
{
    // set up the reading parameters
    int iTimesliceSamples = static_cast<int>(ceil(m_fTimesliceSeconds * m_pFiffRaw->info.sfreq));

    RowVectorXd cals;
    FiffStream::SPtr outfid = FiffStream::start_writing_raw(*m_pFileOut, m_pFiffRaw->info, cals);

    // write start of Fiff file
    fiff_int_t first = 0;  // EDF files start at index 0
    outfid->write_int(FIFF_FIRST_SAMPLE, &first);

    // read chunks, remember how many samples were already read
    int iSamplesRead = 0;
    while(iSamplesRead < m_pEDFRaw->getInfo().getSampleCount()) {
        int iNextChunkSize = std::min(iTimesliceSamples, m_pEDFRaw->getInfo().getSampleCount() - iSamplesRead);
        // EDF sample indexing starts at 0, simply use samplesRead as argument to read_raw_segment
        MatrixXd data = m_pEDFRaw->read_raw_segment(iSamplesRead, iSamplesRead + iNextChunkSize).cast<double>();
        iSamplesRead += iNextChunkSize;
        outfid->write_raw_buffer(data, cals);
        // copy into vector for later comparison with written Fiff file
        m_vRawChunksFromOriginalEDF.append(data);
    }

    outfid->finish_writing_raw();

    QVERIFY(iSamplesRead == m_pEDFRaw->getInfo().getSampleCount());
}

//*************************************************************************************************************

void TestEDF2FIFFRWR::testFiffReadingAndValueEquality()
{
    // close outfile in case it is still open
    m_pFileOut->close();
    // open again
    FiffRawData writtenFiff(*m_pFileOut);

    // set up the reading parameters
    int iTimesliceSamples = static_cast<int>(ceil(m_fTimesliceSeconds * writtenFiff.info.sfreq));
    // read chunks, remember which is the current sample
    int iCurrentSample = writtenFiff.first_samp;
    while(iCurrentSample < writtenFiff.last_samp) {
        // timeslice_samples - 1 because FiffRawData.read_raw_segment has inclusive index arguments
        int iNextChunkSize = std::min(iTimesliceSamples - 1, writtenFiff.last_samp - iCurrentSample);
        MatrixXd data, times;
        writtenFiff.read_raw_segment(data, times, iCurrentSample, iCurrentSample + iNextChunkSize);
        iCurrentSample += iNextChunkSize + 1;  // + 1 because chunkSize of inclusive index arguments (see above)
        // copy into vector for later comparison with original EDF file
        m_vRawChunksFromWrittenFIFF.append(data);
    }

    // compare chunk vectors
    QVERIFY(m_vRawChunksFromOriginalEDF.size() == m_vRawChunksFromWrittenFIFF.size());
    for(int i = 0; i < m_vRawChunksFromOriginalEDF.size(); ++i) {
        const MatrixXd originalEDFChunk = m_vRawChunksFromOriginalEDF[i];
        const MatrixXd writtenFiffChunk = m_vRawChunksFromWrittenFIFF[i];

        if(originalEDFChunk.cols() != writtenFiffChunk.cols() || originalEDFChunk.rows() != writtenFiffChunk.rows()) {
            QFAIL("Found a chunk with mismatching dimensions ...");
        }
        // compare every single raw value
        for(int r = 0; r < originalEDFChunk.rows(); ++r) {
            for(int c = 0; c < originalEDFChunk.cols(); ++c) {
                if(std::abs(originalEDFChunk(r, c) - writtenFiffChunk(r, c)) > static_cast<double>(m_fEpsilon)) {  // double-comparisons via '==' are unsafe
                    QFAIL("Found some non-identical raw values ...");
                }
            }
        }
    }
}

//*************************************************************************************************************

void TestEDF2FIFFRWR::cleanupTestCase()
{
    // destroy containers
    delete m_pFiffRaw;
    delete m_pEDFRaw;

    // close files
    m_pFileOut->close();
    m_pFileIn->close();

    // remove temporary outfile
    m_pFileOut->remove();

    // destroy filehandles
    delete m_pFileOut;
    delete m_pFileIn;
}

//*************************************************************************************************************
//=============================================================================================================
// MAIN
//=============================================================================================================

QTEST_GUILESS_MAIN(TestEDF2FIFFRWR)
#include "test_edf2fiff_rwr.moc"
<|endoftext|>


<commit_before>// Copyright 2016 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <vector>
#include <iostream>
#include <exception>
#include <iomanip>
#include <random>

#include <configuration.hpp>

#include <ArgumentList.hpp>
#include <InitializeOpenCL.hpp>
#include <Kernel.hpp>
#include <Stencil.hpp>
#include <utils.hpp>
#include <Timer.hpp>
#include <Stats.hpp>

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< inputDataType > * input, cl::Buffer * input_d, cl::Buffer * output_d, const unsigned int outputSize);

int main(int argc, char * argv[]) {
  bool reInit = true;
  unsigned int nrIterations = 0;
  unsigned int samplingFactor = 100;
  unsigned int clPlatformID = 0;
  unsigned int clDeviceID = 0;
  unsigned int vectorSize = 0;
  unsigned int maxThreads = 0;
  unsigned int maxItems = 0;
  unsigned int matrixWidth = 0;
  unsigned int padding = 0;
  // Random number generation
  std::random_device randomDevice;
  std::default_random_engine randomEngine(randomDevice());
  std::uniform_int_distribution<unsigned int> uniformDistribution(0, magicValue);

  try {
    isa::utils::ArgumentList args(argc, argv);

    clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
    clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
    if ( args.getSwitch("-sampling") ) {
      samplingFactor = args.getSwitchArgument< unsigned int >("-factor");
    }
    nrIterations = args.getSwitchArgument< unsigned int >("-iterations");
    vectorSize = args.getSwitchArgument< unsigned int >("-vector");
    padding = args.getSwitchArgument< unsigned int >("-padding");
    maxThreads = args.getSwitchArgument< unsigned int >("-max_threads");
    maxItems = args.getSwitchArgument< unsigned int >("-max_items");
    matrixWidth = args.getSwitchArgument< unsigned int >("-matrix_width");
    conf.setLocalMemory(args.getSwitch("-local"));
  } catch ( isa::utils::EmptyCommandLine & err ) {
    std::cerr << argv[0] << " -opencl_platform ... -opencl_device ... [-sampling -factor ...] -iterations ... -vector ... -padding ... -max_threads ... -max_items ... -matrix_width ... [-local]" << std::endl;
    return 1;
  } catch ( std::exception & err ) {
    std::cerr << err.what() << std::endl;
    return 1;
  }

  cl::Context clContext;
  std::vector< cl::Platform > * clPlatforms = new std::vector< cl::Platform >();
  std::vector< cl::Device > * clDevices = new std::vector< cl::Device >();
  std::vector< std::vector< cl::CommandQueue > > * clQueues = 0;

  // Allocate host memory
  std::vector< inputDataType > input((matrixWidth + 2) * isa::utils::pad(matrixWidth + 2, padding)), output(matrixWidth * isa::utils::pad(matrixWidth, padding)), output_c;
  cl::Buffer input_d, output_d;

  for ( unsigned int y = 0; y < matrixWidth + 2; y++ ) {
    for ( unsigned int x = 0; x < matrixWidth + 2; x++ ) {
      if ( y == 0 || y == (matrixWidth - 1) ) {
        input[(y * isa::utils::pad(matrixWidth + 2, padding)) + x] = 0;
      } else if ( x == 0 || x == (matrixWidth - 1) ) {
        input[(y * isa::utils::pad(matrixWidth + 2, padding)) + x] = 0;
      } else {
        input[(y * isa::utils::pad(matrixWidth + 2, padding)) + x] = uniformDistribution(randomEngine);
      }
    }
  }
  output_c.resize(output.size());

  // Run the control
  TuneBench::stencil2D(input, output_c, matrixWidth, padding);

  // Generate tuning configurations
  std::vector<TuneBench::StencilConf> configurations;
  for ( unsigned int threadsD0 = vectorSize; threadsD0 <= maxThreads; threadsD0 += vectorSize) {
    for ( unsigned int threadsD1 = 1; threadsD0 * threadsD1 <= maxThreads; threadsD1++ ) {
      for ( unsigned int itemsD0 = 1; itemsD0 <= maxItems; itemsD0++ ) {
        if ( matrixWidth % (threadsD0 * itemsD0) != 0 ) {
          continue;
        }
        for ( unsigned int itemsD1 = 1; itemsD0 * itemsD1 <= maxItems; itemsD1++ ) {
          if ( matrixWidth % (threadsD1 * itemsD1) != 0 ) {
            continue;
          }
          TuneBench::StencilConf configuration;
          configuration.setNrThreadsD0(threadsD0);
          configuration.setNrThreadsD1(threadsD1);
          configuration.setNrItemsD0(itemsD0);
          configuration.setNrItemsD1(itemsD1);
          configurations.push_back(configuration);
        }
      }
    }
  }
  if ( samplingFactor < 100 ) {
    unsigned int newSize = static_cast<unsigned int>((configurations.size() * samplingFactor) / 100.0);
    std::shuffle(configurations.begin(), configurations.end(), randomEngine);
    configurations.resize(newSize);
  }

  std::cout << std::fixed << std::endl;
  std::cout << "# matrixWidth *configuration* GFLOP/s time stdDeviation COV" << std::endl << std::endl;

  for ( auto configuration = configurations.begin(); configuration != configurations.end(); ++configuration ) {
    // Generate kernel
    double gflops = isa::utils::giga(static_cast< uint64_t >(matrixWidth) * matrixWidth * 18.0);
    cl::Event clEvent;
    cl::Kernel * kernel;
    isa::utils::Timer timer;
    std::string * code = TuneBench::getStencil2DOpenCL(*configuration, inputDataName, matrixWidth, padding);

    if ( reInit ) {
      delete clQueues;
      clQueues = new std::vector< std::vector< cl::CommandQueue > >();
      isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, &clContext, clDevices, clQueues);
      try {
        initializeDeviceMemory(clContext, &(clQueues->at(clDeviceID)[0]), &input, &input_d, &output_d, output.size());
      } catch ( cl::Error & err ) {
        return -1;
      }
      reInit = false;
    }
    try {
      kernel = isa::OpenCL::compile("stencil2D", *code, "-cl-mad-enable -Werror", clContext, clDevices->at(clDeviceID));
    } catch ( isa::OpenCL::OpenCLError & err ) {
      std::cerr << err.what() << std::endl;
      delete code;
      break;
    }
    delete code;

    cl::NDRange global(matrixWidth / *configuration.getNrItemsD0(), matrixWidth / *configuration.getNrItemsD1());
    cl::NDRange local(*configuration.getNrThreadsD0(), *configuration.getNrThreadsD1());

    kernel->setArg(0, input_d);
    kernel->setArg(1, output_d);

    try {
      // Warm-up run
      clQueues->at(clDeviceID)[0].finish();
      clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &clEvent);
      clEvent.wait();
      // Tuning runs
      for ( unsigned int iteration = 0; iteration < nrIterations; iteration++ ) {
        timer.start();
        clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &clEvent);
        clEvent.wait();
        timer.stop();
      }
      clQueues->at(clDeviceID)[0].enqueueReadBuffer(output_d, CL_TRUE, 0, output.size() * sizeof(inputDataType), reinterpret_cast< void * >(output.data()), 0, &clEvent);
      clEvent.wait();
    } catch ( cl::Error & err ) {
      reInit = true;
      std::cerr << "OpenCL kernel execution error (";
      std::cerr << *configuration.print();
      std::cerr << "): ";
      std::cerr << isa::utils::toString(err.err()) << std::endl;
      delete kernel;
      if ( err.err() == -4 || err.err() == -61 ) {
        return -1;
      }
      break;
    }
    delete kernel;

    bool error = false;
    for ( unsigned int y = 0; y < matrixWidth; y++ ) {
      for ( unsigned int x = 0; x < matrixWidth; x++ ) {
        if ( !isa::utils::same(output[(y * isa::utils::pad(matrixWidth, padding)) + x], output_c[(y * isa::utils::pad(matrixWidth, padding)) + x]) ) {
          std::cerr << "Output error (" << *configuration.print() << ")." << std::endl;
          error = true;
          break;
        }
      }
      if ( error ) {
        break;
      }
    }
    if ( error ) {
      continue;
    }

    std::cout << matrixWidth << " ";
    std::cout << *configuration.print() << " ";
    std::cout << std::setprecision(3);
    std::cout << gflops / timer.getAverageTime() << " ";
    std::cout << std::setprecision(6);
    std::cout << timer.getAverageTime() << " " << timer.getStandardDeviation() << " " << timer.getCoefficientOfVariation() << std::endl;
  }
  std::cout << std::endl;

  return 0;
}

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< inputDataType > * input, cl::Buffer * input_d, cl::Buffer * output_d, const unsigned int outputSize) {
  try {
    *input_d = cl::Buffer(clContext, CL_MEM_READ_ONLY, input->size() * sizeof(inputDataType), 0, 0);
    *output_d = cl::Buffer(clContext, CL_MEM_WRITE_ONLY, outputSize * sizeof(inputDataType), 0, 0);
    clQueue->enqueueWriteBuffer(*input_d, CL_FALSE, 0, input->size() * sizeof(inputDataType), reinterpret_cast< void * >(input->data()));
    clQueue->finish();
  } catch ( cl::Error & err ) {
    std::cerr << "OpenCL error (memory initialization): " << isa::utils::toString(err.err()) << "." << std::endl;
    throw;
  }
}

<commit_msg>Typo.<commit_after>// Copyright 2016 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <vector>
#include <iostream>
#include <exception>
#include <iomanip>
#include <random>

#include <configuration.hpp>

#include <ArgumentList.hpp>
#include <InitializeOpenCL.hpp>
#include <Kernel.hpp>
#include <Stencil.hpp>
#include <utils.hpp>
#include <Timer.hpp>
#include <Stats.hpp>

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< inputDataType > * input, cl::Buffer * input_d, cl::Buffer * output_d, const unsigned int outputSize);

int main(int argc, char * argv[]) {
  bool reInit = true;
  unsigned int nrIterations = 0;
  unsigned int samplingFactor = 100;
  unsigned int clPlatformID = 0;
  unsigned int clDeviceID = 0;
  unsigned int vectorSize = 0;
  unsigned int maxThreads = 0;
  unsigned int maxItems = 0;
  unsigned int matrixWidth = 0;
  unsigned int padding = 0;
  // Random number generation
  std::random_device randomDevice;
  std::default_random_engine randomEngine(randomDevice());
  std::uniform_int_distribution<unsigned int> uniformDistribution(0, magicValue);

  try {
    isa::utils::ArgumentList args(argc, argv);

    clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
    clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
    if ( args.getSwitch("-sampling") ) {
      samplingFactor = args.getSwitchArgument< unsigned int >("-factor");
    }
    nrIterations = args.getSwitchArgument< unsigned int >("-iterations");
    vectorSize = args.getSwitchArgument< unsigned int >("-vector");
    padding = args.getSwitchArgument< unsigned int >("-padding");
    maxThreads = args.getSwitchArgument< unsigned int >("-max_threads");
    maxItems = args.getSwitchArgument< unsigned int >("-max_items");
    matrixWidth = args.getSwitchArgument< unsigned int >("-matrix_width");
    conf.setLocalMemory(args.getSwitch("-local"));
  } catch ( isa::utils::EmptyCommandLine & err ) {
    std::cerr << argv[0] << " -opencl_platform ... -opencl_device ... [-sampling -factor ...] -iterations ... -vector ... -padding ... -max_threads ... -max_items ... -matrix_width ... [-local]" << std::endl;
    return 1;
  } catch ( std::exception & err ) {
    std::cerr << err.what() << std::endl;
    return 1;
  }

  cl::Context clContext;
  std::vector< cl::Platform > * clPlatforms = new std::vector< cl::Platform >();
  std::vector< cl::Device > * clDevices = new std::vector< cl::Device >();
  std::vector< std::vector< cl::CommandQueue > > * clQueues = 0;

  // Allocate host memory
  std::vector< inputDataType > input((matrixWidth + 2) * isa::utils::pad(matrixWidth + 2, padding)), output(matrixWidth * isa::utils::pad(matrixWidth, padding)), output_c;
  cl::Buffer input_d, output_d;

  for ( unsigned int y = 0; y < matrixWidth + 2; y++ ) {
    for ( unsigned int x = 0; x < matrixWidth + 2; x++ ) {
      if ( y == 0 || y == (matrixWidth - 1) ) {
        input[(y * isa::utils::pad(matrixWidth + 2, padding)) + x] = 0;
      } else if ( x == 0 || x == (matrixWidth - 1) ) {
        input[(y * isa::utils::pad(matrixWidth + 2, padding)) + x] = 0;
      } else {
        input[(y * isa::utils::pad(matrixWidth + 2, padding)) + x] = uniformDistribution(randomEngine);
      }
    }
  }
  output_c.resize(output.size());

  // Run the control
  TuneBench::stencil2D(input, output_c, matrixWidth, padding);

  // Generate tuning configurations
  std::vector<TuneBench::Stencil2DConf> configurations;
  for ( unsigned int threadsD0 = vectorSize; threadsD0 <= maxThreads; threadsD0 += vectorSize) {
    for ( unsigned int threadsD1 = 1; threadsD0 * threadsD1 <= maxThreads; threadsD1++ ) {
      for ( unsigned int itemsD0 = 1; itemsD0 <= maxItems; itemsD0++ ) {
        if ( matrixWidth % (threadsD0 * itemsD0) != 0 ) {
          continue;
        }
        for ( unsigned int itemsD1 = 1; itemsD0 * itemsD1 <= maxItems; itemsD1++ ) {
          if ( matrixWidth % (threadsD1 * itemsD1) != 0 ) {
            continue;
          }
          TuneBench::StencilConf configuration;
          configuration.setNrThreadsD0(threadsD0);
          configuration.setNrThreadsD1(threadsD1);
          configuration.setNrItemsD0(itemsD0);
          configuration.setNrItemsD1(itemsD1);
          configurations.push_back(configuration);
        }
      }
    }
  }
  if ( samplingFactor < 100 ) {
    unsigned int newSize = static_cast<unsigned int>((configurations.size() * samplingFactor) / 100.0);
    std::shuffle(configurations.begin(), configurations.end(), randomEngine);
    configurations.resize(newSize);
  }

  std::cout << std::fixed << std::endl;
  std::cout << "# matrixWidth *configuration* GFLOP/s time stdDeviation COV" << std::endl << std::endl;

  for ( auto configuration = configurations.begin(); configuration != configurations.end(); ++configuration ) {
    // Generate kernel
    double gflops = isa::utils::giga(static_cast< uint64_t >(matrixWidth) * matrixWidth * 18.0);
    cl::Event clEvent;
    cl::Kernel * kernel;
    isa::utils::Timer timer;
    std::string * code = TuneBench::getStencil2DOpenCL(*configuration, inputDataName, matrixWidth, padding);

    if ( reInit ) {
      delete clQueues;
      clQueues = new std::vector< std::vector< cl::CommandQueue > >();
      isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, &clContext, clDevices, clQueues);
      try {
        initializeDeviceMemory(clContext, &(clQueues->at(clDeviceID)[0]), &input, &input_d, &output_d, output.size());
      } catch ( cl::Error & err ) {
        return -1;
      }
      reInit = false;
    }
    try {
      kernel = isa::OpenCL::compile("stencil2D", *code, "-cl-mad-enable -Werror", clContext, clDevices->at(clDeviceID));
    } catch ( isa::OpenCL::OpenCLError & err ) {
      std::cerr << err.what() << std::endl;
      delete code;
      break;
    }
    delete code;

    cl::NDRange global(matrixWidth / *configuration.getNrItemsD0(), matrixWidth / *configuration.getNrItemsD1());
    cl::NDRange local(*configuration.getNrThreadsD0(), *configuration.getNrThreadsD1());

    kernel->setArg(0, input_d);
    kernel->setArg(1, output_d);

    try {
      // Warm-up run
      clQueues->at(clDeviceID)[0].finish();
      clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &clEvent);
      clEvent.wait();
      // Tuning runs
      for ( unsigned int iteration = 0; iteration < nrIterations; iteration++ ) {
        timer.start();
        clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &clEvent);
        clEvent.wait();
        timer.stop();
      }
      clQueues->at(clDeviceID)[0].enqueueReadBuffer(output_d, CL_TRUE, 0, output.size() * sizeof(inputDataType), reinterpret_cast< void * >(output.data()), 0, &clEvent);
      clEvent.wait();
    } catch ( cl::Error & err ) {
      reInit = true;
      std::cerr << "OpenCL kernel execution error (";
      std::cerr << *configuration.print();
      std::cerr << "): ";
      std::cerr << isa::utils::toString(err.err()) << std::endl;
      delete kernel;
      if ( err.err() == -4 || err.err() == -61 ) {
        return -1;
      }
      break;
    }
    delete kernel;

    bool error = false;
    for ( unsigned int y = 0; y < matrixWidth; y++ ) {
      for ( unsigned int x = 0; x < matrixWidth; x++ ) {
        if ( !isa::utils::same(output[(y * isa::utils::pad(matrixWidth, padding)) + x], output_c[(y * isa::utils::pad(matrixWidth, padding)) + x]) ) {
          std::cerr << "Output error (" << *configuration.print() << ")." << std::endl;
          error = true;
          break;
        }
      }
      if ( error ) {
        break;
      }
    }
    if ( error ) {
      continue;
    }

    std::cout << matrixWidth << " ";
    std::cout << *configuration.print() << " ";
    std::cout << std::setprecision(3);
    std::cout << gflops / timer.getAverageTime() << " ";
    std::cout << std::setprecision(6);
    std::cout << timer.getAverageTime() << " " << timer.getStandardDeviation() << " " << timer.getCoefficientOfVariation() << std::endl;
  }
  std::cout << std::endl;

  return 0;
}

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< inputDataType > * input, cl::Buffer * input_d, cl::Buffer * output_d, const unsigned int outputSize) {
  try {
    *input_d = cl::Buffer(clContext, CL_MEM_READ_ONLY, input->size() * sizeof(inputDataType), 0, 0);
    *output_d = cl::Buffer(clContext, CL_MEM_WRITE_ONLY, outputSize * sizeof(inputDataType), 0, 0);
    clQueue->enqueueWriteBuffer(*input_d, CL_FALSE, 0, input->size() * sizeof(inputDataType), reinterpret_cast< void * >(input->data()));
    clQueue->finish();
  } catch ( cl::Error & err ) {
    std::cerr << "OpenCL error (memory initialization): " << isa::utils::toString(err.err()) << "." << std::endl;
    throw;
  }
}

<|endoftext|>