<commit_before>/******************************************************************************
 *  Copyright (c) 2008 - 2010 IBM Corporation and others.
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  which accompanies this distribution, and is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 *
 *  Contributors:
 *    David Ungar, IBM Research - Initial Implementation
 *    Sam Adams, IBM Research - Initial Implementation
 *    Stefan Marr, Vrije Universiteit Brussel - Port to x86 Multi-Core Systems
 ******************************************************************************/

# include <headers.h>
# include <limits.h>
# include <math.h>

FILE* BytecodeTraceFile;
extern char* displayName;

static void consume_argument(int& argc, char**& argv, int n) {
  argv[n] = argv[0];
  argv += n;
  argc -= n;
}

static bool have_set_core_count = false;

static void set_geom(char* sizes) {
#if On_Tilera
  int w, h;
  if (isdigit(w = sizes[0])  &&  sizes[1] ==','  &&  isdigit(h = sizes[2])  &&  sizes[3] == '\0' ) {
    // convert from ascii
    w = w - '0';
    h = h - '0';

    CPU_Coordinate::set_width_height(w,  h);
    Logical_Core::num_cores = w * h;
    have_set_core_count = true;
  }
  else
    OS_Interface::die("bad argument syntax: needs to be `-geom <digit>,<digit>'\n");
#endif
}

static void set_num_cores(char* num_cores_str) {
  /* parses strings with 1 or 2 digits <digit{1,2}> */
  int num_cores;
  if (isdigit(num_cores = num_cores_str[0])  &&  num_cores_str[1] == '\0' ) {
    num_cores = num_cores - '0';
    Logical_Core::num_cores = num_cores;
    have_set_core_count = true;

  }
  else if (isdigit(num_cores_str[0])  &&  isdigit(num_cores_str[1])  &&  num_cores_str[2] == '\0' ) {
	  num_cores = (num_cores_str[0] - '0') * 10 + (num_cores_str[1] - '0');
	  Logical_Core::num_cores = num_cores;
    have_set_core_count = true;
  }
  else
    OS_Interface::die("bad argument syntax: needs to be `-num_cores <digit>'\n");

# if On_Tilera
  // TODO: put this into its own routine, and avoid the #if

  // Calculate the dimensions of the rectangle fitting all cores
  int w, h;
  h = sqrt(num_cores);
  w = num_cores / h;
  if (w * h < num_cores) {
    if   (w == h)  w += 1;
    else           h += 1;

    assert(w * h >= num_cores);
  }

  CPU_Coordinate::set_width_height(w,  h);
# endif
}

static void set_trace_file(char* f) {
  BytecodeTraceFile = fopen(f, "r");
  if (BytecodeTraceFile == NULL) {
    perror("bytecode trace file:");
    exit(1);
  }
}

extern int headless;

# define FOR_ALL_ARGS_WITH_PARAMS_DO(template) \
template("-display",            displayName=STRING,                               "<display>") \
template("-geom",               set_geom(STRING),                                 "<digit,digit>") \
template("-num_cores",          set_num_cores(STRING),                            "<digit{1,2}>") \
template("-min_heap_MB",        Memory_System::min_heap_MB = NUMBER,              "N") \
template("-profile_after",      The_Squeak_Interpreter()->set_profile_after(NUMBER), "N") \
template("-quit_after",         The_Squeak_Interpreter()->set_quit_after(NUMBER),    "N") \
template("-round_robin_period", Memory_System::set_round_robin_period(NUMBER),    "N") \
template("-run_mask",           The_Squeak_Interpreter()->set_run_mask(NUMBER64),    "N") \
template("-trace",              set_trace_file(STRING),                           "file-name") \
template("-num_chips",          The_Squeak_Interpreter()->set_num_chips(NUMBER),    "N")

# define FOR_ALL_BOOLEAN_ARGS_DO(template) \
template("-dont_replicate_all",    Memory_System::replicate_all = false, "not replicating everything") \
template("-eschew_huge_pages",  Memory_System::use_huge_pages = false, "not using huge pages") \
template("-headless",           headless = 1, "headless") \
template("-make_checkpoint",    The_Squeak_Interpreter()->set_make_checkpoint(true), "making checkpoint") \
template("-no_fence",           The_Squeak_Interpreter()->set_fence(false), "not fencing memory on control transfers") \
template("-print_moves_to_read_write",  The_Squeak_Interpreter()->set_print_moves_to_read_write(true), "printing moves to read_write heaps") \
template("-replicate_methods",  Memory_System::replicate_methods = true, "replicating methods") \
template("-use_checkpoint",     The_Squeak_Interpreter()->set_use_checkpoint(true), "using checkpoint") \
template("-replicate_OT",       Multicore_Object_Table::replicate = true, "let hardware replicate the object table") \
template("-print_gc",           Abstract_Mark_Sweep_Collector::print_gc = true, "Print GC") \
template("-version",            print_version_info(), "Print full version information")

static void print_version_info() {
  // compiling machine
#define stringify(s) expstr(s)
#define expstr(s) #s

  printf("Compiled code:\t\t%s\n", __FILE__);
#if defined(GIT_REVISION_ID)
  printf("Git Revision Id:\t%s\n", stringify(GIT_REVISION_ID));
#endif
  printf("Compilation date:\t%s %s\n", __DATE__, __TIME__);

#if defined(COMPILATION_HOSTNAME)
  printf("Compiled on:\t\t%s\n", stringify(COMPILATION_HOSTNAME));
#endif

  printf("Used compiler:\t\t");
#if defined(__tile__)
  printf("tile-cc version %d.%d.%d\n", __TILECC__, __TILECC_MINOR__, __TILECC_PATCHLEVEL__);
#else
  printf("%s\n", __VERSION__);
#endif

#if defined(__OPTIMIZE__)
  printf("Optimization on\n");
#endif

  printf("\n\n");
  print_config();
  exit(0);
}

static void usage(char** argv) {
  fprintf(stderr, "Usage: %s", argv[0]);

# define print_arg_with_param(argName,setExpr,symbolicVal) fprintf(stderr, " [%s %s]", argName, symbolicVal);
# define print_boolean_arg(argName,setExpr,explanation) fprintf(stderr, " [%s]", argName);

  FOR_ALL_ARGS_WITH_PARAMS_DO(print_arg_with_param)
  FOR_ALL_BOOLEAN_ARGS_DO(print_boolean_arg)
# undef print_arg_with_param
# undef print_boolean_arg

    fprintf(stderr, " <snapshot-file-name.image>\n");
    exit(1);
}

static void process_arguments(int& argc, char**& argv) {
   if (argc < 2) {
    usage(argv);
  }

  bool do_print = 0 == Memory_Semantics::get_group_rank(); // it is not safe to use Logical_Core:my_rank() here, since it is not initialized yet

  for (int old_argc = -1;  old_argc != argc;  ) {
    old_argc = argc;

    # define parse_arg_with_param(argName,setExpr,symbolicVal) \
      if (strcmp(argv[1], argName) == 0) { \
        __attribute__((unused)) char* STRING = argv[2]; \
        __attribute__((unused)) int NUMBER = atoi(argv[2]); \
        __attribute__((unused)) int64 NUMBER64 = atoll(argv[2]); \
        setExpr; \
        if (do_print)  fprintf(stdout, "%s = %s\n", argName, argv[2]); \
        consume_argument(argc, argv, 2); \
       }

    # define parse_boolean_arg(argName,setExpr,explanation) \
      if (strcmp(argv[1], argName) == 0) { \
        setExpr; \
        if (do_print)  fprintf(stdout, "%s\n", explanation); \
        consume_argument(argc, argv, 1); \
      }
      FOR_ALL_ARGS_WITH_PARAMS_DO(parse_arg_with_param);
      FOR_ALL_BOOLEAN_ARGS_DO(parse_boolean_arg);

    # undef parse_arg_with_param
    # undef parse_boolean_arg
  }

  if (!have_set_core_count)
    Logical_Core::num_cores = 1;

  if (argv[1][0] == '-') {
    fprintf(stderr, "bad argument: %s\n", argv[1]);
    usage(argv);
  }
}

void helper_core_main() {
  if ( !On_Tilera )
    Memory_Semantics::initialize_local_logical_core();

  The_Memory_System()->initialize_helper();
  The_Squeak_Interpreter()->receive_initial_interpreter();
  {
    Safepoint_Ability sa(true);
    WAIT_FOR_MESSAGE(startInterpretingMessage, Logical_Core::main_rank);
  }
  extern void initip();
  initip();
  // Because BitBltPlugin only gets initialized when the literal in the ST method
  //  gets set for that prim, bit blt locally prims don't init it on all cores.
  //  Do it by brute force here. HACK -- dmu 4/09
  rvm_callInitializersInAllModules();
  Message_Statics::run_timer = true;
  The_Squeak_Interpreter()->interpret();

  char buf[BUFSIZ];
  Logical_Core::my_print_string(buf, sizeof(buf));
  lprintf( "helper finsihed: %s\n", buf);
  if ( On_Tilera ) {
    rvm_exit();
  }
}

int main (int argc, char *argv[]) {
  struct rlimit rl = {100000000, 100000000}; //{ RLIM_INFINITY, RLIM_INFINITY };
  // The rlimit was an attempt to get core dumps for a MDE version that broke them.
  // It didn't work, but we might need it someday. -- dmu 4/09
  if (false && setrlimit( RLIMIT_CORE, &rl)) {
    perror("setrlimit");
    fatal("rlimit");
  }
  // set_sim_tracing(SIM_TRACE_NONE);
  OS_Interface::profiler_disable();
  OS_Interface::profiler_clear();

  OS_Interface::initialize();

  Timeout_Timer::initialize();
  Memory_Semantics::initialize_memory_system();

  Printer::init_globals();

  char** orig_argv = new char*[argc + 1];
  for (int i = 0;  i <= argc;  ++i)  orig_argv[i] = argv[i];
  process_arguments(argc, argv);

  if (MakeByteCodeTrace) {
    BytecodeTraceFile = fopen("bytecode_trace", "w");
    if (BytecodeTraceFile == NULL) {
      perror("bytecode trace file");
      exit(1);
    }
  }

  OS_Interface::ensure_Time_Machine_backs_up_run_directory();

  Memory_Semantics::go_parallel(helper_core_main, orig_argv);

  char buf[BUFSIZ];
  Logical_Core::my_print_string(buf, sizeof(buf));
  fprintf(stdout, "main running: %s\n", buf);
  print_time(); fprintf(stderr, "\n");

  print_config();

  Runtime_Tester::test();

  extern void initip();
  initip();

  char image_path[PATH_MAX];
  realpath(argv[1], image_path);

  if (The_Squeak_Interpreter()->use_checkpoint())
    Squeak_Image_Reader::fake_read(image_path, The_Memory_System(), The_Squeak_Interpreter());
  else
    Squeak_Image_Reader::read(image_path, The_Memory_System(), The_Squeak_Interpreter());

  extern char** environ;
  sqr_main(argc, argv, environ);

  if (The_Squeak_Interpreter()->make_checkpoint())
    The_Squeak_Interpreter()->save_all_to_checkpoint();

  assert_always(The_Squeak_Interpreter()->safepoint_ability == NULL);
  The_Squeak_Interpreter()->distribute_initial_interpreter();
  Message_Statics::run_timer = true;
  {
    Safepoint_Ability sa(true);
    The_Memory_System()->verify_if(check_assertions);
    if (check_assertions)
      The_Squeak_Interpreter()->verify_all_processes_in_scheduler();
    if (Trace_Execution) The_Squeak_Interpreter()->trace_execution();
    if (Trace_For_Debugging) The_Squeak_Interpreter()->trace_for_debugging();
    startInterpretingMessage_class().send_to_other_cores();
  }

  if (OS_Interface::get_power_source() == OS_Interface::battery) {
    fprintf(stdout, "running on battery power: saving cycles but idle cores will slow things down\n", buf);
    The_Squeak_Interpreter()->set_idle_cores_relinquish_cpus(true);
  }
  // Doesn't work yet:  The_Memory_System()->moveAllToRead_MostlyHeaps();
  The_Squeak_Interpreter()->interpret();
  ioExit();
  return 0;
}

<commit_msg>Added warning when -geom is used on x86 systems<commit_after>/******************************************************************************
 *  Copyright (c) 2008 - 2010 IBM Corporation and others.
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  which accompanies this distribution, and is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 *
 *  Contributors:
 *    David Ungar, IBM Research - Initial Implementation
 *    Sam Adams, IBM Research - Initial Implementation
 *    Stefan Marr, Vrije Universiteit Brussel - Port to x86 Multi-Core Systems
 ******************************************************************************/

# include <headers.h>
# include <limits.h>
# include <math.h>

FILE* BytecodeTraceFile;
extern char* displayName;

static void consume_argument(int& argc, char**& argv, int n) {
  argv[n] = argv[0];
  argv += n;
  argc -= n;
}

static bool have_set_core_count = false;

static void set_geom(char* sizes) {
#if On_Tilera
  int w, h;
  if (isdigit(w = sizes[0])  &&  sizes[1] ==','  &&  isdigit(h = sizes[2])  &&  sizes[3] == '\0' ) {
    // convert from ascii
    w = w - '0';
    h = h - '0';

    CPU_Coordinate::set_width_height(w,  h);
    Logical_Core::num_cores = w * h;
    have_set_core_count = true;
  }
  else
    OS_Interface::die("bad argument syntax: needs to be `-geom <digit>,<digit>'\n");
#else
  OS_Interface::die("bad argument: -geom only supported on Tilera, use -num_cores instead.'\n");
#endif
}

static void set_num_cores(char* num_cores_str) {
  /* parses strings with 1 or 2 digits <digit{1,2}> */
  int num_cores;
  if (isdigit(num_cores = num_cores_str[0])  &&  num_cores_str[1] == '\0' ) {
    num_cores = num_cores - '0';
    Logical_Core::num_cores = num_cores;
    have_set_core_count = true;

  }
  else if (isdigit(num_cores_str[0])  &&  isdigit(num_cores_str[1])  &&  num_cores_str[2] == '\0' ) {
	  num_cores = (num_cores_str[0] - '0') * 10 + (num_cores_str[1] - '0');
	  Logical_Core::num_cores = num_cores;
    have_set_core_count = true;
  }
  else
    OS_Interface::die("bad argument syntax: needs to be `-num_cores <digit>'\n");

# if On_Tilera
  // TODO: put this into its own routine, and avoid the #if

  // Calculate the dimensions of the rectangle fitting all cores
  int w, h;
  h = sqrt(num_cores);
  w = num_cores / h;
  if (w * h < num_cores) {
    if   (w == h)  w += 1;
    else           h += 1;

    assert(w * h >= num_cores);
  }

  CPU_Coordinate::set_width_height(w,  h);
# endif
}

static void set_trace_file(char* f) {
  BytecodeTraceFile = fopen(f, "r");
  if (BytecodeTraceFile == NULL) {
    perror("bytecode trace file:");
    exit(1);
  }
}

extern int headless;

# define FOR_ALL_ARGS_WITH_PARAMS_DO(template) \
template("-display",            displayName=STRING,                               "<display>") \
template("-geom",               set_geom(STRING),                                 "<digit,digit>") \
template("-num_cores",          set_num_cores(STRING),                            "<digit{1,2}>") \
template("-min_heap_MB",        Memory_System::min_heap_MB = NUMBER,              "N") \
template("-profile_after",      The_Squeak_Interpreter()->set_profile_after(NUMBER), "N") \
template("-quit_after",         The_Squeak_Interpreter()->set_quit_after(NUMBER),    "N") \
template("-round_robin_period", Memory_System::set_round_robin_period(NUMBER),    "N") \
template("-run_mask",           The_Squeak_Interpreter()->set_run_mask(NUMBER64),    "N") \
template("-trace",              set_trace_file(STRING),                           "file-name") \
template("-num_chips",          The_Squeak_Interpreter()->set_num_chips(NUMBER),    "N")

# define FOR_ALL_BOOLEAN_ARGS_DO(template) \
template("-dont_replicate_all",    Memory_System::replicate_all = false, "not replicating everything") \
template("-eschew_huge_pages",  Memory_System::use_huge_pages = false, "not using huge pages") \
template("-headless",           headless = 1, "headless") \
template("-make_checkpoint",    The_Squeak_Interpreter()->set_make_checkpoint(true), "making checkpoint") \
template("-no_fence",           The_Squeak_Interpreter()->set_fence(false), "not fencing memory on control transfers") \
template("-print_moves_to_read_write",  The_Squeak_Interpreter()->set_print_moves_to_read_write(true), "printing moves to read_write heaps") \
template("-replicate_methods",  Memory_System::replicate_methods = true, "replicating methods") \
template("-use_checkpoint",     The_Squeak_Interpreter()->set_use_checkpoint(true), "using checkpoint") \
template("-replicate_OT",       Multicore_Object_Table::replicate = true, "let hardware replicate the object table") \
template("-print_gc",           Abstract_Mark_Sweep_Collector::print_gc = true, "Print GC") \
template("-version",            print_version_info(), "Print full version information")

static void print_version_info() {
  // compiling machine
#define stringify(s) expstr(s)
#define expstr(s) #s

  printf("Compiled code:\t\t%s\n", __FILE__);
#if defined(GIT_REVISION_ID)
  printf("Git Revision Id:\t%s\n", stringify(GIT_REVISION_ID));
#endif
  printf("Compilation date:\t%s %s\n", __DATE__, __TIME__);

#if defined(COMPILATION_HOSTNAME)
  printf("Compiled on:\t\t%s\n", stringify(COMPILATION_HOSTNAME));
#endif

  printf("Used compiler:\t\t");
#if defined(__tile__)
  printf("tile-cc version %d.%d.%d\n", __TILECC__, __TILECC_MINOR__, __TILECC_PATCHLEVEL__);
#else
  printf("%s\n", __VERSION__);
#endif

#if defined(__OPTIMIZE__)
  printf("Optimization on\n");
#endif

  printf("\n\n");
  print_config();
  exit(0);
}

static void usage(char** argv) {
  fprintf(stderr, "Usage: %s", argv[0]);

# define print_arg_with_param(argName,setExpr,symbolicVal) fprintf(stderr, " [%s %s]", argName, symbolicVal);
# define print_boolean_arg(argName,setExpr,explanation) fprintf(stderr, " [%s]", argName);

  FOR_ALL_ARGS_WITH_PARAMS_DO(print_arg_with_param)
  FOR_ALL_BOOLEAN_ARGS_DO(print_boolean_arg)
# undef print_arg_with_param
# undef print_boolean_arg

    fprintf(stderr, " <snapshot-file-name.image>\n");
    exit(1);
}

static void process_arguments(int& argc, char**& argv) {
   if (argc < 2) {
    usage(argv);
  }

  bool do_print = 0 == Memory_Semantics::get_group_rank(); // it is not safe to use Logical_Core:my_rank() here, since it is not initialized yet

  for (int old_argc = -1;  old_argc != argc;  ) {
    old_argc = argc;

    # define parse_arg_with_param(argName,setExpr,symbolicVal) \
      if (strcmp(argv[1], argName) == 0) { \
        __attribute__((unused)) char* STRING = argv[2]; \
        __attribute__((unused)) int NUMBER = atoi(argv[2]); \
        __attribute__((unused)) int64 NUMBER64 = atoll(argv[2]); \
        setExpr; \
        if (do_print)  fprintf(stdout, "%s = %s\n", argName, argv[2]); \
        consume_argument(argc, argv, 2); \
       }

    # define parse_boolean_arg(argName,setExpr,explanation) \
      if (strcmp(argv[1], argName) == 0) { \
        setExpr; \
        if (do_print)  fprintf(stdout, "%s\n", explanation); \
        consume_argument(argc, argv, 1); \
      }
      FOR_ALL_ARGS_WITH_PARAMS_DO(parse_arg_with_param);
      FOR_ALL_BOOLEAN_ARGS_DO(parse_boolean_arg);

    # undef parse_arg_with_param
    # undef parse_boolean_arg
  }

  if (!have_set_core_count)
    Logical_Core::num_cores = 1;

  if (argv[1][0] == '-') {
    fprintf(stderr, "bad argument: %s\n", argv[1]);
    usage(argv);
  }
}

void helper_core_main() {
  if ( !On_Tilera )
    Memory_Semantics::initialize_local_logical_core();

  The_Memory_System()->initialize_helper();
  The_Squeak_Interpreter()->receive_initial_interpreter();
  {
    Safepoint_Ability sa(true);
    WAIT_FOR_MESSAGE(startInterpretingMessage, Logical_Core::main_rank);
  }
  extern void initip();
  initip();
  // Because BitBltPlugin only gets initialized when the literal in the ST method
  //  gets set for that prim, bit blt locally prims don't init it on all cores.
  //  Do it by brute force here. HACK -- dmu 4/09
  rvm_callInitializersInAllModules();
  Message_Statics::run_timer = true;
  The_Squeak_Interpreter()->interpret();

  char buf[BUFSIZ];
  Logical_Core::my_print_string(buf, sizeof(buf));
  lprintf( "helper finsihed: %s\n", buf);
  if ( On_Tilera ) {
    rvm_exit();
  }
}

int main (int argc, char *argv[]) {
  struct rlimit rl = {100000000, 100000000}; //{ RLIM_INFINITY, RLIM_INFINITY };
  // The rlimit was an attempt to get core dumps for a MDE version that broke them.
  // It didn't work, but we might need it someday. -- dmu 4/09
  if (false && setrlimit( RLIMIT_CORE, &rl)) {
    perror("setrlimit");
    fatal("rlimit");
  }
  // set_sim_tracing(SIM_TRACE_NONE);
  OS_Interface::profiler_disable();
  OS_Interface::profiler_clear();

  OS_Interface::initialize();

  Timeout_Timer::initialize();
  Memory_Semantics::initialize_memory_system();

  Printer::init_globals();

  char** orig_argv = new char*[argc + 1];
  for (int i = 0;  i <= argc;  ++i)  orig_argv[i] = argv[i];
  process_arguments(argc, argv);

  if (MakeByteCodeTrace) {
    BytecodeTraceFile = fopen("bytecode_trace", "w");
    if (BytecodeTraceFile == NULL) {
      perror("bytecode trace file");
      exit(1);
    }
  }

  OS_Interface::ensure_Time_Machine_backs_up_run_directory();

  Memory_Semantics::go_parallel(helper_core_main, orig_argv);

  char buf[BUFSIZ];
  Logical_Core::my_print_string(buf, sizeof(buf));
  fprintf(stdout, "main running: %s\n", buf);
  print_time(); fprintf(stderr, "\n");

  print_config();

  Runtime_Tester::test();

  extern void initip();
  initip();

  char image_path[PATH_MAX];
  realpath(argv[1], image_path);

  if (The_Squeak_Interpreter()->use_checkpoint())
    Squeak_Image_Reader::fake_read(image_path, The_Memory_System(), The_Squeak_Interpreter());
  else
    Squeak_Image_Reader::read(image_path, The_Memory_System(), The_Squeak_Interpreter());

  extern char** environ;
  sqr_main(argc, argv, environ);

  if (The_Squeak_Interpreter()->make_checkpoint())
    The_Squeak_Interpreter()->save_all_to_checkpoint();

  assert_always(The_Squeak_Interpreter()->safepoint_ability == NULL);
  The_Squeak_Interpreter()->distribute_initial_interpreter();
  Message_Statics::run_timer = true;
  {
    Safepoint_Ability sa(true);
    The_Memory_System()->verify_if(check_assertions);
    if (check_assertions)
      The_Squeak_Interpreter()->verify_all_processes_in_scheduler();
    if (Trace_Execution) The_Squeak_Interpreter()->trace_execution();
    if (Trace_For_Debugging) The_Squeak_Interpreter()->trace_for_debugging();
    startInterpretingMessage_class().send_to_other_cores();
  }

  if (OS_Interface::get_power_source() == OS_Interface::battery) {
    fprintf(stdout, "running on battery power: saving cycles but idle cores will slow things down\n", buf);
    The_Squeak_Interpreter()->set_idle_cores_relinquish_cpus(true);
  }
  // Doesn't work yet:  The_Memory_System()->moveAllToRead_MostlyHeaps();
  The_Squeak_Interpreter()->interpret();
  ioExit();
  return 0;
}

<|endoftext|>


<commit_before><commit_msg>core/gl: Fixing bug when creating texture from resource<commit_after><|endoftext|>


<commit_before><commit_msg>[cpp]Bind supporting structs<commit_after><|endoftext|>


<commit_before><commit_msg>Finished support for ISSN mapping.<commit_after><|endoftext|>


<commit_before>// Ylikuutio - A 3D game and simulation engine.
//
// Copyright (C) 2015-2022 Antti Nuortimo.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

#include "biont.hpp"
#include "mesh_module.hpp"
#include "shader.hpp"
#include "holobiont.hpp"
#include "symbiosis.hpp"
#include "symbiont_species.hpp"
#include "biont_struct.hpp"
#include "code/ylikuutio/hierarchy/hierarchy_templates.hpp"
#include "code/ylikuutio/opengl/opengl.hpp"
#include "code/ylikuutio/opengl/ylikuutio_glew.hpp" // GLfloat, GLuint etc.

// Include GLM
#ifndef __GLM_GLM_HPP_INCLUDED
#define __GLM_GLM_HPP_INCLUDED
#include <glm/glm.hpp> // glm
#endif

#ifndef __GLM_GTC_MATRIX_TRANSFORM_HPP_INCLUDED
#define __GLM_GTC_MATRIX_TRANSFORM_HPP_INCLUDED
#include <glm/gtc/matrix_transform.hpp>
#endif

#ifndef __GLM_GTC_QUATERNION_HPP_INCLUDED
#define __GLM_GTC_QUATERNION_HPP_INCLUDED
#include <glm/gtc/quaternion.hpp> // glm::quat
#endif

// Include standard headers
#include <cstddef>  // std::size_t
#include <ios>      // std::defaultfloat, std::dec, std::fixed, std::hex, std::ios
#include <iostream> // std::cout, std::cin, std::cerr
#include <stdint.h> // uint32_t etc.
#include <string>   // std::string

namespace yli::ontology
{
    class Entity;
    class Universe;
    class Scene;

    Biont::~Biont()
    {
        // destructor.
        //
        // Requirements:
        // `this->symbiont_species` must not be `nullptr`.

        std::cout << "Biont with childID " << std::dec << this->childID << " will be destroyed.\n";
    }

    yli::ontology::Entity* Biont::get_parent() const
    {
        return this->child_of_holobiont.get_parent();
    }

    void Biont::render()
    {
        // Render this `Biont`.
        //
        // Requirements:
        // `this->holobiont_parent` must not be `nullptr`.
        // `this->holobiont_parent->get_parent()` must not be `nullptr`.

        const yli::ontology::Holobiont* const holobiont = static_cast<yli::ontology::Holobiont*>(this->get_parent());

        if (holobiont == nullptr)
        {
            std::cerr << "ERROR: `Biont::render`: `holobiont` is `nullptr`!\n";
            return;
        }

        const yli::ontology::Symbiosis* const symbiosis = static_cast<yli::ontology::Symbiosis*>(holobiont->get_parent());

        if (symbiosis == nullptr)
        {
            std::cerr << "ERROR: `Biont::render`: `symbiosis` is `nullptr`!\n";
            return;
        }

        if (this->should_render)
        {
            this->render_this_biont(symbiosis->get_shader());
        }
    }

    void Biont::render_this_biont(const yli::ontology::Shader* const shader)
    {
        // Requirements:
        // `this->universe` must not be `nullptr`.
        // `shader` must not be `nullptr`.
        // `this->holobiont_parent` must not be `nullptr`.
        // `this->symbiont_species` must not be `nullptr`.

        yli::ontology::Universe& universe = this->universe;

        if (shader == nullptr)
        {
            std::cerr << "ERROR: `Biont::render_this_biont`: `shader` is `nullptr`!\n";
            return;
        }

        const yli::ontology::Holobiont* const holobiont = static_cast<yli::ontology::Holobiont*>(this->get_parent());

        if (holobiont == nullptr)
        {
            std::cerr << "ERROR: `Biont::render_this_biont`: `holobiont` is `nullptr`!\n";
            return;
        }

        yli::ontology::Symbiosis* const symbiosis = static_cast<yli::ontology::Symbiosis*>(holobiont->get_parent());

        if (symbiosis == nullptr)
        {
            std::cerr << "ERROR: `Biont::render_this_biont`: `symbiosis` is `nullptr`!\n";
            return;
        }

        const yli::ontology::SymbiontSpecies* const symbiont_species = static_cast<yli::ontology::SymbiontSpecies*>(this->apprentice_of_symbiont_species.get_master());

        if (symbiont_species == nullptr)
        {
            std::cerr << "ERROR: `Biont::render_this_biont`: `symbiont_species` is `nullptr`!\n";
            return;
        }

        this->model_matrix = glm::mat4(1.0f);

        const std::string model_file_format = symbiosis->get_model_file_format();

        if (this->initial_rotate_vectors.size() == this->initial_rotate_angles.size())
        {
            for (std::size_t i = 0; i < this->initial_rotate_vectors.size() && i < this->initial_rotate_angles.size(); i++)
            {
                this->model_matrix = glm::rotate(this->model_matrix, this->initial_rotate_angles[i], this->initial_rotate_vectors[i]);
            }
        }

        this->model_matrix = glm::scale(this->model_matrix, this->original_scale_vector);
        glm::vec3 euler_angles { holobiont->roll, holobiont->yaw, holobiont->pitch };
        glm::quat my_quaternion = glm::quat(euler_angles);
        glm::mat4 rotation_matrix = glm::mat4_cast(my_quaternion);
        this->model_matrix = rotation_matrix * this->model_matrix;
        this->model_matrix[3][0] = holobiont->cartesian_coordinates.x;
        this->model_matrix[3][1] = holobiont->cartesian_coordinates.y;
        this->model_matrix[3][2] = holobiont->cartesian_coordinates.z;

        this->mvp_matrix = universe.get_projection_matrix() * universe.get_view_matrix() * this->model_matrix;

        // Bind our texture in Texture Unit 0.
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, symbiosis->get_texture(this->biontID));
        // Set our "texture_sampler" sampler to user Texture Unit 0.
        yli::opengl::uniform_1i(symbiosis->get_openGL_textureID(this->biontID), 0);

        // '`Material`' part ends here.

        // '`Species`' part begins here.

        // Compute the MVP matrix from keyboard and mouse input.
        const glm::vec3& light_position = symbiosis->get_light_position(this->biontID);
        glUniform3f(
                symbiosis->get_light_id(this->biontID),
                light_position.x,
                light_position.y,
                light_position.z);

        const yli::ontology::MeshModule& mesh = symbiont_species->mesh;

        // 1st attribute buffer : vertices.
        yli::opengl::enable_vertex_attrib_array(mesh.get_vertex_position_modelspace_id());

        // 2nd attribute buffer : UVs.
        yli::opengl::enable_vertex_attrib_array(mesh.get_vertex_uv_id());

        // 3rd attribute buffer : normals.
        yli::opengl::enable_vertex_attrib_array(mesh.get_vertex_normal_modelspace_id());

        // '`Species`' part ends here.

        // Send our transformation to the currently bound shader,
        // in the "MVP" uniform.
        glUniformMatrix4fv(shader->get_matrix_id(), 1, GL_FALSE, &this->mvp_matrix[0][0]);
        glUniformMatrix4fv(shader->get_model_matrix_id(), 1, GL_FALSE, &this->model_matrix[0][0]);

        GLuint vao                             = mesh.get_vao();
        GLuint vertexbuffer                    = mesh.get_vertexbuffer();
        uint32_t vertex_position_modelspace_id = mesh.get_vertex_position_modelspace_id();
        GLuint uvbuffer                        = mesh.get_uvbuffer();
        uint32_t vertex_uv_id                  = mesh.get_vertex_uv_id();
        GLuint normalbuffer                    = mesh.get_normalbuffer();
        uint32_t vertex_normal_modelspace_id   = mesh.get_vertex_normal_modelspace_id();
        GLuint elementbuffer                   = mesh.get_elementbuffer();
        uint32_t indices_size                  = mesh.get_indices_size();

        glBindVertexArray(vao);

        // 1st attribute buffer : vertices.
        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
        glVertexAttribPointer(
                vertex_position_modelspace_id, // The attribute we want to configure
                3,                            // size
                GL_FLOAT,                     // type
                GL_FALSE,                     // normalized?
                0,                            // stride
                (void*) 0                     // array buffer offset
                );
        yli::opengl::enable_vertex_attrib_array(vertex_position_modelspace_id);

        // 2nd attribute buffer : UVs.
        glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
        glVertexAttribPointer(
                vertex_uv_id,                   // The attribute we want to configure
                2,                            // size : U+V => 2
                GL_FLOAT,                     // type
                GL_FALSE,                     // normalized?
                0,                            // stride
                (void*) 0                     // array buffer offset
                );
        yli::opengl::enable_vertex_attrib_array(vertex_uv_id);

        // 3rd attribute buffer : normals.
        glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
        glVertexAttribPointer(
                vertex_normal_modelspace_id,   // The attribute we want to configure
                3,                            // size
                GL_FLOAT,                     // type
                GL_FALSE,                     // normalized?
                0,                            // stride
                (void*) 0                     // array buffer offset
                );
        yli::opengl::enable_vertex_attrib_array(vertex_normal_modelspace_id);

        // Index buffer.
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);

        // Draw the triangles!
        glDrawElements(
                GL_TRIANGLES,                 // mode
                indices_size,                 // count
                GL_UNSIGNED_INT,              // type
                (void*) 0                     // element array buffer offset
                );

        yli::opengl::disable_vertex_attrib_array(mesh.get_vertex_position_modelspace_id());
        yli::opengl::disable_vertex_attrib_array(mesh.get_vertex_uv_id());
        yli::opengl::disable_vertex_attrib_array(mesh.get_vertex_normal_modelspace_id());
        yli::opengl::disable_vertex_attrib_array(vertex_position_modelspace_id);
        yli::opengl::disable_vertex_attrib_array(vertex_uv_id);
        yli::opengl::disable_vertex_attrib_array(vertex_normal_modelspace_id);
    }

    yli::ontology::Scene* Biont::get_scene() const
    {
        yli::ontology::Entity* const parent = this->get_parent();

        if (parent != nullptr)
        {
            return parent->get_scene();
        }

        return nullptr;
    }

    std::size_t Biont::get_number_of_children() const
    {
        return 0; // `Biont` has no children.
    }

    std::size_t Biont::get_number_of_descendants() const
    {
        return 0; // `Biont` has no children.
    }
}
<commit_msg>Add a comment.<commit_after>// Ylikuutio - A 3D game and simulation engine.
//
// Copyright (C) 2015-2022 Antti Nuortimo.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

#include "biont.hpp"
#include "mesh_module.hpp"
#include "shader.hpp"
#include "holobiont.hpp"
#include "symbiosis.hpp"
#include "symbiont_species.hpp"
#include "biont_struct.hpp"
#include "code/ylikuutio/hierarchy/hierarchy_templates.hpp"
#include "code/ylikuutio/opengl/opengl.hpp"
#include "code/ylikuutio/opengl/ylikuutio_glew.hpp" // GLfloat, GLuint etc.

// Include GLM
#ifndef __GLM_GLM_HPP_INCLUDED
#define __GLM_GLM_HPP_INCLUDED
#include <glm/glm.hpp> // glm
#endif

#ifndef __GLM_GTC_MATRIX_TRANSFORM_HPP_INCLUDED
#define __GLM_GTC_MATRIX_TRANSFORM_HPP_INCLUDED
#include <glm/gtc/matrix_transform.hpp>
#endif

#ifndef __GLM_GTC_QUATERNION_HPP_INCLUDED
#define __GLM_GTC_QUATERNION_HPP_INCLUDED
#include <glm/gtc/quaternion.hpp> // glm::quat
#endif

// Include standard headers
#include <cstddef>  // std::size_t
#include <ios>      // std::defaultfloat, std::dec, std::fixed, std::hex, std::ios
#include <iostream> // std::cout, std::cin, std::cerr
#include <stdint.h> // uint32_t etc.
#include <string>   // std::string

namespace yli::ontology
{
    class Entity;
    class Universe;
    class Scene;

    Biont::~Biont()
    {
        // destructor.
        //
        // Requirements:
        // `this->symbiont_species` must not be `nullptr`.

        std::cout << "Biont with childID " << std::dec << this->childID << " will be destroyed.\n";
    }

    yli::ontology::Entity* Biont::get_parent() const
    {
        return this->child_of_holobiont.get_parent();
    }

    void Biont::render()
    {
        // Render this `Biont`.
        //
        // Requirements:
        // `this->holobiont_parent` must not be `nullptr`.
        // `this->holobiont_parent->get_parent()` must not be `nullptr`.

        const yli::ontology::Holobiont* const holobiont = static_cast<yli::ontology::Holobiont*>(this->get_parent());

        if (holobiont == nullptr)
        {
            std::cerr << "ERROR: `Biont::render`: `holobiont` is `nullptr`!\n";
            return;
        }

        const yli::ontology::Symbiosis* const symbiosis = static_cast<yli::ontology::Symbiosis*>(holobiont->get_parent());

        if (symbiosis == nullptr)
        {
            std::cerr << "ERROR: `Biont::render`: `symbiosis` is `nullptr`!\n";
            return;
        }

        if (this->should_render)
        {
            this->render_this_biont(symbiosis->get_shader());
        }
    }

    void Biont::render_this_biont(const yli::ontology::Shader* const shader)
    {
        // Requirements:
        // `this->universe` must not be `nullptr`.
        // `shader` must not be `nullptr`.
        // `this->holobiont_parent` must not be `nullptr`.
        // `this->symbiont_species` must not be `nullptr`.

        yli::ontology::Universe& universe = this->universe;

        if (shader == nullptr)
        {
            std::cerr << "ERROR: `Biont::render_this_biont`: `shader` is `nullptr`!\n";
            return;
        }

        const yli::ontology::Holobiont* const holobiont = static_cast<yli::ontology::Holobiont*>(this->get_parent());

        if (holobiont == nullptr)
        {
            std::cerr << "ERROR: `Biont::render_this_biont`: `holobiont` is `nullptr`!\n";
            return;
        }

        yli::ontology::Symbiosis* const symbiosis = static_cast<yli::ontology::Symbiosis*>(holobiont->get_parent());

        if (symbiosis == nullptr)
        {
            std::cerr << "ERROR: `Biont::render_this_biont`: `symbiosis` is `nullptr`!\n";
            return;
        }

        const yli::ontology::SymbiontSpecies* const symbiont_species = static_cast<yli::ontology::SymbiontSpecies*>(this->apprentice_of_symbiont_species.get_master());

        if (symbiont_species == nullptr)
        {
            std::cerr << "ERROR: `Biont::render_this_biont`: `symbiont_species` is `nullptr`!\n";
            return;
        }

        this->model_matrix = glm::mat4(1.0f);

        const std::string model_file_format = symbiosis->get_model_file_format();

        if (this->initial_rotate_vectors.size() == this->initial_rotate_angles.size())
        {
            for (std::size_t i = 0; i < this->initial_rotate_vectors.size() && i < this->initial_rotate_angles.size(); i++)
            {
                this->model_matrix = glm::rotate(this->model_matrix, this->initial_rotate_angles[i], this->initial_rotate_vectors[i]);
            }
        }

        this->model_matrix = glm::scale(this->model_matrix, this->original_scale_vector);
        glm::vec3 euler_angles { holobiont->roll, holobiont->yaw, holobiont->pitch };
        glm::quat my_quaternion = glm::quat(euler_angles);
        glm::mat4 rotation_matrix = glm::mat4_cast(my_quaternion);
        this->model_matrix = rotation_matrix * this->model_matrix;
        this->model_matrix[3][0] = holobiont->cartesian_coordinates.x;
        this->model_matrix[3][1] = holobiont->cartesian_coordinates.y;
        this->model_matrix[3][2] = holobiont->cartesian_coordinates.z;

        this->mvp_matrix = universe.get_projection_matrix() * universe.get_view_matrix() * this->model_matrix;

        // '`Material`' part begins here.

        // Bind our texture in Texture Unit 0.
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, symbiosis->get_texture(this->biontID));
        // Set our "texture_sampler" sampler to user Texture Unit 0.
        yli::opengl::uniform_1i(symbiosis->get_openGL_textureID(this->biontID), 0);

        // '`Material`' part ends here.

        // '`Species`' part begins here.

        // Compute the MVP matrix from keyboard and mouse input.
        const glm::vec3& light_position = symbiosis->get_light_position(this->biontID);
        glUniform3f(
                symbiosis->get_light_id(this->biontID),
                light_position.x,
                light_position.y,
                light_position.z);

        const yli::ontology::MeshModule& mesh = symbiont_species->mesh;

        // 1st attribute buffer : vertices.
        yli::opengl::enable_vertex_attrib_array(mesh.get_vertex_position_modelspace_id());

        // 2nd attribute buffer : UVs.
        yli::opengl::enable_vertex_attrib_array(mesh.get_vertex_uv_id());

        // 3rd attribute buffer : normals.
        yli::opengl::enable_vertex_attrib_array(mesh.get_vertex_normal_modelspace_id());

        // '`Species`' part ends here.

        // Send our transformation to the currently bound shader,
        // in the "MVP" uniform.
        glUniformMatrix4fv(shader->get_matrix_id(), 1, GL_FALSE, &this->mvp_matrix[0][0]);
        glUniformMatrix4fv(shader->get_model_matrix_id(), 1, GL_FALSE, &this->model_matrix[0][0]);

        GLuint vao                             = mesh.get_vao();
        GLuint vertexbuffer                    = mesh.get_vertexbuffer();
        uint32_t vertex_position_modelspace_id = mesh.get_vertex_position_modelspace_id();
        GLuint uvbuffer                        = mesh.get_uvbuffer();
        uint32_t vertex_uv_id                  = mesh.get_vertex_uv_id();
        GLuint normalbuffer                    = mesh.get_normalbuffer();
        uint32_t vertex_normal_modelspace_id   = mesh.get_vertex_normal_modelspace_id();
        GLuint elementbuffer                   = mesh.get_elementbuffer();
        uint32_t indices_size                  = mesh.get_indices_size();

        glBindVertexArray(vao);

        // 1st attribute buffer : vertices.
        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
        glVertexAttribPointer(
                vertex_position_modelspace_id, // The attribute we want to configure
                3,                            // size
                GL_FLOAT,                     // type
                GL_FALSE,                     // normalized?
                0,                            // stride
                (void*) 0                     // array buffer offset
                );
        yli::opengl::enable_vertex_attrib_array(vertex_position_modelspace_id);

        // 2nd attribute buffer : UVs.
        glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
        glVertexAttribPointer(
                vertex_uv_id,                   // The attribute we want to configure
                2,                            // size : U+V => 2
                GL_FLOAT,                     // type
                GL_FALSE,                     // normalized?
                0,                            // stride
                (void*) 0                     // array buffer offset
                );
        yli::opengl::enable_vertex_attrib_array(vertex_uv_id);

        // 3rd attribute buffer : normals.
        glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
        glVertexAttribPointer(
                vertex_normal_modelspace_id,   // The attribute we want to configure
                3,                            // size
                GL_FLOAT,                     // type
                GL_FALSE,                     // normalized?
                0,                            // stride
                (void*) 0                     // array buffer offset
                );
        yli::opengl::enable_vertex_attrib_array(vertex_normal_modelspace_id);

        // Index buffer.
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);

        // Draw the triangles!
        glDrawElements(
                GL_TRIANGLES,                 // mode
                indices_size,                 // count
                GL_UNSIGNED_INT,              // type
                (void*) 0                     // element array buffer offset
                );

        yli::opengl::disable_vertex_attrib_array(mesh.get_vertex_position_modelspace_id());
        yli::opengl::disable_vertex_attrib_array(mesh.get_vertex_uv_id());
        yli::opengl::disable_vertex_attrib_array(mesh.get_vertex_normal_modelspace_id());
        yli::opengl::disable_vertex_attrib_array(vertex_position_modelspace_id);
        yli::opengl::disable_vertex_attrib_array(vertex_uv_id);
        yli::opengl::disable_vertex_attrib_array(vertex_normal_modelspace_id);
    }

    yli::ontology::Scene* Biont::get_scene() const
    {
        yli::ontology::Entity* const parent = this->get_parent();

        if (parent != nullptr)
        {
            return parent->get_scene();
        }

        return nullptr;
    }

    std::size_t Biont::get_number_of_children() const
    {
        return 0; // `Biont` has no children.
    }

    std::size_t Biont::get_number_of_descendants() const
    {
        return 0; // `Biont` has no children.
    }
}
<|endoftext|>


<commit_before>/*!
  \copyright (c) RDO-Team, 2011
  \file      main.cpp
  \authors     (rdo@rk9.bmstu.ru)
  \authors     (lord.tiran@gmail.com)
  \authors     (robot.xet@gmail.com)
  \date      13.07.2009
  \brief       RDOValue
  \indent    4T
*/

// ---------------------------------------------------------------------------- PCH
// ----------------------------------------------------------------------- INCLUDES
#include <iostream>
#include <boost/regex.hpp>
#define BOOST_TEST_MODULE RDOValue_Test
#include <boost/test/included/unit_test.hpp>
// ----------------------------------------------------------------------- SYNOPSIS
#include "simulator/runtime/rdo_runtime.h"
#include "simulator/runtime/rdo_res_type.h"
// --------------------------------------------------------------------------------

BOOST_AUTO_TEST_SUITE(RDOValue_Test)

BOOST_AUTO_TEST_CASE(RDOValue_String)
{
	const tstring str1 = _T("qqq");
	rdoRuntime::RDOValue value1(str1);
	BOOST_CHECK(value1.getString  () == str1);
	BOOST_CHECK(value1.getAsString() == str1);

	rdoRuntime::RDOValue value2 = value1;
	BOOST_CHECK(value2.getString  () == str1);
	BOOST_CHECK(value2.getAsString() == str1);
	BOOST_CHECK(value2 == value1);

	const tstring str2 = _T("aaa");
	value2 += str2;
	BOOST_CHECK(value2.getString  () == str1 + str2);
	BOOST_CHECK(value2.getAsString() == str1 + str2);
}

BOOST_AUTO_TEST_CASE(RDOValue_Rsint_Arifmethic)
{
	const rsint val1 = 30;
	rdoRuntime::RDOValue value1(val1);
	BOOST_CHECK(value1.getInt() == val1);

	rdoRuntime::RDOValue value2 = value1;
	BOOST_CHECK(value2 == val1);
	BOOST_CHECK(value2 == value1);

	const rsint val2 = 20;
	value1 += val2;
	BOOST_CHECK(value1 == val1 + val2);

	const rsint val3 = 10;
	value1 -= val3;
	BOOST_CHECK(value1 == val1 + val2 - val3);

	const rsint val4 = 2;
	value2 = value1;
	value2 *= val4;
	BOOST_CHECK(value2 == (val1 + val2 - val3) * val4);

	const rsint val5 = 5;
	value2 = value1;
	value2 /= val5;
	BOOST_CHECK(value2 == ((val1 + val2 - val3) / val5));

	value2 = value1;
	value2 --;
	BOOST_CHECK(value2 == value1 - 1);
	value2 ++;
	BOOST_CHECK(value2 == value1);
}

BOOST_AUTO_TEST_CASE(RDOValue_Rsint_Compare)
{
	const rsint val1 = 30;
	const rsint val2 = 20;
	rdoRuntime::RDOValue value1(val1);
	rdoRuntime::RDOValue value2(val2);

	BOOST_CHECK(value1 != value2);
	BOOST_CHECK(value1 > value2);
	BOOST_CHECK(value2 < value1);
	BOOST_CHECK(value1 >= value2);
	BOOST_CHECK(value2 <= value1);
	value2 = val1;
	BOOST_CHECK(value1 >= value2);
	BOOST_CHECK(value2 <= value1);
}

BOOST_AUTO_TEST_CASE(RDOValue_Ruint_Arifmethic)
{
	const ruint val1 = 30;
	rdoRuntime::RDOValue value1(val1);
	BOOST_CHECK(value1 == val1);
	//BOOST_CHECK(value1.getUInt() == val1);

	rdoRuntime::RDOValue value2 = value1;
	BOOST_CHECK(value2 == val1);
	BOOST_CHECK(value2 == value1);

	const ruint val2 = 20;
	value1 += val2;
	BOOST_CHECK(value1 == val1 + val2);

	const ruint val3 = 10;
	value1 -= val3;
	BOOST_CHECK(value1 == val1 + val2 - val3);

	const ruint val4 = 2;
	value2 = value1;
	value2 *= val4;
	BOOST_CHECK(value2 == (val1 + val2 - val3) * val4);

	const ruint val5 = 5;
	value2 = value1;
	value2 /= val5;
	BOOST_CHECK(value2 == ((val1 + val2 - val3) / val5));

	value2 = value1;
	value2 --;
	BOOST_CHECK(value2 == value1 - 1);
	value2 ++;
	BOOST_CHECK(value2 == value1);
}

BOOST_AUTO_TEST_CASE(RDOValue_Ruint_Compare)
{
	const ruint val1 = 30;
	const ruint val2 = 20;
	rdoRuntime::RDOValue value1(val1);
	rdoRuntime::RDOValue value2(val2);

	BOOST_CHECK(value1 != value2);
	BOOST_CHECK(value1 > value2);
	BOOST_CHECK(value2 < value1);
	BOOST_CHECK(value1 >= value2);
	BOOST_CHECK(value2 <= value1);
	value2 = val1;
	BOOST_CHECK(value1 >= value2);
	BOOST_CHECK(value2 <= value1);
}

BOOST_AUTO_TEST_CASE(RDOValue_Double_Arifmethic)
{
	const double doub1 = 30.2;
	rdoRuntime::RDOValue value1(doub1);
	BOOST_CHECK(value1 == doub1);
	//BOOST_CHECK(value1.getDouble() == doub1);

	rdoRuntime::RDOValue value2 = value1;
	BOOST_CHECK(value2 == doub1);
	BOOST_CHECK(value2 == value1);

	const double doub2 = 20.5;
	value1 += doub2;
	BOOST_CHECK(value1 == doub1 + doub2);

	const double doub3 = 10.3;
	value1 -= doub3;
	BOOST_CHECK(value1 == doub1 + doub2 - doub3);

	const double doub4 = 2.5;
	value2 = value1;
	value2 *= doub4;
	BOOST_CHECK(value2 == (doub1 + doub2 - doub3) * doub4);

	const double doub5 = 5;
	value2 = value1;
	value2 /= doub5;
	BOOST_CHECK(value2 == ((doub1 + doub2 - doub3) / doub5));

	value2 = value1;
	value2 --;
	BOOST_CHECK(value2 == value1 - 1);
	value2 ++;
	BOOST_CHECK(value2 == value1);
}

BOOST_AUTO_TEST_CASE(RDOValue_Double_Compare)
{
	const double doub1 = 30.2;
	const double doub2 = 20.5;
	rdoRuntime::RDOValue value1(doub1);
	rdoRuntime::RDOValue value2(doub2);

	BOOST_CHECK(value1 != value2);
	BOOST_CHECK(value1 > value2);
	BOOST_CHECK(value2 < value1);
	BOOST_CHECK(value1 >= value2);
	BOOST_CHECK(value2 <= value1);
	value2 = doub1;
	BOOST_CHECK(value1 >= value2);
	BOOST_CHECK(value2 <= value1);
}

BOOST_AUTO_TEST_CASE(RDOValue_Bool)
{
	rbool bool1 = true;
	rbool bool2 = false;
	rbool bool3 = true;
	rbool bool4 = false;

	rdoRuntime::RDOValue value1(bool1);
	rdoRuntime::RDOValue value2(bool2);
	rdoRuntime::RDOValue value3(bool3);
	rdoRuntime::RDOValue value4(bool4);

	BOOST_CHECK(value1.getBool());
	BOOST_CHECK(!value2);
	BOOST_CHECK(value2 == value4);
	BOOST_CHECK(value1 != value2);
	BOOST_CHECK(!(value1 == value2));
	BOOST_CHECK(value1 && value3);
	BOOST_CHECK(!(value2 && value3));
	BOOST_CHECK(value1 || value2);
	BOOST_CHECK(!(value2 || value4));
}

BOOST_AUTO_TEST_CASE(RDOValue_Char)
{
	tchar ch1 = 'a';
	tchar ch2 = 'b';
	rdoRuntime::RDOValue value1 = ch1;
	rdoRuntime::RDOValue value2 = ch2;
	BOOST_CHECK(value1 == ch1);
	BOOST_CHECK(value1 < value2);
	BOOST_CHECK(value2 > value1);
	BOOST_CHECK(value1 != value2);
	value1 = value2;
	BOOST_CHECK(value1 == value2);
}

BOOST_AUTO_TEST_CASE(RDOValue_Enum)
{
	using namespace rdoRuntime;
	RDOEnumType::EnumItem item1 = "test1";
	BOOST_CHECK(item1 == "test1");
	RDOEnumType::Enums enum1;
	enum1.push_back(item1);
	BOOST_CHECK(enum1[0] == item1);

	LPRDOEnumType pEnum = rdo::Factory<RDOEnumType>::create();
	BOOST_CHECK(pEnum);
	BOOST_CHECK(pEnum->empty());

}

/*
BOOST_AUTO_TEST_CASE(RDOValue_Identificator)
{

}
*/
BOOST_AUTO_TEST_CASE(RDOValue_Resource)
{
	using namespace rdoRuntime;

	LPRDORuntime pRuntime = rdo::Factory<RDORuntime>::create();
	BOOST_CHECK(pRuntime);

	LPRDOResourceType pResourceType = rdo::Factory<RDOResourceType>::create(0);
	BOOST_CHECK(pResourceType);
	LPIResourceType pResourceFactory = pResourceType.interface_cast<IResourceType>();
	BOOST_CHECK(pResourceFactory);

	std::vector<RDOValue> paramList;
	paramList.push_back(RDOValue(1      ));
	paramList.push_back(RDOValue(2.2    ));
	paramList.push_back(RDOValue(_T("3")));

	LPRDOResource pResource = pResourceFactory->createRes(pRuntime, pRuntime->getResourceId(), paramList, true, true);
	BOOST_CHECK(pResource);

	RDOValue value1(pResourceType, pResource);

	LPRDOResourceType pType = value1.type().object_dynamic_cast<RDOResourceType>();
	BOOST_CHECK(pType);

	LPRDOResource pResource1 = value1.getPointer<RDOResource>();

	pRuntime   = NULL;
	value1     = RDOValue();
	pResource1 = NULL;

	BOOST_CHECK(pResource.owner());

	pResource = NULL;
}

BOOST_AUTO_TEST_SUITE_END() //RDOValue_Resource
<commit_msg> - начало теста enum'а<commit_after>/*!
  \copyright (c) RDO-Team, 2011
  \file      main.cpp
  \authors     (rdo@rk9.bmstu.ru)
  \authors     (lord.tiran@gmail.com)
  \authors     (robot.xet@gmail.com)
  \date      13.07.2009
  \brief       RDOValue
  \indent    4T
*/

// ---------------------------------------------------------------------------- PCH
// ----------------------------------------------------------------------- INCLUDES
#include <iostream>
#include <boost/regex.hpp>
#define BOOST_TEST_MODULE RDOValue_Test
#include <boost/test/included/unit_test.hpp>
// ----------------------------------------------------------------------- SYNOPSIS
#include "simulator/runtime/rdo_runtime.h"
#include "simulator/runtime/rdo_res_type.h"
// --------------------------------------------------------------------------------

BOOST_AUTO_TEST_SUITE(RDOValue_Test)

BOOST_AUTO_TEST_CASE(RDOValue_String)
{
	const tstring str1 = _T("qqq");
	rdoRuntime::RDOValue value1(str1);
	BOOST_CHECK(value1.getString  () == str1);
	BOOST_CHECK(value1.getAsString() == str1);

	rdoRuntime::RDOValue value2 = value1;
	BOOST_CHECK(value2.getString  () == str1);
	BOOST_CHECK(value2.getAsString() == str1);
	BOOST_CHECK(value2 == value1);

	const tstring str2 = _T("aaa");
	value2 += str2;
	BOOST_CHECK(value2.getString  () == str1 + str2);
	BOOST_CHECK(value2.getAsString() == str1 + str2);
}

BOOST_AUTO_TEST_CASE(RDOValue_Rsint_Arifmethic)
{
	const rsint val1 = 30;
	rdoRuntime::RDOValue value1(val1);
	BOOST_CHECK(value1.getInt() == val1);

	rdoRuntime::RDOValue value2 = value1;
	BOOST_CHECK(value2 == val1);
	BOOST_CHECK(value2 == value1);

	const rsint val2 = 20;
	value1 += val2;
	BOOST_CHECK(value1 == val1 + val2);

	const rsint val3 = 10;
	value1 -= val3;
	BOOST_CHECK(value1 == val1 + val2 - val3);

	const rsint val4 = 2;
	value2 = value1;
	value2 *= val4;
	BOOST_CHECK(value2 == (val1 + val2 - val3) * val4);

	const rsint val5 = 5;
	value2 = value1;
	value2 /= val5;
	BOOST_CHECK(value2 == ((val1 + val2 - val3) / val5));

	value2 = value1;
	value2 --;
	BOOST_CHECK(value2 == value1 - 1);
	value2 ++;
	BOOST_CHECK(value2 == value1);
}

BOOST_AUTO_TEST_CASE(RDOValue_Rsint_Compare)
{
	const rsint val1 = 30;
	const rsint val2 = 20;
	rdoRuntime::RDOValue value1(val1);
	rdoRuntime::RDOValue value2(val2);

	BOOST_CHECK(value1 != value2);
	BOOST_CHECK(value1 > value2);
	BOOST_CHECK(value2 < value1);
	BOOST_CHECK(value1 >= value2);
	BOOST_CHECK(value2 <= value1);
	value2 = val1;
	BOOST_CHECK(value1 >= value2);
	BOOST_CHECK(value2 <= value1);
}

BOOST_AUTO_TEST_CASE(RDOValue_Ruint_Arifmethic)
{
	const ruint val1 = 30;
	rdoRuntime::RDOValue value1(val1);
	BOOST_CHECK(value1 == val1);
	//BOOST_CHECK(value1.getUInt() == val1);

	rdoRuntime::RDOValue value2 = value1;
	BOOST_CHECK(value2 == val1);
	BOOST_CHECK(value2 == value1);

	const ruint val2 = 20;
	value1 += val2;
	BOOST_CHECK(value1 == val1 + val2);

	const ruint val3 = 10;
	value1 -= val3;
	BOOST_CHECK(value1 == val1 + val2 - val3);

	const ruint val4 = 2;
	value2 = value1;
	value2 *= val4;
	BOOST_CHECK(value2 == (val1 + val2 - val3) * val4);

	const ruint val5 = 5;
	value2 = value1;
	value2 /= val5;
	BOOST_CHECK(value2 == ((val1 + val2 - val3) / val5));

	value2 = value1;
	value2 --;
	BOOST_CHECK(value2 == value1 - 1);
	value2 ++;
	BOOST_CHECK(value2 == value1);
}

BOOST_AUTO_TEST_CASE(RDOValue_Ruint_Compare)
{
	const ruint val1 = 30;
	const ruint val2 = 20;
	rdoRuntime::RDOValue value1(val1);
	rdoRuntime::RDOValue value2(val2);

	BOOST_CHECK(value1 != value2);
	BOOST_CHECK(value1 > value2);
	BOOST_CHECK(value2 < value1);
	BOOST_CHECK(value1 >= value2);
	BOOST_CHECK(value2 <= value1);
	value2 = val1;
	BOOST_CHECK(value1 >= value2);
	BOOST_CHECK(value2 <= value1);
}

BOOST_AUTO_TEST_CASE(RDOValue_Double_Arifmethic)
{
	const double doub1 = 30.2;
	rdoRuntime::RDOValue value1(doub1);
	BOOST_CHECK(value1 == doub1);
	//BOOST_CHECK(value1.getDouble() == doub1);

	rdoRuntime::RDOValue value2 = value1;
	BOOST_CHECK(value2 == doub1);
	BOOST_CHECK(value2 == value1);

	const double doub2 = 20.5;
	value1 += doub2;
	BOOST_CHECK(value1 == doub1 + doub2);

	const double doub3 = 10.3;
	value1 -= doub3;
	BOOST_CHECK(value1 == doub1 + doub2 - doub3);

	const double doub4 = 2.5;
	value2 = value1;
	value2 *= doub4;
	BOOST_CHECK(value2 == (doub1 + doub2 - doub3) * doub4);

	const double doub5 = 5;
	value2 = value1;
	value2 /= doub5;
	BOOST_CHECK(value2 == ((doub1 + doub2 - doub3) / doub5));

	value2 = value1;
	value2 --;
	BOOST_CHECK(value2 == value1 - 1);
	value2 ++;
	BOOST_CHECK(value2 == value1);
}

BOOST_AUTO_TEST_CASE(RDOValue_Double_Compare)
{
	const double doub1 = 30.2;
	const double doub2 = 20.5;
	rdoRuntime::RDOValue value1(doub1);
	rdoRuntime::RDOValue value2(doub2);

	BOOST_CHECK(value1 != value2);
	BOOST_CHECK(value1 > value2);
	BOOST_CHECK(value2 < value1);
	BOOST_CHECK(value1 >= value2);
	BOOST_CHECK(value2 <= value1);
	value2 = doub1;
	BOOST_CHECK(value1 >= value2);
	BOOST_CHECK(value2 <= value1);
}

BOOST_AUTO_TEST_CASE(RDOValue_Bool)
{
	rbool bool1 = true;
	rbool bool2 = false;
	rbool bool3 = true;
	rbool bool4 = false;

	rdoRuntime::RDOValue value1(bool1);
	rdoRuntime::RDOValue value2(bool2);
	rdoRuntime::RDOValue value3(bool3);
	rdoRuntime::RDOValue value4(bool4);

	BOOST_CHECK(value1.getBool());
	BOOST_CHECK(!value2);
	BOOST_CHECK(value2 == value4);
	BOOST_CHECK(value1 != value2);
	BOOST_CHECK(!(value1 == value2));
	BOOST_CHECK(value1 && value3);
	BOOST_CHECK(!(value2 && value3));
	BOOST_CHECK(value1 || value2);
	BOOST_CHECK(!(value2 || value4));
}

BOOST_AUTO_TEST_CASE(RDOValue_Char)
{
	tchar ch1 = 'a';
	tchar ch2 = 'b';
	rdoRuntime::RDOValue value1 = ch1;
	rdoRuntime::RDOValue value2 = ch2;
	BOOST_CHECK(value1 == ch1);
	BOOST_CHECK(value1 < value2);
	BOOST_CHECK(value2 > value1);
	BOOST_CHECK(value1 != value2);
	value1 = value2;
	BOOST_CHECK(value1 == value2);
}

BOOST_AUTO_TEST_CASE(RDOValue_Enum)
{
	using namespace rdoRuntime;
	LPRDOEnumType pEnum = rdo::Factory<RDOEnumType>::create();
	BOOST_CHECK(pEnum);
	BOOST_CHECK(pEnum->empty());
	pEnum->add("test0");
	pEnum->add("test1");
	pEnum->add("test2");
	pEnum->add("test3");

	RDOValue value(pEnum);
	BOOST_CHECK(value.typeID() == RDOType::t_enum);
}

/*
BOOST_AUTO_TEST_CASE(RDOValue_Identificator)
{

}
*/
BOOST_AUTO_TEST_CASE(RDOValue_Resource)
{
	using namespace rdoRuntime;

	LPRDORuntime pRuntime = rdo::Factory<RDORuntime>::create();
	BOOST_CHECK(pRuntime);

	LPRDOResourceType pResourceType = rdo::Factory<RDOResourceType>::create(0);
	BOOST_CHECK(pResourceType);
	LPIResourceType pResourceFactory = pResourceType.interface_cast<IResourceType>();
	BOOST_CHECK(pResourceFactory);

	std::vector<RDOValue> paramList;
	paramList.push_back(RDOValue(1      ));
	paramList.push_back(RDOValue(2.2    ));
	paramList.push_back(RDOValue(_T("3")));

	LPRDOResource pResource = pResourceFactory->createRes(pRuntime, pRuntime->getResourceId(), paramList, true, true);
	BOOST_CHECK(pResource);

	RDOValue value1(pResourceType, pResource);

	LPRDOResourceType pType = value1.type().object_dynamic_cast<RDOResourceType>();
	BOOST_CHECK(pType);

	LPRDOResource pResource1 = value1.getPointer<RDOResource>();

	pRuntime   = NULL;
	value1     = RDOValue();
	pResource1 = NULL;

	BOOST_CHECK(pResource.owner());

	pResource = NULL;
}

BOOST_AUTO_TEST_SUITE_END() //RDOValue_Resource
<|endoftext|>


<commit_before>#include "tiramisu/tiramisu.h"

using namespace tiramisu;

#define mixf(x, y, a) (cast(p_float32, x) * (expr((float) 1) - cast(p_float32, a)) + cast(p_float32, y) * cast(p_float32, a))

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

    // Name of the function that we want to generate.
    tiramisu::init("warp_affine_tiramisu");

    // Declare an input that holds the sizes of input arrays.
    input SIZES("SIZES", {var("S", 0, 2)}, p_int32);

    constant N0("N0", SIZES(0));
    constant N1("N1", SIZES(1));

    var x("x", 0, N1), y("y", 0, N0);
    input in("in", {y, x}, p_uint8);

    expr a00 = expr((float) 0.1);
    expr a01 = expr((float) 0.1);
    expr a10 = expr((float) 0.1);
    expr a11 = expr((float) 0.1);
    expr b00 = expr((float) 0.1);
    expr b10 = expr((float) 0.1);

    // Translating this algorithm as close as possible
    expr o_r = a11*cast(p_float32, y) + a10*cast(p_float32, x) + b00;
    expr o_c = a01*cast(p_float32, y) + a00*cast(p_float32, x) + b10;

    expr r = o_r - floor(o_r);
    expr c = o_c - floor(o_c);

    expr coord_00_r = cast(p_int32, floor(o_r));
    expr coord_00_c = cast(p_int32, floor(o_c));
    expr coord_01_r = cast(p_int32, coord_00_r);
    expr coord_01_c = cast(p_int32, coord_00_c + 1);
    expr coord_10_r = cast(p_int32, coord_00_r + 1);
    expr coord_10_c = cast(p_int32, coord_00_c);
    expr coord_11_r = cast(p_int32, coord_00_r + 1);
    expr coord_11_c = cast(p_int32, coord_00_c + 1);

    coord_00_r = clamp(coord_00_r, 0, N0);
    coord_00_c = clamp(coord_00_c, 0, N1);
    coord_01_r = clamp(coord_01_r, 0, N0);
    coord_01_c = clamp(coord_01_c, 0, N1);
    coord_10_r = clamp(coord_10_r, 0, N0);
    coord_10_c = clamp(coord_10_c, 0, N1);
    coord_11_r = clamp(coord_11_r, 0, N0);
    coord_11_c = clamp(coord_11_c, 0, N1);

    expr A00 = in(coord_00_c, coord_00_r);
    expr A10 = in(coord_10_c, coord_10_r);
    expr A01 = in(coord_01_c, coord_01_r);
    expr A11 = in(coord_11_c, coord_11_r);

    expr e = cast(p_float32, mixf(mixf(A00, A10, r), mixf(A01, A11, r), c));

    computation affine({y, x}, e);

    affine.parallelize(y);
    affine.vectorize(x, 16);

    buffer  b_input("b_input",  {N0, N1}, p_uint8, a_input);
    buffer b_SIZES("b_SIZES", {2}, p_int32, a_input);
    buffer b_affine("b_affine", {N0, N1}, p_float32, a_output);
    in.store_in(&b_input);
    SIZES.store_in(&b_SIZES);
    affine.store_in(&b_affine);

    tiramisu::codegen({&b_SIZES, &b_input, &b_affine}, "build/generated_fct_warp_affine.o");

    return 0;
}
<commit_msg>Update warpAffine<commit_after>#include "tiramisu/tiramisu.h"

using namespace tiramisu;

#define mixf(x, y, a) (cast(p_float32, x) * (expr((float) 1) - cast(p_float32, a)) + cast(p_float32, y) * cast(p_float32, a))

int main(int argc, char* argv[])
{
    tiramisu::init("warp_affine_tiramisu");

    input SIZES("SIZES", {var("S", 0, 2)}, p_int32);

    constant N0("N0", SIZES(0));
    constant N1("N1", SIZES(1));

    var x("x", 0, N1), y("y", 0, N0);
    input in("in", {y, x}, p_uint8);

    expr a00 = expr((float) 0.1);
    expr a01 = expr((float) 0.1);
    expr a10 = expr((float) 0.1);
    expr a11 = expr((float) 0.1);
    expr b00 = expr((float) 0.1);
    expr b10 = expr((float) 0.1);

    expr o_r = a11*cast(p_float32, y) + a10*cast(p_float32, x) + b00;
    expr o_c = a01*cast(p_float32, y) + a00*cast(p_float32, x) + b10;

    expr r = o_r - floor(o_r);
    expr c = o_c - floor(o_c);

    expr coord_00_r = cast(p_int32, floor(o_r));
    expr coord_00_c = cast(p_int32, floor(o_c));
    expr coord_01_r = cast(p_int32, coord_00_r);
    expr coord_01_c = cast(p_int32, coord_00_c + 1);
    expr coord_10_r = cast(p_int32, coord_00_r + 1);
    expr coord_10_c = cast(p_int32, coord_00_c);
    expr coord_11_r = cast(p_int32, coord_00_r + 1);
    expr coord_11_c = cast(p_int32, coord_00_c + 1);

    coord_00_r = clamp(coord_00_r, 0, N0);
    coord_00_c = clamp(coord_00_c, 0, N1);
    coord_01_r = clamp(coord_01_r, 0, N0);
    coord_01_c = clamp(coord_01_c, 0, N1);
    coord_10_r = clamp(coord_10_r, 0, N0);
    coord_10_c = clamp(coord_10_c, 0, N1);
    coord_11_r = clamp(coord_11_r, 0, N0);
    coord_11_c = clamp(coord_11_c, 0, N1);

    expr A00 = in(coord_00_c, coord_00_r);
    expr A10 = in(coord_10_c, coord_10_r);
    expr A01 = in(coord_01_c, coord_01_r);
    expr A11 = in(coord_11_c, coord_11_r);

    expr e = cast(p_float32, mixf(mixf(A00, A10, r), mixf(A01, A11, r), c));

    computation affine({y, x}, e);

    affine.parallelize(y);
    affine.vectorize(x, 16);

    buffer  b_input("b_input",  {N0, N1}, p_uint8, a_input);
    buffer b_SIZES("b_SIZES", {2}, p_int32, a_input);
    buffer b_affine("b_affine", {N0, N1}, p_float32, a_output);
    in.store_in(&b_input);
    SIZES.store_in(&b_SIZES);
    affine.store_in(&b_affine);

    tiramisu::codegen({&b_SIZES, &b_input, &b_affine}, "build/generated_fct_warp_affine.o");

    return 0;
}
<|endoftext|>


<commit_before>#define QT_COMPILING_QSTRING_COMPAT_CPP
#include <QApplication>
#include <QTcpSocket>
#include <QTcpServer>

#include <QMainWindow>
#include <QDockWidget>
#include <QVBoxLayout>
#include <QPushButton>

#include <functional>

#include "MicroscopeTcpServerDockWidget.h"
#include "devices\microscope.h"
#include "AgentController.h"

namespace fetch {
namespace ui {

typedef QHash<QTcpSocket*, QByteArray*>  buffers_t;
typedef QHash<QTcpSocket*,bool>          validation_state_t;

typedef std::function<void(QTcpSocket*,QList<QString> & args)> callback_t;
typedef QHash<QString,callback_t>        protocol_t;

static void read(QTcpSocket* socket,buffers_t &buffers, QTcpServer &server,const protocol_t& protocol) {
    auto *buffer = buffers.value(socket);
    qDebug()<<"Reading from client";
    while (socket->bytesAvailable() > 0) {
        buffer->append(socket->readAll());
        auto s=QString::fromUtf8(buffer->data());
        auto keeplast=!s.endsWith("\r\n");
        auto cmds=s.split("\r\n",QString::SkipEmptyParts);
        buffer->clear();
        if(keeplast) {
            auto a=cmds.takeLast();
            auto b=a.toUtf8();
            buffer->append(b);
        }

        qDebug()<<"[Socket "<<socket<<"] "<<cmds;
        for(auto cmd:cmds) {
            auto parts=cmd.split(' ');
            auto c=parts.first();
            parts.pop_front();
            if(protocol.contains(c)) {
                qDebug()<<"\tProcessing: "<<cmd;
                qDebug()<<"\t\tCmd : "<<c;
                qDebug()<<"\t\tArgs: "<<parts;
                protocol[c](socket,parts);
                socket->write("Done\r\n");
            } else {
                qDebug()<<"\tReceived: "<<cmd;
                qDebug()<<"\tDid not match any of "<<protocol.keys();
                socket->write("Command not recognized\r\n");
            }
        }
    }
}

static void disconnect(QTcpSocket* socket, buffers_t &buffers) {
    qDebug()<<"disconnect";
    auto *buffer = buffers.value(socket);
    socket->deleteLater();
    delete buffer;
}

enum server_state_t{
    ServerRunning,
    ServerStopped
};

static const char * get_start_button_label(server_state_t state) {
    const char* s[]={"Stop","Start"};
    return s[state];
}

/* FIXME:
    arm/disarm/track microscope tasks?
*/

class device_t {
    enum device_state_t{
        DeviceRunning=0,
        DeviceStopped
    };
    QHash<Task*,QString> tasknames;
    QHash<QString,Task*> tasksByName;
    device::Microscope *dc;
    AgentController *ac;
public:
    device_t(device::Microscope* dc, AgentController *ac): dc(dc),ac(ac) {
        tasknames[&dc->interaction_task]="Video";
        tasknames[&dc->stack_task]      ="Stack";
        tasknames[&dc->time_series_task]="TimeSeries";
        tasknames[&dc->auto_tile_task]  ="AutoTileAcquisition";
        for(auto e=tasknames.constBegin();e!=tasknames.constEnd();++e)
            tasksByName[e.value()]=e.key();
    }
    inline device_state_t state() const {
        return dc->__self_agent.is_running()?DeviceRunning:DeviceStopped;
    }
    void run()  { ac->run();}
    void stop() { ac->stop();}
    QString task() const { return tasknames[dc->__self_agent._task]; };
    QList<QString> tasks() const { return tasknames.values(); }
    void set_task(const QString taskname) {
        auto t=tasksByName.value(taskname,0);
        if(t)
            ac->arm(t);
    }
};

class server_t {
    server_state_t state_;
    device_t *device;
    protocol_t protocol;
    validation_state_t validation_state; //Keep track of password-validation state for each connection
    QTcpServer s;
    buffers_t buffers; //We need a buffer to store data until command has completely received
public:
    explicit server_t(device_t *device,unsigned port=1024)
        : state_(ServerStopped)
        , device(device)
    {
        make_protocol();
        s.connect(&s,&QTcpServer::newConnection,[this](){this->on_connection();});
    }
    void toggle_state() {
        switch (state()) {
            case ServerRunning: stop(); break;
            case ServerStopped: start(); break;
            default:;
        }
        if(s.isListening())
            state_=ServerRunning;
        else
            state_=ServerStopped;
    }
    inline server_state_t state() const{ return state_; }
private:
    void on_connection() {
        while (s.hasPendingConnections())
        {
            qDebug()<<"Accepting connections...";
            auto *socket = s.nextPendingConnection();
            qDebug()<<"Peer address: "<<socket->peerAddress();
            s.connect(socket, &QTcpSocket::readyRead, [this,socket](){
                read(socket,this->buffers,this->s,this->protocol);
            });
            s.connect(socket, &QTcpSocket::disconnected, [this,socket]() {
                disconnect(socket,this->buffers);
            });
            buffers.insert(socket, new QByteArray());
            qDebug()<<"...accepted"<<socket;
        }
    }
    void start() {
        qDebug() << "Listening:" << s.listen(QHostAddress::Any,1024);
    }
    void stop() {
        validation_state.empty();
        buffers.empty();
        s.close();
        qDebug()<<"No longer accepting connections.";
    }
    auto is_validated(QTcpSocket *socket)->bool{
        if(validation_state.contains(socket))
            return validation_state[socket];
        return false;
    };
    void make_protocol() {
        protocol.insert("status",[this](QTcpSocket *socket,QList<QString> & args){
            const char* s[]={
                "running",
                "stopped"
            };
            if(!is_validated(socket)) return;
            auto resp=QString("Task: %1 State: %2\r\n").arg(this->device->task(),s[this->device->state()]);
            socket->write(resp.toUtf8());
        });
        protocol.insert("stop",[this](QTcpSocket *socket,QList<QString> & args) {
            if(!is_validated(socket)) return;
            this->device->stop();
        });
        protocol.insert("run",[this](QTcpSocket *socket,QList<QString> & args) {
            if(!is_validated(socket)) return;
            this->device->run();
        });
        protocol.insert("arm",[this](QTcpSocket *socket,QList<QString> & args) {
            if(!is_validated(socket)) return;
            this->device->set_task(args[0]);
        });
        protocol.insert("tasks",[this](QTcpSocket *socket,QList<QString> & args) {
            if(!is_validated(socket)) return;
            auto ts=this->device->tasks();
            for(auto t:ts)
                socket->write((t+QString("\r\n")).toUtf8());
        });
        protocol.insert("help",[this](QTcpSocket *socket,QList<QString> & args) {
            if(!is_validated(socket)) return;
            QTextStream cmdlist(socket);
            for(auto k:this->protocol.keys())
                cmdlist<<k<<"\r\n";
        });
        protocol.insert("version0",[this](QTcpSocket* socket,QList<QString> & args) {
            this->validation_state[socket]=true;
        });
    }
};

class server_widget_t : public QWidget {
    server_t server;
public:
    explicit server_widget_t(device_t *device,unsigned port=1024)
        : server(device,port)
    {
        auto *layout=new QVBoxLayout;
        setLayout(layout);
        auto *w=new QPushButton(get_start_button_label(server.state()));
        layout->addWidget(w);
        w->connect(w,&QPushButton::clicked,[this,w](){
            qDebug()<<"clicked";
            this->server.toggle_state();
            w->setText(get_start_button_label(this->server.state()));
        });
    }
};

MicroscopeTcpServerDockWidget::MicroscopeTcpServerDockWidget(device::Microscope* dc,  AgentController *ac,MainWindow* parent)
    : QDockWidget("TCP Server",parent)
{
    setWidget(new server_widget_t(new device_t(dc,ac)));
}

}} // fetch::ui<commit_msg>fix/AllowSearchRegionToShrink: Merge branch 'develop' into fix/AllowSearchRegionToShrink<commit_after>#define QT_COMPILING_QSTRING_COMPAT_CPP
#include <QApplication>
#include <QTcpSocket>
#include <QTcpServer>

#include <QMainWindow>
#include <QDockWidget>
#include <QVBoxLayout>
#include <QPushButton>

#include <functional>

#include "MicroscopeTcpServerDockWidget.h"
#include "devices\microscope.h"
#include "AgentController.h"

namespace fetch {
namespace ui {

typedef QHash<QTcpSocket*, QByteArray*>  buffers_t;
typedef QHash<QTcpSocket*,bool>          validation_state_t;

typedef std::function<void(QTcpSocket*,QList<QString> & args)> callback_t;
typedef QHash<QString,callback_t>        protocol_t;

static void read(QTcpSocket* socket,buffers_t &buffers, QTcpServer &server,const protocol_t& protocol) {
    auto *buffer = buffers.value(socket);
    qDebug()<<"Reading from client";
    while (socket->bytesAvailable() > 0) {
        buffer->append(socket->readAll());
        auto s=QString::fromUtf8(buffer->data());
        auto keeplast=!s.endsWith("\r\n");
        auto cmds=s.split("\r\n",QString::SkipEmptyParts);
        buffer->clear();
        if(keeplast) {
            auto a=cmds.takeLast();
            auto b=a.toUtf8();
            buffer->append(b);
        }

        qDebug()<<"[Socket "<<socket<<"] "<<cmds;
        for(auto cmd:cmds) {
            auto parts=cmd.split(' ');
            auto c=parts.first();
            parts.pop_front();
            if(protocol.contains(c)) {
                qDebug()<<"\tProcessing: "<<cmd;
                qDebug()<<"\t\tCmd : "<<c;
                qDebug()<<"\t\tArgs: "<<parts;
                protocol[c](socket,parts);
                socket->write("Done\r\n");
            } else {
                qDebug()<<"\tReceived: "<<cmd;
                qDebug()<<"\tDid not match any of "<<protocol.keys();
                socket->write("Command not recognized\r\n");
            }
        }
    }
}

static void disconnect(QTcpSocket* socket, buffers_t &buffers) {
    qDebug()<<"disconnect";
    auto *buffer = buffers.value(socket);
    socket->deleteLater();
    delete buffer;
}

enum server_state_t{
    ServerRunning,
    ServerStopped
};

static const char * get_start_button_label(server_state_t state) {
    const char* s[]={"Stop","Start"};
    return s[state];
}

/* FIXME:
    arm/disarm/track microscope tasks?
*/

class device_t {
    enum device_state_t{
        DeviceRunning=0,
        DeviceStopped
    };
    QHash<Task*,QString> tasknames;
    QHash<QString,Task*> tasksByName;
    device::Microscope *dc;
    AgentController *ac;
public:
    device_t(device::Microscope* dc, AgentController *ac): dc(dc),ac(ac) {
        tasknames[&dc->interaction_task]="Video";
        tasknames[&dc->stack_task]      ="Stack";
        tasknames[&dc->time_series_task]="TimeSeries";
        tasknames[&dc->auto_tile_task]  ="AutoTileAcquisition";
        for(auto e=tasknames.constBegin();e!=tasknames.constEnd();++e)
            tasksByName[e.value()]=e.key();
    }
    inline device_state_t state() const {
        return dc->__self_agent.is_running()?DeviceRunning:DeviceStopped;
    }
    void run()  { ac->run();}
    void stop() { ac->stop();}
    QString task() const { return tasknames[dc->__self_agent._task]; };
    QList<QString> tasks() const { return tasknames.values(); }
    void set_task(const QString taskname) {
        auto t=tasksByName.value(taskname,0);
        if(t)
            ac->arm(t);
    }
};

class server_t {
    server_state_t state_;
    device_t *device;
    protocol_t protocol;
    validation_state_t validation_state; //Keep track of password-validation state for each connection
    QTcpServer s;
    buffers_t buffers; //We need a buffer to store data until command has completely received
public:
    explicit server_t(device_t *device,unsigned port=1024)
        : state_(ServerRunning) //DGA: Made it so that it says it is running by default. Alternatively could just "click" it after it is created so it will be outputted
        , device(device)
    {
        make_protocol();
        s.connect(&s,&QTcpServer::newConnection,[this](){this->on_connection();});
		start(); //DGA: Actually make it start running by default
    }
    void toggle_state() {
        switch (state()) {
            case ServerRunning: stop(); break;
            case ServerStopped: start(); break;
            default:;
        }
        if(s.isListening())
            state_=ServerRunning;
        else
            state_=ServerStopped;
    }
    inline server_state_t state() const{ return state_; }
private:
    void on_connection() {
        while (s.hasPendingConnections())
        {
            qDebug()<<"Accepting connections...";
            auto *socket = s.nextPendingConnection();
            qDebug()<<"Peer address: "<<socket->peerAddress();
            s.connect(socket, &QTcpSocket::readyRead, [this,socket](){
                read(socket,this->buffers,this->s,this->protocol);
            });
            s.connect(socket, &QTcpSocket::disconnected, [this,socket]() {
                disconnect(socket,this->buffers);
            });
            buffers.insert(socket, new QByteArray());
            qDebug()<<"...accepted"<<socket;
        }
    }
    void start() {
        qDebug() << "Listening:" << s.listen(QHostAddress::Any,1024);
    }
    void stop() {
        validation_state.empty();
        buffers.empty();
        s.close();
        qDebug()<<"No longer accepting connections.";
    }
    auto is_validated(QTcpSocket *socket)->bool{
        if(validation_state.contains(socket))
            return validation_state[socket];
        return false;
    };
    void make_protocol() {
        protocol.insert("status",[this](QTcpSocket *socket,QList<QString> & args){
            const char* s[]={
                "running",
                "stopped"
            };
            if(!is_validated(socket)) return;
            auto resp=QString("Task: %1 State: %2\r\n").arg(this->device->task(),s[this->device->state()]);
            socket->write(resp.toUtf8());
        });
        protocol.insert("stop",[this](QTcpSocket *socket,QList<QString> & args) {
            if(!is_validated(socket)) return;
            this->device->stop();
        });
        protocol.insert("run",[this](QTcpSocket *socket,QList<QString> & args) {
            if(!is_validated(socket)) return;
            this->device->run();
        });
        protocol.insert("arm",[this](QTcpSocket *socket,QList<QString> & args) {
            if(!is_validated(socket)) return;
            this->device->set_task(args[0]);
        });
        protocol.insert("tasks",[this](QTcpSocket *socket,QList<QString> & args) {
            if(!is_validated(socket)) return;
            auto ts=this->device->tasks();
            for(auto t:ts)
                socket->write((t+QString("\r\n")).toUtf8());
        });
        protocol.insert("help",[this](QTcpSocket *socket,QList<QString> & args) {
            if(!is_validated(socket)) return;
            QTextStream cmdlist(socket);
            for(auto k:this->protocol.keys())
                cmdlist<<k<<"\r\n";
        });
        protocol.insert("version0",[this](QTcpSocket* socket,QList<QString> & args) {
            this->validation_state[socket]=true;
        });
    }
};

class server_widget_t : public QWidget {
    server_t server;
public:
    explicit server_widget_t(device_t *device,unsigned port=1024)
        : server(device,port)
    {
        auto *layout=new QVBoxLayout;
        setLayout(layout);
        auto *w=new QPushButton(get_start_button_label(server.state()));
        layout->addWidget(w);
        w->connect(w,&QPushButton::clicked,[this,w](){
            qDebug()<<"clicked";
            this->server.toggle_state();
            w->setText(get_start_button_label(this->server.state()));
        });
    }
};

MicroscopeTcpServerDockWidget::MicroscopeTcpServerDockWidget(device::Microscope* dc,  AgentController *ac,MainWindow* parent)
    : QDockWidget("TCP Server",parent)
{
    setWidget(new server_widget_t(new device_t(dc,ac)));
}

}} // fetch::ui<|endoftext|>


<commit_before>#include <anabel/anabel.h>
#include <iostream>
#include <sstream>
using namespace Anabel;
using namespace std;

int indent(char * db_to_indent) {
	try {
		TimeSeries ts(db_to_indent);
		ts.open(TSO_APPEND);
		ts.indent();
		ts.close();
	} catch (Anabel::Exceptions::InvalidRootDirectory) {
		std::cout << "ERROR: Invalid directory" << std::endl;
		return 2;
	}
	return 0;
}

int create(char * db_path, int record_size) {
	TimeSeries::create(db_path, record_size);
	return 0;
}

template <class T>
int view_t(Anabel::ReadQuery rq, T referential_type, int record_size) {
	if (sizeof(T) != record_size) return 3;		// invalid type

#pragma pack(push, 1)
	struct _e_struct {
		Timestamp timestamp;
		T value;
	};
#pragma pack(pop)

	rq.set_desired_cache_size(20000);
	_e_struct * buffer = (_e_struct*)malloc((8+sizeof(T))*20000);

	while (int items_readed = rq.get_data(20000, (void*)buffer))
		for (int i=0; i<items_readed; i++)
			std::cout << buffer[i].timestamp << " " << buffer[i].value << std::endl;

	free((void*)buffer);

	return 0;
}

int append(char * db_path, Anabel::Timestamp timestamp, std::string value, char * commontype) {
	auto_ptr<TimeSeries> ts;
	try {
		ts = auto_ptr<TimeSeries>(new TimeSeries(db_path));
	} catch (Anabel::Exceptions::InvalidRootDirectory) {
		return 2;
	}

	ts->open(TSO_APPEND);

	if ((strcmp(commontype, "float")==0) && (ts->record_size != 4)) return 3;
	if ((strcmp(commontype, "int32")==0) && (ts->record_size != 4)) return 3;
	if ((strcmp(commontype, "int8")==0) && (ts->record_size != 1)) return 3;

	char * absurdity_of_life = (char*)malloc(8+ts->record_size);
	*(Anabel::Timestamp*)absurdity_of_life = timestamp;

	if (strcmp(commontype, "float")==0) {
		float f;
		std::stringstream(value) >> f;
		*(float*)(absurdity_of_life+8) = f;
	}
	if (strcmp(commontype, "int32")==0) {
		int f;
		std::stringstream(value) >> f;
		*(int*)(absurdity_of_life+8) = f;
	}
	if (strcmp(commontype, "int8")==0) {
		char f;
		std::stringstream(value) >> f;
		*(char*)(absurdity_of_life+8) = f;
	}

	ts->append((void*)absurdity_of_life);

	free(absurdity_of_life);
	ts->close();
	return 0;
}

int view(char * db_path, Anabel::Timestamp t_from, Anabel::Timestamp t_to, char * commontype) {
	auto_ptr<TimeSeries> ts;
	try {
		ts = auto_ptr<TimeSeries>(new TimeSeries(db_path));
	} catch (Anabel::Exceptions::InvalidRootDirectory) {
		return 2;
	}

	ts->open(TSO_READ);

	Anabel::ReadQuery rq = ts->get_query(t_from, t_to);	// validity was checked earlier

	int return_value;
	if (strcmp("int32", commontype)==0) return_value = view_t(rq, (int)0, ts->record_size);
	if (strcmp("int8", commontype)==0) return_value = view_t(rq, (char)0, ts->record_size);
	if (strcmp("float", commontype)==0) return_value = view_t(rq, (float)0, ts->record_size);

	return return_value;
}<commit_msg>consistency in internally using destructors to close()<commit_after>#include <anabel/anabel.h>
#include <iostream>
#include <sstream>
using namespace Anabel;
using namespace std;

int indent(char * db_to_indent) {
	try {
		TimeSeries ts(db_to_indent);
		ts.open(TSO_APPEND);
		ts.indent();
		ts.close();
	} catch (Anabel::Exceptions::InvalidRootDirectory) {
		std::cout << "ERROR: Invalid directory" << std::endl;
		return 2;
	}
	return 0;
}

int create(char * db_path, int record_size) {
	TimeSeries::create(db_path, record_size);
	return 0;
}

template <class T>
int view_t(Anabel::ReadQuery rq, T referential_type, int record_size) {
	if (sizeof(T) != record_size) return 3;		// invalid type

#pragma pack(push, 1)
	struct _e_struct {
		Timestamp timestamp;
		T value;
	};
#pragma pack(pop)

	rq.set_desired_cache_size(20000);
	_e_struct * buffer = (_e_struct*)malloc((8+sizeof(T))*20000);

	while (int items_readed = rq.get_data(20000, (void*)buffer))
		for (int i=0; i<items_readed; i++)
			std::cout << buffer[i].timestamp << " " << buffer[i].value << std::endl;

	free((void*)buffer);

	return 0;
}

int append(char * db_path, Anabel::Timestamp timestamp, std::string value, char * commontype) {
	auto_ptr<TimeSeries> ts;
	try {
		ts = auto_ptr<TimeSeries>(new TimeSeries(db_path));
	} catch (Anabel::Exceptions::InvalidRootDirectory) {
		return 2;
	}

	ts->open(TSO_APPEND);

	if ((strcmp(commontype, "float")==0) && (ts->record_size != 4)) return 3;
	if ((strcmp(commontype, "int32")==0) && (ts->record_size != 4)) return 3;
	if ((strcmp(commontype, "int8")==0) && (ts->record_size != 1)) return 3;

	char * absurdity_of_life = (char*)malloc(8+ts->record_size);
	*(Anabel::Timestamp*)absurdity_of_life = timestamp;

	if (strcmp(commontype, "float")==0) {
		float f;
		std::stringstream(value) >> f;
		*(float*)(absurdity_of_life+8) = f;
	}
	if (strcmp(commontype, "int32")==0) {
		int f;
		std::stringstream(value) >> f;
		*(int*)(absurdity_of_life+8) = f;
	}
	if (strcmp(commontype, "int8")==0) {
		char f;
		std::stringstream(value) >> f;
		*(char*)(absurdity_of_life+8) = f;
	}

	ts->append((void*)absurdity_of_life);

	free(absurdity_of_life);
	return 0;
}

int view(char * db_path, Anabel::Timestamp t_from, Anabel::Timestamp t_to, char * commontype) {
	auto_ptr<TimeSeries> ts;
	try {
		ts = auto_ptr<TimeSeries>(new TimeSeries(db_path));
	} catch (Anabel::Exceptions::InvalidRootDirectory) {
		return 2;
	}

	ts->open(TSO_READ);

	Anabel::ReadQuery rq = ts->get_query(t_from, t_to);	// validity was checked earlier

	int return_value;
	if (strcmp("int32", commontype)==0) return_value = view_t(rq, (int)0, ts->record_size);
	if (strcmp("int8", commontype)==0) return_value = view_t(rq, (char)0, ts->record_size);
	if (strcmp("float", commontype)==0) return_value = view_t(rq, (float)0, ts->record_size);

	return return_value;
}<|endoftext|>


<commit_before>/* ===========================
  Copyright (c) 2013 Philippe Tillet
  UMinTL - Unconstrained Minimization Template Library

  License : MIT X11 - See the LICENSE file in the root folder
 * ===========================*/

#ifndef UMINTL_DIRECTIONS_SECOND_ORDER_SOLVE_FORWARDS_H_
#define UMINTL_DIRECTIONS_SECOND_ORDER_SOLVE_FORWARDS_H_

#include "umintl/tools/shared_ptr.hpp"

#include "conjugate_gradient/compute_Ab/forwards.h"
#include "conjugate_gradient/compute_Ab/gemv.hpp"

namespace umintl{

  namespace linear{

    template<class BackendType>
    struct conjugate_gradient{
      private:
        typedef typename BackendType::MatrixType MatrixType;
        typedef typename BackendType::VectorType VectorType;
        typedef typename BackendType::ScalarType ScalarType;
      public:
        enum return_code{
          SUCCESS,
          FAILURE
        };
      private:
        void allocate_tmp(std::size_t N){
          r = BackendType::create_vector(N);
          rr = BackendType::create_vector(N);
          p = BackendType::create_vector(N);
          Ap = BackendType::create_vector(N);
        }

        return_code clear_terminate(return_code ret){
          BackendType::delete_if_dynamically_allocated(r);
          BackendType::delete_if_dynamically_allocated(rr);
          BackendType::delete_if_dynamically_allocated(p);
          BackendType::delete_if_dynamically_allocated(Ap);
          return ret;
        }

      public:

        conjugate_gradient(std::size_t _max_iter, ScalarType _tolerance, conjugate_gradient_detail::compute_Ab<BackendType> * _compute_Ab = new umintl::linear::conjugate_gradient_detail::gemv<BackendType>()) :
          compute_Ab(_compute_Ab), max_iter(_max_iter), tolerance(_tolerance){ }

        return_code operator()(std::size_t N, MatrixType const & A, VectorType const & x0, VectorType const & b, VectorType & x)
        {
          allocate_tmp(N);

          //x = x0;
          BackendType::copy(N,x0,x);

          //r = Ax0 - b
          BackendType::symv(N,1,A,x0,0,r);
          BackendType::axpy(N,-1,b,r);

          //p = -r;
          BackendType::copy(N,r,p);
          BackendType::scale(N,-1,p);

          for(std::size_t i = 0 ; i < max_iter ; ++i){
            BackendType::symv(N,1,A,p,0,Ap); //Ap = A*p
            ScalarType alpha = BackendType::dot(N,r,r)/BackendType::dot(N,p,Ap); //alpha = r'*r/(p'*Ap)
            BackendType::axpy(N,alpha,p,x); //x = x + alpha*p
            BackendType::copy(N,r,rr); //rr = r + alpha*Ap
            BackendType::axpy(N,alpha,Ap,rr);
            ScalarType beta = BackendType::dot(N,rr,rr)/BackendType::dot(N,r,r); //beta = (rr'.rr)/(r'.r)
            BackendType::scale(N,beta,p);//pk = -rr + beta*pk
            BackendType::axpy(N,-1,rr,p);

            BackendType::copy(N,rr,r);//r = rr;

            ScalarType nrm_res = BackendType::nrm2(N,r);
            if(nrm_res < tolerance)
              return clear_terminate(SUCCESS);
          }
          return clear_terminate(FAILURE);
        }

        tools::shared_ptr<linear::conjugate_gradient_detail::compute_Ab<BackendType> > compute_Ab;
        std::size_t max_iter;
        ScalarType tolerance;

      private:
        VectorType r;
        VectorType rr;
        VectorType p;
        VectorType Ap;
    };

  }

}

#endif
<commit_msg>More efficient Linear-CG version<commit_after>/* ===========================
  Copyright (c) 2013 Philippe Tillet
  UMinTL - Unconstrained Minimization Template Library

  License : MIT X11 - See the LICENSE file in the root folder
 * ===========================*/

#ifndef UMINTL_DIRECTIONS_SECOND_ORDER_SOLVE_FORWARDS_H_
#define UMINTL_DIRECTIONS_SECOND_ORDER_SOLVE_FORWARDS_H_

#include "umintl/tools/shared_ptr.hpp"

#include "conjugate_gradient/compute_Ab/forwards.h"
#include "conjugate_gradient/compute_Ab/gemv.hpp"

namespace umintl{

  namespace linear{

    template<class BackendType>
    struct conjugate_gradient{
      private:
        typedef typename BackendType::MatrixType MatrixType;
        typedef typename BackendType::VectorType VectorType;
        typedef typename BackendType::ScalarType ScalarType;
      public:
        enum return_code{
          SUCCESS,
          FAILURE
        };
      private:
        void allocate_tmp(std::size_t N){
          r = BackendType::create_vector(N);
          p = BackendType::create_vector(N);
          Ap = BackendType::create_vector(N);
        }

        return_code clear_terminate(return_code ret){
          BackendType::delete_if_dynamically_allocated(r);
          BackendType::delete_if_dynamically_allocated(p);
          BackendType::delete_if_dynamically_allocated(Ap);
          return ret;
        }

      public:

        conjugate_gradient(std::size_t _max_iter, ScalarType _tolerance, conjugate_gradient_detail::compute_Ab<BackendType> * _compute_Ab = new umintl::linear::conjugate_gradient_detail::gemv<BackendType>()) :
          compute_Ab(_compute_Ab), max_iter(_max_iter), tolerance(_tolerance){ }

        return_code operator()(std::size_t N, MatrixType const & A, VectorType const & x0, VectorType const & b, VectorType & x)
        {
          allocate_tmp(N);
          ScalarType nrm_b = BackendType::nrm2(N,b);

          //x = x0;
          BackendType::copy(N,x0,x);
          //r = b - Ax0
          BackendType::symv(N,-1,A,x,0,r);
          BackendType::axpy(N,1,b,r);
          //p = r;
          BackendType::copy(N,r,p);
          ScalarType rso = BackendType::dot(N,r,r);

//          for(std::size_t i = 0 ; i < N ; ++i){
//            for(std::size_t j = 0 ; j < N ; ++j)
//              std::cout << A[i*N+j] << " " << std::flush;
//            std::cout << std::endl;
//          }

          for(std::size_t i = 0 ; i < max_iter ; ++i){
            BackendType::gemv(N,N,1,A,p,0,Ap); //Ap = A*p
            ScalarType alpha = rso/BackendType::dot(N,p,Ap); //alpha = rso/(p'*Ap)
            BackendType::axpy(N,alpha,p,x); //x = x + alpha*p
            BackendType::axpy(N,-alpha,Ap,r); //r = r - alpha*Ap
            ScalarType rsn = BackendType::dot(N,r,r);
            std::cout << std::sqrt(rsn)/nrm_b << std::endl;
            if(std::sqrt(rsn)/nrm_b < tolerance)
              return clear_terminate(SUCCESS);
            BackendType::scale(N,rsn/rso,p);//pk = r + rsn/rso*pk
            BackendType::axpy(N,1,r,p);
            rso = rsn;

          }
          return clear_terminate(FAILURE);
        }

        tools::shared_ptr<linear::conjugate_gradient_detail::compute_Ab<BackendType> > compute_Ab;
        std::size_t max_iter;
        ScalarType tolerance;

      private:
        VectorType r;
        VectorType p;
        VectorType Ap;
    };

  }

}

#endif
<|endoftext|>