<commit_before>
/*
  Copyright 1995 The University of Rhode Island and The Massachusetts
  Institute of Technology

  Portions of this software were developed by the Graduate School of
  Oceanography (GSO) at the University of Rhode Island (URI) in collaboration
  with The Massachusetts Institute of Technology (MIT).

  Access and use of this software shall impose the following obligations and
  understandings on the user. The user is granted the right, without any fee
  or cost, to use, copy, modify, alter, enhance and distribute this software,
  and any derivative works thereof, and its supporting documentation for any
  purpose whatsoever, provided that this entire notice appears in all copies
  of the software, derivative works and supporting documentation.  Further,
  the user agrees to credit URI/MIT in any publications that result from the
  use of this software or in any product that includes this software. The
  names URI, MIT and/or GSO, however, may not be used in any advertising or
  publicity to endorse or promote any products or commercial entity unless
  specific written permission is obtained from URI/MIT. The user also
  understands that URI/MIT is not obligated to provide the user with any
  support, consulting, training or assistance of any kind with regard to the
  use, operation and performance of this software nor to provide the user
  with any updates, revisions, new versions or "bug fixes".

  THIS SOFTWARE IS PROVIDED BY URI/MIT "AS IS" AND ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
  EVENT SHALL URI/MIT BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
  DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS
  ACTION, ARISING OUT OF OR IN CONNECTION WITH THE ACCESS, USE OR PERFORMANCE
  OF THIS SOFTWARE.
*/

// Implementation for BaseType.
//
// jhrg 9/6/94

// $Log: BaseType.cc,v $
// Revision 1.19  1995/12/06 21:49:53  jimg
// var(): now returns null for anything that does not define its own version.
// print_decl(): uses `constrained' flag.
//
// Revision 1.18  1995/10/23  23:20:47  jimg
// Added _send_p and _read_p fields (and their accessors) along with the
// virtual mfuncs set_send_p() and set_read_p().
//
// Revision 1.17  1995/08/26  00:31:24  jimg
// Removed code enclosed in #ifdef NEVER #endif.
//
// Revision 1.16  1995/08/23  00:04:45  jimg
// Switched from String representation of data type to Type enum.
// Added type_name() member function so that it is simple to get the string
// representation of a variable's type.
// Changed the name of read_val/store_val to buf2val/val2buf.
//
// Revision 1.15  1995/07/09  21:28:52  jimg
// Added copyright notice.
//
// Revision 1.14  1995/05/10  15:33:54  jimg
// Failed to change `config.h' to `config_dap.h' in these files.
//
// Revision 1.13  1995/05/10  13:45:06  jimg
// Changed the name of the configuration header file from `config.h' to
// `config_dap.h' so that other libraries could have header files which were
// installed in the DODS include directory without overwriting this one. Each
// config header should follow the convention config_<name>.h.
//
// Revision 1.12  1995/03/16  17:26:36  jimg
// Moved include of config_dap.h to top of includes.
// Added TRACE_NEW switched dbnew debugging includes.
//
// Revision 1.11  1995/02/16  22:46:00  jimg
// Added _in private member. It is used to keep a copy of the input FILE *
// so that when the next chunk of data is read in the previous one can be
// closed. Since the netio library unlinks the tmp file before returning
// the FILE *, closing it effectively deletes the tmp file.
//
// Revision 1.10  1995/02/10  02:41:56  jimg
// Added new mfuncs to access _name and _type.
// Made private and protected filed's names start with `_'.
// Added store_val() as a abstract virtual mfunc.
//
// Revision 1.9  1995/01/18  18:33:25  dan
// Added external declarations for utility functions, new_xdrstdio and
// delete_xdrstdio.
//
// Revision 1.8  1995/01/11  16:06:47  jimg
// Added static XDR pointers to BaseType class and removed the XDR pointers
// that were class members - now there is only one xdrin and one xdrout
// for all children of BaseType.
// Added friend functions to help in setting the FILE * associated with
// the XDR *s.
// Removed FILE *in member (but FILE *out was kept as FILE * _out, mfunc
// expunge()).
// Changed ctor so that it no longer takes FILE * params.
//
// Revision 1.7  1994/12/16  22:01:42  jimg
// Added mfuncs var() and add_var() to BaseType. These print an error
// message when called with a simple BaseType (Int32, ...). Classes like
// Array use them and provide their own definitions.
//
// Revision 1.6  1994/11/29  19:59:01  jimg
// Added FILE * input and output buffers. All data set and all data received
// passes through these buffers. This simplifies testing and makes using
// the toolkit with files a little easier.
// Added xdrin and xdrout members (both are XDR *). These are the source and
// sink for xdr data.
// Modified ctor and duplicate() to correctly handle xdrin/out.
// Added expunge() which flushes the output buffer.
//
// Revision 1.5  1994/11/22  14:05:26  jimg
// Added code for data transmission to parts of the type hierarchy. Not
// complete yet.
// Fixed erros in type hierarchy headers (typos, incorrect comments, ...).
//
// Revision 1.4  1994/10/17  23:30:46  jimg
// Added ptr_duplicate virtual mfunc. Child classes can also define this
// to copy parts that BaseType does not have (and allocate correctly sized
// pointers.
// Removed protected mfunc error() -- use errmsg library instead.
// Added formatted printing of types (works with DDS::print()).
//
// Revision 1.3  1994/09/23  14:34:42  jimg
// Added mfunc check_semantics().
// Moved definition of dtor to BaseType.cc.
//
// Revision 1.2  1994/09/15  21:08:36  jimg
// Added many classes to the BaseType hierarchy - the complete set of types
// described in the DODS API design documet is now represented.
// The parser can parse DDS files.
// Fixed many small problems with BaseType.
// Added CtorType.
//
// Revision 1.1  1994/09/09  15:28:41  jimg
// Class for base type variables. Int32, ... inherit from this class.

#ifdef __GNUG__
#pragma implementation
#endif

#include "config_dap.h"

#include <stdio.h>		// for stdin and stdout

#include "BaseType.h"
#include "util.h"

// Initial definition of the protected static members _xdrin and
// _xdrout. By default they use the stdin and stdout streams (resp).

XDR * BaseType::_xdrin = new_xdrstdio(stdin, XDR_DECODE);
XDR * BaseType::_xdrout = new_xdrstdio(stdout, XDR_ENCODE);
FILE * BaseType::_out = stdout;
FILE * BaseType::_in = stdin;

// Private copy mfunc

void
BaseType::_duplicate(const BaseType &bt)
{
    _name = bt._name;
    _type = bt._type;
    _xdr_coder = bt._xdr_coder;	// just copy this function pointer
}

// friend functions

// Delete the current XDR * assigned to _xdrin, free the storage, create a
// new XDR * and assign it to _xdrin.

void
set_xdrin(FILE *in)
{
    delete_xdrstdio(BaseType::_xdrin);
    if (BaseType::_in != stdin)
	fclose(BaseType::_in);
    BaseType::_xdrin = new_xdrstdio(in, XDR_DECODE);
    BaseType::_in = in;
}

// Same as above except do it for _xdrout instead of _xdrin and store the
// OUT in private member _out. _out is used by mfunc expunge().

void
set_xdrout(FILE *out)
{
    delete_xdrstdio(BaseType::_xdrout);
    BaseType::_xdrout = new_xdrstdio(out, XDR_ENCODE);
    BaseType::_out = out;
}

// Public mfuncs

// Note that the ctor (as well as the copy ctor via duplicate)
// open/initialize the (XDRS *)s XDRIN and XDROUT to reference sdtin and
// stdout. This means that writing to std{in,out} must work correctly, and
// probably means that is must be OK to mix calls to cout/cin with calls that
// write to std{out,in} (it is for g++ with libg++ at version 2.6 or
// greater).

BaseType::BaseType(const String &n, const Type &t, xdrproc_t xdr)
    : _name(n), _type(t), _xdr_coder(xdr), _read_p(false), _send_p(false)
{
}

BaseType::BaseType(const BaseType &copy_from)
{
    _duplicate(copy_from);
}

BaseType::~BaseType()
{
}

BaseType &
BaseType::operator=(const BaseType &rhs)
{
    if (this == &rhs)
	return *this;

    _duplicate(rhs);

    return *this;
}

String
BaseType::name() const
{
    return _name;
}

void
BaseType::set_name(const String &n)
{
    _name = n;
}

Type
BaseType::type() const
{
    return _type;
}

void
BaseType::set_type(const Type &t)
{
    _type = t;
}

String
BaseType::type_name() const
{
    switch(_type) {
      case null_t:
	return String("Null");
      case byte_t:
	return String("Byte");
      case int32_t:
	return String("Int32");
      case float64_t:
	return String("Float64");
      case str_t:
	return String("String");
      case url_t:
	return String("Url");
      case array_t:
	return String("Array");
      case list_t:
	return String("List");
      case structure_t:
	return String("Structure");
      case sequence_t:
	return String("Sequence");
      case function_t:
	return String("Function");
      case grid_t:
	return String("Grid");
      default:
	cerr << "BaseType::type_name: Undefined type" << endl;
	return String("");
    }
}

// Return the state of _read_p (true if the value of the variable has been
// read (and is in memory) false otherwise).

bool
BaseType::read_p()
{
    return _read_p;
}

void
BaseType::set_read_p(bool state)
{
    _read_p = state;
}

// Return the state of _send_p (true if the variable should be sent, false
// otherwise).

bool
BaseType::send_p()
{
    return _send_p;
}

void
BaseType::set_send_p(bool state)
{
    _send_p = state;
}

// Defined by constructor types (Array, ...)
//
// Return a pointer to the contained variable in a ctor class.

BaseType *
BaseType::var(const String &name)
{
    return (BaseType *)0;
}

// Defined by constructor types (Array, ...)

void
BaseType::add_var(BaseType *v, Part p)
{
}

// Using this mfunc, objects that contain a (BaseType *) can get the xdr
// function used to serialize the object.

xdrproc_t
BaseType::xdr_coder()
{
    return _xdr_coder;
}

// Use these mfuncs to access the xdrin/out pointers.

XDR *
BaseType::xdrin() const
{
    return _xdrin;
}

XDR *
BaseType::xdrout() const
{
    return _xdrout;
}

// send a printed representation of the variable's declaration to cout. If
// print_semi is true, append a semicolon and newline.

void
BaseType::print_decl(ostream &os, String space, bool print_semi,
		     bool constraint_info, bool constrained)
{
    // if printing the constrained declaration, exit if this variable was not
    // selected.
    if (constrained && !send_p())
	return;

    os << space << type_name() << " " << _name;

    if (constraint_info) {
	if (send_p())
	    cout << ": Send True";
	else
	    cout << ": Send False";
    }

    if (print_semi)
	os << ";" << endl;
}

// Compares the object's current state with the semantics of a particular
// type. This will typically be defined in ctor classes (which have
// complicated semantics). For BaseType, an object is semantically correct if
// it has both a non-null name and type.
//
// NB: This is not the same as an invariant -- during the parse objects exist
// but have no name. Also, the bool ALL defaults to false for BaseType. It is
// used by children of CtorType.
//
// Returns: true if the object is semantically correct, false otherwise.

bool
BaseType::check_semantics(bool all)
{
    bool sem = (_type != null_t && (const char *)_name);

    if (!sem)
	cerr << "Every variable must have both a name and a type" << endl;

    return sem;
}

// Flush the output buffer.
// Returns: false if an error was detected by fflush(), true otherwise.

bool
BaseType::expunge()
{
    return fflush(_out) == 0;
}
<commit_msg>Added ops member function.<commit_after>
/*
  Copyright 1995 The University of Rhode Island and The Massachusetts
  Institute of Technology

  Portions of this software were developed by the Graduate School of
  Oceanography (GSO) at the University of Rhode Island (URI) in collaboration
  with The Massachusetts Institute of Technology (MIT).

  Access and use of this software shall impose the following obligations and
  understandings on the user. The user is granted the right, without any fee
  or cost, to use, copy, modify, alter, enhance and distribute this software,
  and any derivative works thereof, and its supporting documentation for any
  purpose whatsoever, provided that this entire notice appears in all copies
  of the software, derivative works and supporting documentation.  Further,
  the user agrees to credit URI/MIT in any publications that result from the
  use of this software or in any product that includes this software. The
  names URI, MIT and/or GSO, however, may not be used in any advertising or
  publicity to endorse or promote any products or commercial entity unless
  specific written permission is obtained from URI/MIT. The user also
  understands that URI/MIT is not obligated to provide the user with any
  support, consulting, training or assistance of any kind with regard to the
  use, operation and performance of this software nor to provide the user
  with any updates, revisions, new versions or "bug fixes".

  THIS SOFTWARE IS PROVIDED BY URI/MIT "AS IS" AND ANY EXPRESS OR IMPLIED
  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
  EVENT SHALL URI/MIT BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
  DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS
  ACTION, ARISING OUT OF OR IN CONNECTION WITH THE ACCESS, USE OR PERFORMANCE
  OF THIS SOFTWARE.
*/

// Implementation for BaseType.
//
// jhrg 9/6/94

// $Log: BaseType.cc,v $
// Revision 1.20  1996/03/05 18:45:29  jimg
// Added ops member function.
//
// Revision 1.19  1995/12/06  21:49:53  jimg
// var(): now returns null for anything that does not define its own version.
// print_decl(): uses `constrained' flag.
//
// Revision 1.18  1995/10/23  23:20:47  jimg
// Added _send_p and _read_p fields (and their accessors) along with the
// virtual mfuncs set_send_p() and set_read_p().
//
// Revision 1.17  1995/08/26  00:31:24  jimg
// Removed code enclosed in #ifdef NEVER #endif.
//
// Revision 1.16  1995/08/23  00:04:45  jimg
// Switched from String representation of data type to Type enum.
// Added type_name() member function so that it is simple to get the string
// representation of a variable's type.
// Changed the name of read_val/store_val to buf2val/val2buf.
//
// Revision 1.15  1995/07/09  21:28:52  jimg
// Added copyright notice.
//
// Revision 1.14  1995/05/10  15:33:54  jimg
// Failed to change `config.h' to `config_dap.h' in these files.
//
// Revision 1.13  1995/05/10  13:45:06  jimg
// Changed the name of the configuration header file from `config.h' to
// `config_dap.h' so that other libraries could have header files which were
// installed in the DODS include directory without overwriting this one. Each
// config header should follow the convention config_<name>.h.
//
// Revision 1.12  1995/03/16  17:26:36  jimg
// Moved include of config_dap.h to top of includes.
// Added TRACE_NEW switched dbnew debugging includes.
//
// Revision 1.11  1995/02/16  22:46:00  jimg
// Added _in private member. It is used to keep a copy of the input FILE *
// so that when the next chunk of data is read in the previous one can be
// closed. Since the netio library unlinks the tmp file before returning
// the FILE *, closing it effectively deletes the tmp file.
//
// Revision 1.10  1995/02/10  02:41:56  jimg
// Added new mfuncs to access _name and _type.
// Made private and protected filed's names start with `_'.
// Added store_val() as a abstract virtual mfunc.
//
// Revision 1.9  1995/01/18  18:33:25  dan
// Added external declarations for utility functions, new_xdrstdio and
// delete_xdrstdio.
//
// Revision 1.8  1995/01/11  16:06:47  jimg
// Added static XDR pointers to BaseType class and removed the XDR pointers
// that were class members - now there is only one xdrin and one xdrout
// for all children of BaseType.
// Added friend functions to help in setting the FILE * associated with
// the XDR *s.
// Removed FILE *in member (but FILE *out was kept as FILE * _out, mfunc
// expunge()).
// Changed ctor so that it no longer takes FILE * params.
//
// Revision 1.7  1994/12/16  22:01:42  jimg
// Added mfuncs var() and add_var() to BaseType. These print an error
// message when called with a simple BaseType (Int32, ...). Classes like
// Array use them and provide their own definitions.
//
// Revision 1.6  1994/11/29  19:59:01  jimg
// Added FILE * input and output buffers. All data set and all data received
// passes through these buffers. This simplifies testing and makes using
// the toolkit with files a little easier.
// Added xdrin and xdrout members (both are XDR *). These are the source and
// sink for xdr data.
// Modified ctor and duplicate() to correctly handle xdrin/out.
// Added expunge() which flushes the output buffer.
//
// Revision 1.5  1994/11/22  14:05:26  jimg
// Added code for data transmission to parts of the type hierarchy. Not
// complete yet.
// Fixed erros in type hierarchy headers (typos, incorrect comments, ...).
//
// Revision 1.4  1994/10/17  23:30:46  jimg
// Added ptr_duplicate virtual mfunc. Child classes can also define this
// to copy parts that BaseType does not have (and allocate correctly sized
// pointers.
// Removed protected mfunc error() -- use errmsg library instead.
// Added formatted printing of types (works with DDS::print()).
//
// Revision 1.3  1994/09/23  14:34:42  jimg
// Added mfunc check_semantics().
// Moved definition of dtor to BaseType.cc.
//
// Revision 1.2  1994/09/15  21:08:36  jimg
// Added many classes to the BaseType hierarchy - the complete set of types
// described in the DODS API design documet is now represented.
// The parser can parse DDS files.
// Fixed many small problems with BaseType.
// Added CtorType.
//
// Revision 1.1  1994/09/09  15:28:41  jimg
// Class for base type variables. Int32, ... inherit from this class.

#ifdef __GNUG__
#pragma implementation
#endif

#include "config_dap.h"

#include <stdio.h>		// for stdin and stdout

#include "BaseType.h"
#include "util.h"

// Initial definition of the protected static members _xdrin and
// _xdrout. By default they use the stdin and stdout streams (resp).

XDR * BaseType::_xdrin = new_xdrstdio(stdin, XDR_DECODE);
XDR * BaseType::_xdrout = new_xdrstdio(stdout, XDR_ENCODE);
FILE * BaseType::_out = stdout;
FILE * BaseType::_in = stdin;

// Private copy mfunc

void
BaseType::_duplicate(const BaseType &bt)
{
    _name = bt._name;
    _type = bt._type;
    _xdr_coder = bt._xdr_coder;	// just copy this function pointer
}

// friend functions

// Delete the current XDR * assigned to _xdrin, free the storage, create a
// new XDR * and assign it to _xdrin.

void
set_xdrin(FILE *in)
{
    delete_xdrstdio(BaseType::_xdrin);
    if (BaseType::_in != stdin)
	fclose(BaseType::_in);
    BaseType::_xdrin = new_xdrstdio(in, XDR_DECODE);
    BaseType::_in = in;
}

// Same as above except do it for _xdrout instead of _xdrin and store the
// OUT in private member _out. _out is used by mfunc expunge().

void
set_xdrout(FILE *out)
{
    delete_xdrstdio(BaseType::_xdrout);
    BaseType::_xdrout = new_xdrstdio(out, XDR_ENCODE);
    BaseType::_out = out;
}

// Public mfuncs

// Note that the ctor (as well as the copy ctor via duplicate)
// open/initialize the (XDRS *)s XDRIN and XDROUT to reference sdtin and
// stdout. This means that writing to std{in,out} must work correctly, and
// probably means that is must be OK to mix calls to cout/cin with calls that
// write to std{out,in} (it is for g++ with libg++ at version 2.6 or
// greater).

BaseType::BaseType(const String &n, const Type &t, xdrproc_t xdr)
    : _name(n), _type(t), _xdr_coder(xdr), _read_p(false), _send_p(false)
{
}

BaseType::BaseType(const BaseType &copy_from)
{
    _duplicate(copy_from);
}

BaseType::~BaseType()
{
}

BaseType &
BaseType::operator=(const BaseType &rhs)
{
    if (this == &rhs)
	return *this;

    _duplicate(rhs);

    return *this;
}

String
BaseType::name() const
{
    return _name;
}

void
BaseType::set_name(const String &n)
{
    _name = n;
}

Type
BaseType::type() const
{
    return _type;
}

void
BaseType::set_type(const Type &t)
{
    _type = t;
}

String
BaseType::type_name() const
{
    switch(_type) {
      case null_t:
	return String("Null");
      case byte_t:
	return String("Byte");
      case int32_t:
	return String("Int32");
      case float64_t:
	return String("Float64");
      case str_t:
	return String("String");
      case url_t:
	return String("Url");
      case array_t:
	return String("Array");
      case list_t:
	return String("List");
      case structure_t:
	return String("Structure");
      case sequence_t:
	return String("Sequence");
      case function_t:
	return String("Function");
      case grid_t:
	return String("Grid");
      default:
	cerr << "BaseType::type_name: Undefined type" << endl;
	return String("");
    }
}

// Return the state of _read_p (true if the value of the variable has been
// read (and is in memory) false otherwise).

bool
BaseType::read_p()
{
    return _read_p;
}

void
BaseType::set_read_p(bool state)
{
    _read_p = state;
}

// Return the state of _send_p (true if the variable should be sent, false
// otherwise).

bool
BaseType::send_p()
{
    return _send_p;
}

void
BaseType::set_send_p(bool state)
{
    _send_p = state;
}

// Defined by constructor types (Array, ...)
//
// Return a pointer to the contained variable in a ctor class.

BaseType *
BaseType::var(const String &name)
{
    return (BaseType *)0;
}

// Defined by constructor types (Array, ...)

void
BaseType::add_var(BaseType *v, Part p)
{
}

// Using this mfunc, objects that contain a (BaseType *) can get the xdr
// function used to serialize the object.

xdrproc_t
BaseType::xdr_coder()
{
    return _xdr_coder;
}

// Use these mfuncs to access the xdrin/out pointers.

XDR *
BaseType::xdrin() const
{
    return _xdrin;
}

XDR *
BaseType::xdrout() const
{
    return _xdrout;
}

// send a printed representation of the variable's declaration to cout. If
// print_semi is true, append a semicolon and newline.

void
BaseType::print_decl(ostream &os, String space, bool print_semi,
		     bool constraint_info, bool constrained)
{
    // if printing the constrained declaration, exit if this variable was not
    // selected.
    if (constrained && !send_p())
	return;

    os << space << type_name() << " " << _name;

    if (constraint_info) {
	if (send_p())
	    cout << ": Send True";
	else
	    cout << ": Send False";
    }

    if (print_semi)
	os << ";" << endl;
}

// Compares the object's current state with the semantics of a particular
// type. This will typically be defined in ctor classes (which have
// complicated semantics). For BaseType, an object is semantically correct if
// it has both a non-null name and type.
//
// NB: This is not the same as an invariant -- during the parse objects exist
// but have no name. Also, the bool ALL defaults to false for BaseType. It is
// used by children of CtorType.
//
// Returns: true if the object is semantically correct, false otherwise.

bool
BaseType::check_semantics(bool all)
{
    bool sem = (_type != null_t && (const char *)_name);

    if (!sem)
	cerr << "Every variable must have both a name and a type" << endl;

    return sem;
}

// Flush the output buffer.
// Returns: false if an error was detected by fflush(), true otherwise.

bool
BaseType::expunge()
{
    return fflush(_out) == 0;
}

// Member functions for the relational operators used in evaluating a
// relational clause in a constraint expression. Each class that wants these
// to do something interesting must supply their own versions. These print en
// error message and return False.

bool
BaseType::ops(BaseType &b, int op)
{
    cerr << "Unimplemented operator" << endl;

    return false;
}

<|endoftext|>


<commit_before>
// g++-4.2 -O3 -DNDEBUG -I.. benchBlasGemm.cpp /usr/lib/libcblas.so.3 - o benchBlasGemm
// possible options:
//    -DEIGEN_DONT_VECTORIZE
//    -msse2

// #define EIGEN_DEFAULT_TO_ROW_MAJOR
#define _FLOAT

#include <Eigen/Array>
#include <Eigen/Core>
#include "BenchTimer.h"

// include the BLAS headers
#include <cblas.h>
#include <string>

#ifdef _FLOAT
typedef float Scalar;
#define CBLAS_GEMM cblas_sgemm
#else
typedef double Scalar;
#define CBLAS_GEMM cblas_dgemm
#endif

typedef Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> MyMatrix;
void bench_eigengemm(MyMatrix& mc, const MyMatrix& ma, const MyMatrix& mb, int nbloops);
void bench_eigengemm_normal(MyMatrix& mc, const MyMatrix& ma, const MyMatrix& mb, int nbloops);
void check_product(int M, int N, int K);
void check_product(void);

int main(int argc, char *argv[])
{
  // disable SSE exceptions
  #ifdef __GNUC__
  {
    int aux;
    asm(
    "stmxcsr   %[aux]           \n\t"
    "orl       $32832, %[aux]   \n\t"
    "ldmxcsr   %[aux]           \n\t"
    : : [aux] "m" (aux));
  }
  #endif

  int nbtries=1, nbloops=1, M, N, K;

  if (argc==2)
  {
    if (std::string(argv[1])=="check")
      check_product();
    else
      M = N = K = atoi(argv[1]);
  }
  else if ((argc==3) && (std::string(argv[1])=="auto"))
  {
    M = N = K = atoi(argv[2]);
    nbloops = 1000000000/(M*M*M);
    if (nbloops<1)
      nbloops = 1;
    nbtries = 6;
  }
  else if (argc==4)
  {
    M = N = K = atoi(argv[1]);
    nbloops = atoi(argv[2]);
    nbtries = atoi(argv[3]);
  }
  else if (argc==6)
  {
    M = atoi(argv[1]);
    N = atoi(argv[2]);
    K = atoi(argv[3]);
    nbloops = atoi(argv[4]);
    nbtries = atoi(argv[5]);
  }
  else
  {
    std::cout << "Usage: " << argv[0] << " size  \n";
    std::cout << "Usage: " << argv[0] << " auto size\n";
    std::cout << "Usage: " << argv[0] << " size nbloops nbtries\n";
    std::cout << "Usage: " << argv[0] << " M N K nbloops nbtries\n";
    std::cout << "Usage: " << argv[0] << " check\n";
    std::cout << "Options:\n";
    std::cout << "    size       unique size of the 2 matrices (integer)\n";
    std::cout << "    auto       automatically set the number of repetitions and tries\n";
    std::cout << "    nbloops    number of times the GEMM routines is executed\n";
    std::cout << "    nbtries    number of times the loop is benched (return the best try)\n";
    std::cout << "    M N K      sizes of the matrices: MxN  =  MxK * KxN (integers)\n";
    std::cout << "    check      check eigen product using cblas as a reference\n";
    exit(1);
  }

  double nbmad = double(M) * double(N) * double(K) * double(nbloops);

  if (!(std::string(argv[1])=="auto"))
    std::cout << M << " x " << N << " x " << K << "\n";

  Scalar alpha, beta;
  MyMatrix ma(M,K), mb(K,N), mc(M,N);
  ma = MyMatrix::Random(M,K);
  mb = MyMatrix::Random(K,N);
  mc = MyMatrix::Random(M,N);

  Eigen::BenchTimer timer;

  // we simply compute c += a*b, so:
  alpha = 1;
  beta = 1;

  // bench cblas
  // ROWS_A, COLS_B, COLS_A, 1.0,  A, COLS_A, B, COLS_B, 0.0, C, COLS_B);
  if (!(std::string(argv[1])=="auto"))
  {
    timer.reset();
    for (uint k=0 ; k<nbtries ; ++k)
    {
        timer.start();
        for (uint j=0 ; j<nbloops ; ++j)
              #ifdef EIGEN_DEFAULT_TO_ROW_MAJOR
              CBLAS_GEMM(CblasRowMajor, CblasNoTrans, CblasNoTrans, M, N, K, alpha, ma.data(), K, mb.data(), N, beta, mc.data(), N);
              #else
              CBLAS_GEMM(CblasColMajor, CblasNoTrans, CblasNoTrans, M, N, K, alpha, ma.data(), M, mb.data(), K, beta, mc.data(), M);
              #endif
        timer.stop();
    }
    if (!(std::string(argv[1])=="auto"))
      std::cout << "cblas: " << timer.value() << " (" << 1e-3*floor(1e-6*nbmad/timer.value()) << " GFlops/s)\n";
    else
        std::cout << M << " : " << timer.value() << " ; " << 1e-3*floor(1e-6*nbmad/timer.value()) << "\n";
  }

  // clear
  ma = MyMatrix::Random(M,K);
  mb = MyMatrix::Random(K,N);
  mc = MyMatrix::Random(M,N);

  // eigen
//   if (!(std::string(argv[1])=="auto"))
  {
      timer.reset();
      for (uint k=0 ; k<nbtries ; ++k)
      {
          timer.start();
          bench_eigengemm(mc, ma, mb, nbloops);
          timer.stop();
      }
      if (!(std::string(argv[1])=="auto"))
        std::cout << "eigen : " << timer.value() << " (" << 1e-3*floor(1e-6*nbmad/timer.value()) << " GFlops/s)\n";
      else
        std::cout << M << " : " << timer.value() << " ; " << 1e-3*floor(1e-6*nbmad/timer.value()) << "\n";
  }

  // clear
  ma = MyMatrix::Random(M,K);
  mb = MyMatrix::Random(K,N);
  mc = MyMatrix::Random(M,N);

  // eigen normal
  if (!(std::string(argv[1])=="auto"))
  {
      timer.reset();
      for (uint k=0 ; k<nbtries ; ++k)
      {
          timer.start();
          bench_eigengemm_normal(mc, ma, mb, nbloops);
          timer.stop();
      }
      std::cout << "eigen : " << timer.value() << " (" << 1e-3*floor(1e-6*nbmad/timer.value()) << " GFlops/s)\n";
  }

  return 0;
}

using namespace Eigen;

void bench_eigengemm(MyMatrix& mc, const MyMatrix& ma, const MyMatrix& mb, int nbloops)
{
  for (uint j=0 ; j<nbloops ; ++j)
      mc += (ma * mb).lazy();
}

void bench_eigengemm_normal(MyMatrix& mc, const MyMatrix& ma, const MyMatrix& mb, int nbloops)
{
  for (uint j=0 ; j<nbloops ; ++j)
    mc += Product<MyMatrix,MyMatrix,NormalProduct>(ma,mb).lazy();
}

#define MYVERIFY(A,M) if (!(A)) { \
    std::cout << "FAIL: " << M << "\n"; \
  }
void check_product(int M, int N, int K)
{
  MyMatrix ma(M,K), mb(K,N), mc(M,N), maT(K,M), mbT(N,K), meigen(M,N), mref(M,N);
  ma = MyMatrix::Random(M,K);
  mb = MyMatrix::Random(K,N);
  maT = ma.transpose();
  mbT = mb.transpose();
  mc = MyMatrix::Random(M,N);

  MyMatrix::Scalar eps = 1e-4;

  meigen = mref = mc;
  CBLAS_GEMM(CblasColMajor, CblasNoTrans, CblasNoTrans, M, N, K, 1, ma.data(), M, mb.data(), K, 1, mref.data(), M);
  meigen += ma * mb;
  MYVERIFY(meigen.isApprox(mref, eps),". * .");

  meigen = mref = mc;
  CBLAS_GEMM(CblasColMajor, CblasTrans, CblasNoTrans, M, N, K, 1, maT.data(), K, mb.data(), K, 1, mref.data(), M);
  meigen += maT.transpose() * mb;
  MYVERIFY(meigen.isApprox(mref, eps),"T * .");

  meigen = mref = mc;
  CBLAS_GEMM(CblasColMajor, CblasTrans, CblasTrans, M, N, K, 1, maT.data(), K, mbT.data(), N, 1, mref.data(), M);
  meigen += (maT.transpose()) * (mbT.transpose());
  MYVERIFY(meigen.isApprox(mref, eps),"T * T");

  meigen = mref = mc;
  CBLAS_GEMM(CblasColMajor, CblasNoTrans, CblasTrans, M, N, K, 1, ma.data(), M, mbT.data(), N, 1, mref.data(), M);
  meigen += ma * mbT.transpose();
  MYVERIFY(meigen.isApprox(mref, eps),". * T");
}

void check_product(void)
{
  int M, N, K;
  for (uint i=0; i<1000; ++i)
  {
    M = ei_random<int>(1,64);
    N = ei_random<int>(1,768);
    K = ei_random<int>(1,768);
    M = (0 + M) * 1;
    std::cout << M << " x " << N << " x " << K << "\n";
    check_product(M, N, K);
  }
}

<commit_msg>update product bench<commit_after>
// g++-4.2 -O3 -DNDEBUG -I.. benchBlasGemm.cpp /usr/lib/libcblas.so.3 - o benchBlasGemm
// possible options:
//    -DEIGEN_DONT_VECTORIZE
//    -msse2

// #define EIGEN_DEFAULT_TO_ROW_MAJOR
#define _FLOAT

#include <Eigen/Array>
#include <Eigen/Core>
#include "BenchTimer.h"

// include the BLAS headers
#include <cblas.h>
#include <string>

#ifdef _FLOAT
typedef float Scalar;
#define CBLAS_GEMM cblas_sgemm
#else
typedef double Scalar;
#define CBLAS_GEMM cblas_dgemm
#endif

typedef Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> MyMatrix;
void bench_eigengemm(MyMatrix& mc, const MyMatrix& ma, const MyMatrix& mb, int nbloops);
void bench_eigengemm_normal(MyMatrix& mc, const MyMatrix& ma, const MyMatrix& mb, int nbloops);
void check_product(int M, int N, int K);
void check_product(void);

int main(int argc, char *argv[])
{
  // disable SSE exceptions
  #ifdef __GNUC__
  {
    int aux;
    asm(
    "stmxcsr   %[aux]           \n\t"
    "orl       $32832, %[aux]   \n\t"
    "ldmxcsr   %[aux]           \n\t"
    : : [aux] "m" (aux));
  }
  #endif

  int nbtries=1, nbloops=1, M, N, K;

  if (argc==2)
  {
    if (std::string(argv[1])=="check")
      check_product();
    else
      M = N = K = atoi(argv[1]);
  }
  else if ((argc==3) && (std::string(argv[1])=="auto"))
  {
    M = N = K = atoi(argv[2]);
    nbloops = 1000000000/(M*M*M);
    if (nbloops<1)
      nbloops = 1;
    nbtries = 6;
  }
  else if (argc==4)
  {
    M = N = K = atoi(argv[1]);
    nbloops = atoi(argv[2]);
    nbtries = atoi(argv[3]);
  }
  else if (argc==6)
  {
    M = atoi(argv[1]);
    N = atoi(argv[2]);
    K = atoi(argv[3]);
    nbloops = atoi(argv[4]);
    nbtries = atoi(argv[5]);
  }
  else
  {
    std::cout << "Usage: " << argv[0] << " size  \n";
    std::cout << "Usage: " << argv[0] << " auto size\n";
    std::cout << "Usage: " << argv[0] << " size nbloops nbtries\n";
    std::cout << "Usage: " << argv[0] << " M N K nbloops nbtries\n";
    std::cout << "Usage: " << argv[0] << " check\n";
    std::cout << "Options:\n";
    std::cout << "    size       unique size of the 2 matrices (integer)\n";
    std::cout << "    auto       automatically set the number of repetitions and tries\n";
    std::cout << "    nbloops    number of times the GEMM routines is executed\n";
    std::cout << "    nbtries    number of times the loop is benched (return the best try)\n";
    std::cout << "    M N K      sizes of the matrices: MxN  =  MxK * KxN (integers)\n";
    std::cout << "    check      check eigen product using cblas as a reference\n";
    exit(1);
  }

  double nbmad = double(M) * double(N) * double(K) * double(nbloops);

  if (!(std::string(argv[1])=="auto"))
    std::cout << M << " x " << N << " x " << K << "\n";

  Scalar alpha, beta;
  MyMatrix ma(M,K), mb(K,N), mc(M,N);
  ma = MyMatrix::Random(M,K);
  mb = MyMatrix::Random(K,N);
  mc = MyMatrix::Random(M,N);

  Eigen::BenchTimer timer;

  // we simply compute c += a*b, so:
  alpha = 1;
  beta = 1;

  // bench cblas
  // ROWS_A, COLS_B, COLS_A, 1.0,  A, COLS_A, B, COLS_B, 0.0, C, COLS_B);
  if (!(std::string(argv[1])=="auto"))
  {
    timer.reset();
    for (uint k=0 ; k<nbtries ; ++k)
    {
        timer.start();
        for (uint j=0 ; j<nbloops ; ++j)
              #ifdef EIGEN_DEFAULT_TO_ROW_MAJOR
              CBLAS_GEMM(CblasRowMajor, CblasNoTrans, CblasNoTrans, M, N, K, alpha, ma.data(), K, mb.data(), N, beta, mc.data(), N);
              #else
              CBLAS_GEMM(CblasColMajor, CblasNoTrans, CblasNoTrans, M, N, K, alpha, ma.data(), M, mb.data(), K, beta, mc.data(), M);
              #endif
        timer.stop();
    }
    if (!(std::string(argv[1])=="auto"))
      std::cout << "cblas: " << timer.value() << " (" << 1e-3*floor(1e-6*nbmad/timer.value()) << " GFlops/s)\n";
    else
        std::cout << M << " : " << timer.value() << " ; " << 1e-3*floor(1e-6*nbmad/timer.value()) << "\n";
  }

  // clear
  ma = MyMatrix::Random(M,K);
  mb = MyMatrix::Random(K,N);
  mc = MyMatrix::Random(M,N);

  // eigen
//   if (!(std::string(argv[1])=="auto"))
  {
      timer.reset();
      for (uint k=0 ; k<nbtries ; ++k)
      {
          timer.start();
          bench_eigengemm(mc, ma, mb, nbloops);
          timer.stop();
      }
      if (!(std::string(argv[1])=="auto"))
        std::cout << "eigen : " << timer.value() << " (" << 1e-3*floor(1e-6*nbmad/timer.value()) << " GFlops/s)\n";
      else
        std::cout << M << " : " << timer.value() << " ; " << 1e-3*floor(1e-6*nbmad/timer.value()) << "\n";
  }

  // clear
  ma = MyMatrix::Random(M,K);
  mb = MyMatrix::Random(K,N);
  mc = MyMatrix::Random(M,N);

  // eigen normal
  if (!(std::string(argv[1])=="auto"))
  {
      timer.reset();
      for (uint k=0 ; k<nbtries ; ++k)
      {
          timer.start();
          bench_eigengemm_normal(mc, ma, mb, nbloops);
          timer.stop();
      }
      std::cout << "eigen : " << timer.value() << " (" << 1e-3*floor(1e-6*nbmad/timer.value()) << " GFlops/s)\n";
  }

  return 0;
}

using namespace Eigen;

void bench_eigengemm(MyMatrix& mc, const MyMatrix& ma, const MyMatrix& mb, int nbloops)
{
  for (uint j=0 ; j<nbloops ; ++j)
      mc.noalias() += ma * mb;
}

void bench_eigengemm_normal(MyMatrix& mc, const MyMatrix& ma, const MyMatrix& mb, int nbloops)
{
  for (uint j=0 ; j<nbloops ; ++j)
    mc.noalias() += GeneralProduct<MyMatrix,MyMatrix,UnrolledProduct>(ma,mb);
}

#define MYVERIFY(A,M) if (!(A)) { \
    std::cout << "FAIL: " << M << "\n"; \
  }
void check_product(int M, int N, int K)
{
  MyMatrix ma(M,K), mb(K,N), mc(M,N), maT(K,M), mbT(N,K), meigen(M,N), mref(M,N);
  ma = MyMatrix::Random(M,K);
  mb = MyMatrix::Random(K,N);
  maT = ma.transpose();
  mbT = mb.transpose();
  mc = MyMatrix::Random(M,N);

  MyMatrix::Scalar eps = 1e-4;

  meigen = mref = mc;
  CBLAS_GEMM(CblasColMajor, CblasNoTrans, CblasNoTrans, M, N, K, 1, ma.data(), M, mb.data(), K, 1, mref.data(), M);
  meigen += ma * mb;
  MYVERIFY(meigen.isApprox(mref, eps),". * .");

  meigen = mref = mc;
  CBLAS_GEMM(CblasColMajor, CblasTrans, CblasNoTrans, M, N, K, 1, maT.data(), K, mb.data(), K, 1, mref.data(), M);
  meigen += maT.transpose() * mb;
  MYVERIFY(meigen.isApprox(mref, eps),"T * .");

  meigen = mref = mc;
  CBLAS_GEMM(CblasColMajor, CblasTrans, CblasTrans, M, N, K, 1, maT.data(), K, mbT.data(), N, 1, mref.data(), M);
  meigen += (maT.transpose()) * (mbT.transpose());
  MYVERIFY(meigen.isApprox(mref, eps),"T * T");

  meigen = mref = mc;
  CBLAS_GEMM(CblasColMajor, CblasNoTrans, CblasTrans, M, N, K, 1, ma.data(), M, mbT.data(), N, 1, mref.data(), M);
  meigen += ma * mbT.transpose();
  MYVERIFY(meigen.isApprox(mref, eps),". * T");
}

void check_product(void)
{
  int M, N, K;
  for (uint i=0; i<1000; ++i)
  {
    M = ei_random<int>(1,64);
    N = ei_random<int>(1,768);
    K = ei_random<int>(1,768);
    M = (0 + M) * 1;
    std::cout << M << " x " << N << " x " << K << "\n";
    check_product(M, N, K);
  }
}

<|endoftext|>


<commit_before>#include "Sorter.h"

using namespace sf1r;

const char SortPropertyCache::Separator[] = {'-', '~', ','};

SortProperty::SortProperty(const SortProperty& src)
    : property_(src.property_)
    , propertyDataType_(src.propertyDataType_)
    , type_(src.type_)
    , reverse_(src.reverse_)
    , pComparator_(src.pComparator_)
{
}

SortProperty::SortProperty(const string& property, PropertyDataType propertyType, bool reverse)
    : property_(property)
    , propertyDataType_(propertyType)
    , type_(AUTO)
    , reverse_(reverse)
    , pComparator_(NULL)
{
}

SortProperty::SortProperty(const string& property, PropertyDataType propertyType, SortPropertyType type, bool reverse)
    : property_(property)
    , propertyDataType_(propertyType)
    , type_(type)
    , reverse_(reverse)
    , pComparator_(NULL)
{
}
SortProperty::SortProperty(const string& property, PropertyDataType propertyType, SortPropertyComparator* pComparator, bool reverse)
    : property_(property)
    , propertyDataType_(propertyType)
    , type_(CUSTOM)
    , reverse_(reverse)
    , pComparator_(pComparator)
{
}

SortProperty::SortProperty(const string& property, PropertyDataType propertyType, SortPropertyComparator* pComparator, SortPropertyType type, bool reverse)
    : property_(property)
    , propertyDataType_(propertyType)
    , type_(type)
    , reverse_(reverse)
    , pComparator_(pComparator)
{
}

SortProperty::~SortProperty()
{
    if (pComparator_)
        delete pComparator_;
}

SortPropertyCache::SortPropertyCache(IndexManager* pIndexer, IndexBundleConfiguration* config)
    : pIndexer_(pIndexer)
    , pCTRManager_(NULL)
    , updateInterval_(config->sortCacheUpdateInterval_)
    , dirty_(true)
    , config_(config)
{
    std::cout << "SortPropertyCache::updateInterval_ = " << updateInterval_ << std::endl;
}

void SortPropertyCache::setCtrManager(faceted::CTRManager* pCTRManager)
{
    pCTRManager_ = pCTRManager;
}

void SortPropertyCache::loadSortData(const std::string& property, PropertyDataType type)
{
    void* data = NULL;
    size_t size = 0;
    switch (type)
    {
    case INT_PROPERTY_TYPE:
        pIndexer_->loadPropertyDataForSorting(property, (int64_t*&)data, size);
        break;

    case UNSIGNED_INT_PROPERTY_TYPE:
        pIndexer_->loadPropertyDataForSorting(property, (uint64_t*&)data, size);
        break;

    case FLOAT_PROPERTY_TYPE:
        pIndexer_->loadPropertyDataForSorting(property, (float*&)data, size);
        break;

    case DOUBLE_PROPERTY_TYPE:
        pIndexer_->loadPropertyDataForSorting(property, (double*&)data, size);
        break;

    case STRING_PROPERTY_TYPE:
        pIndexer_->convertStringPropertyDataForSorting(property, (uint32_t*&)data, size);
        break;

    default:
        break;
    }

    if (data)
        sortDataCache_[property].reset(new PropertyData(type, data, size));
    else
        sortDataCache_[property].reset();
}

boost::shared_ptr<PropertyData> SortPropertyCache::getSortPropertyData(const std::string& propertyName, PropertyDataType propertyType)
{
    boost::mutex::scoped_lock lock(this->mutex_);
    if (dirty_)
    {
        for (SortDataCache::iterator iter = sortDataCache_.begin();
            iter != sortDataCache_.end(); ++iter)
        {
            LOG(INFO) << "dirty sort data cache on property: " << iter->first;
            if (iter->second) loadSortData(iter->first, iter->second->type_);
        }
        dirty_ = false;
    }

    SortDataCache::iterator iter = sortDataCache_.find(propertyName) ;
    if (iter == sortDataCache_.end() || !iter->second)
    {
        LOG(INFO) << "first load sort data cache on property: " << propertyName;
        loadSortData(propertyName, propertyType);
    }

    return sortDataCache_[propertyName];
}

boost::shared_ptr<PropertyData> SortPropertyCache::getCTRPropertyData(const std::string& propertyName, PropertyDataType propertyType)
{
    boost::mutex::scoped_lock lock(this->mutex_);

    bool updateCache = false;

    SortDataCache::iterator iter = sortDataCache_.find(propertyName) ;
    if (iter == sortDataCache_.end())
    {
        LOG(INFO) << "first load sort data cache on property: " << propertyName;
        updateCache = true;
    }
    else if (!(iter->second) ||(iter->second->elapsedFromLastLoad() > updateInterval_))
    {
        //LOG(INFO) << "Refresh sort data cache for property: " << propertyName
        //          << " after "<<iter->second->elapsedFromLastLoad()<<" seconds";
        updateCache = true;
    }

    if (updateCache)
    {
        void* data = NULL;
        size_t size = 0;
        pCTRManager_->loadCtrDataInt64((uint64_t*&)data,size);

        if (data)
        {
            sortDataCache_[propertyName].reset(new PropertyData(propertyType, data,size));
        }
        else
        {
            sortDataCache_[propertyName].reset();
        }
    }

    return sortDataCache_[propertyName];
}

bool SortPropertyCache::split_int(const izenelib::util::UString& szText, int64_t& out, izenelib::util::UString::EncodingType encoding, char Separator)
{
    izenelib::util::UString str(szText);
    izenelib::util::UString sep(" ",encoding);
    sep[0] = Separator;
    size_t n = 0;

    n = str.find(sep, 0);
    if (n != izenelib::util::UString::npos)
    {
        if (n != 0)
        {
            try
            {
                izenelib::util::UString tmpStr = str.substr(0, n);
                trim( tmpStr );
                out = boost::lexical_cast< int64_t >( tmpStr );
                return true;
            }
            catch( const boost::bad_lexical_cast & )
            {
                return false;
            }
        }
    }
    return false;
}

bool SortPropertyCache::split_float(const izenelib::util::UString& szText, float& out, izenelib::util::UString::EncodingType encoding, char Separator)
{
    izenelib::util::UString str(szText);
    izenelib::util::UString sep(" ",encoding);
    sep[0] = Separator;
    size_t n = 0;

    n = str.find(sep, 0);
    if (n != izenelib::util::UString::npos)
    {
        if (n != 0)
        {
            try
            {
                izenelib::util::UString tmpStr = str.substr(0, n);
                trim( tmpStr );
                out = boost::lexical_cast< float >( tmpStr );
                return true;
            }
            catch( const boost::bad_lexical_cast & )
            {
                return false;
            }
        }
    }
    return false;
}

void SortPropertyCache::updateSortData(docid_t id, const std::map<std::string, pair<PropertyDataType, izenelib::util::UString> >& rTypeFieldValue)
{
    boost::mutex::scoped_lock lock(this->mutex_);

    izenelib::util::UString::EncodingType encoding = config_->encoding_;
    std::map<std::string, pair<PropertyDataType, izenelib::util::UString> >::const_iterator iter;
    SortDataCache::const_iterator it;
    for (iter = rTypeFieldValue.begin(); iter != rTypeFieldValue.end(); iter++)
    {
        string propertyName = iter->first;
        PropertyDataType dataType = iter->second.first;
        switch(dataType)
        {
        case INT_PROPERTY_TYPE:
            {
                std::string str("");
                iter->second.second.convertString(str, encoding);
                int64_t value = 0;
                try
                {
                    value = boost::lexical_cast< int64_t >( iter->second.second );
                }
                catch( const boost::bad_lexical_cast & )
                {
                    for (int i = 0; i < EoC; i++)
                        if (split_int(iter->second.second, value, encoding, Separator[i]))
                            break;
                    if (value == 0)
                    {
                        LOG(ERROR) << "Wrong format of number value. value:"<<str;
                        break;
                    }
                }
                if ((it = sortDataCache_.find(propertyName)) != sortDataCache_.end())
                {
                    if (!it->second ||id >= it->second->size_)
                        continue;

                    int64_t* data = (int64_t*)(it->second->data_);
                    data[id] = value;
                }
            }
            break;
        case FLOAT_PROPERTY_TYPE:
            {
                std::string str("");
                iter->second.second.convertString(str, encoding);
                float value = 0.0;
                try
                {
                    value = boost::lexical_cast< float >( iter->second.second );
                }
                catch( const boost::bad_lexical_cast & )
                {
                    for (int i = 0; i < EoC; i++)
                        if (split_float(iter->second.second, value, encoding, Separator[i]))
                            break;
                    if (value == 0.0)
                    {
                        LOG(ERROR) << "Wrong format of number value. value:"<<str;
                        break;
                    }
                }
                if ((it = sortDataCache_.find(propertyName)) != sortDataCache_.end())
                {
                    if (!it->second ||id >= it->second->size_)
                        continue;

                    float* data = (float*)(it->second->data_);
                    data[id] = value;
                }
            }
            break;
        default:
            break;
        }
    }
}

SortPropertyComparator* SortPropertyCache::getComparator(SortProperty* pSortProperty)
{
    SortProperty::SortPropertyType propSortType = pSortProperty->getType();
    const std::string& propName = pSortProperty->getProperty();
    const PropertyDataType propDataType = pSortProperty->getPropertyDataType();

    boost::shared_ptr<PropertyData> propData;
    if (propSortType == SortProperty::AUTO)
    {
        propData = getSortPropertyData(propName, propDataType);
    }
    else if (propSortType == SortProperty::CTR)
    {
        if (pCTRManager_)
            propData = getCTRPropertyData(propName, propDataType);
    }
    else
    {
        // to extend
    }

    if (propData)
        return new SortPropertyComparator(propData);
    else
        return NULL;
}

Sorter::Sorter(SortPropertyCache* pCache)
    : pCache_(pCache)
    , ppSortProperties_(0)
    , reverseMul_(0)
{
}

Sorter::~Sorter()
{
    for (std::list<SortProperty*>::iterator iter = sortProperties_.begin();
            iter != sortProperties_.end(); ++iter)
        delete *iter;
    if (ppSortProperties_) delete[] ppSortProperties_;
    if (reverseMul_) delete[] reverseMul_;
}

void Sorter::addSortProperty(const string& property, PropertyDataType propertyType, bool reverse)
{
    SortProperty* pSortProperty = new SortProperty(property, propertyType, reverse);
    sortProperties_.push_back(pSortProperty);
}

void Sorter::addSortProperty(SortProperty* pSortProperty)
{
    sortProperties_.push_back(pSortProperty);
}

void Sorter::getComparators()
{
    SortProperty* pSortProperty;
    nNumProperties_ = sortProperties_.size();
    ppSortProperties_ = new SortProperty*[nNumProperties_];
    size_t i = 0;
    size_t numOfInValidComparators = 0;
    for (std::list<SortProperty*>::iterator iter = sortProperties_.begin();
            iter != sortProperties_.end(); ++iter, ++i)
    {
        pSortProperty = *iter;
        ppSortProperties_[i] = pSortProperty;
        if (pSortProperty)
        {
            switch (pSortProperty->getType())
            {
            case SortProperty::SCORE:
                pSortProperty->pComparator_= new SortPropertyComparator();
                break;
            case SortProperty::AUTO:
                {
                    if (!pSortProperty->pComparator_)
                        pSortProperty->pComparator_ = pCache_->getComparator(pSortProperty);

                    if (!pSortProperty->pComparator_)
                        ++numOfInValidComparators;
                }
                break;
            case SortProperty::CUSTOM:
                pSortProperty->pComparator_ = new SortPropertyComparator(CUSTOM_RANKING_PROPERTY_TYPE);
                break;
            case SortProperty::CTR:
                pSortProperty->pComparator_ = pCache_->getComparator(pSortProperty);
                if (!pSortProperty->pComparator_)
                    ++numOfInValidComparators;
                break;
            }
        }
    }
    if (numOfInValidComparators > 0)
    {
        SortProperty** ppSortProperties = NULL;
        if (numOfInValidComparators == nNumProperties_)
        {
            nNumProperties_ = 1;
            ppSortProperties = new SortProperty*[nNumProperties_];
            SortProperty* pSortProperty = new SortProperty("RANK", UNKNOWN_DATA_PROPERTY_TYPE);
            pSortProperty->pComparator_ = new SortPropertyComparator();
            ppSortProperties[0] = pSortProperty;
            sortProperties_.push_back(pSortProperty);
        }
        else
        {
            ppSortProperties = new SortProperty*[nNumProperties_];
            size_t j = 0;
            for (i = 0; i < nNumProperties_; ++i)
            {
                SortProperty* pSortProperty = ppSortProperties_[i];
                if (pSortProperty->pComparator_)
                {
                    ppSortProperties[j++] = pSortProperty;
                }
            }
            nNumProperties_ = j;
        }
        delete [] ppSortProperties_;
        ppSortProperties_ = ppSortProperties;
    }
    reverseMul_ = new int[nNumProperties_];
    for (i = 0; i < nNumProperties_; ++i)
    {
        reverseMul_[i] = ppSortProperties_[i]->isReverse() ? -1 : 1;
    }
}
<commit_msg>bugs of split_float in SortPropertyCache:it's totally broken<commit_after>#include "Sorter.h"

using namespace sf1r;

const char SortPropertyCache::Separator[] = {'-', '~', ','};

SortProperty::SortProperty(const SortProperty& src)
    : property_(src.property_)
    , propertyDataType_(src.propertyDataType_)
    , type_(src.type_)
    , reverse_(src.reverse_)
    , pComparator_(src.pComparator_)
{
}

SortProperty::SortProperty(const string& property, PropertyDataType propertyType, bool reverse)
    : property_(property)
    , propertyDataType_(propertyType)
    , type_(AUTO)
    , reverse_(reverse)
    , pComparator_(NULL)
{
}

SortProperty::SortProperty(const string& property, PropertyDataType propertyType, SortPropertyType type, bool reverse)
    : property_(property)
    , propertyDataType_(propertyType)
    , type_(type)
    , reverse_(reverse)
    , pComparator_(NULL)
{
}
SortProperty::SortProperty(const string& property, PropertyDataType propertyType, SortPropertyComparator* pComparator, bool reverse)
    : property_(property)
    , propertyDataType_(propertyType)
    , type_(CUSTOM)
    , reverse_(reverse)
    , pComparator_(pComparator)
{
}

SortProperty::SortProperty(const string& property, PropertyDataType propertyType, SortPropertyComparator* pComparator, SortPropertyType type, bool reverse)
    : property_(property)
    , propertyDataType_(propertyType)
    , type_(type)
    , reverse_(reverse)
    , pComparator_(pComparator)
{
}

SortProperty::~SortProperty()
{
    if (pComparator_)
        delete pComparator_;
}

SortPropertyCache::SortPropertyCache(IndexManager* pIndexer, IndexBundleConfiguration* config)
    : pIndexer_(pIndexer)
    , pCTRManager_(NULL)
    , updateInterval_(config->sortCacheUpdateInterval_)
    , dirty_(true)
    , config_(config)
{
    std::cout << "SortPropertyCache::updateInterval_ = " << updateInterval_ << std::endl;
}

void SortPropertyCache::setCtrManager(faceted::CTRManager* pCTRManager)
{
    pCTRManager_ = pCTRManager;
}

void SortPropertyCache::loadSortData(const std::string& property, PropertyDataType type)
{
    void* data = NULL;
    size_t size = 0;
    switch (type)
    {
    case INT_PROPERTY_TYPE:
        pIndexer_->loadPropertyDataForSorting(property, (int64_t*&)data, size);
        break;

    case UNSIGNED_INT_PROPERTY_TYPE:
        pIndexer_->loadPropertyDataForSorting(property, (uint64_t*&)data, size);
        break;

    case FLOAT_PROPERTY_TYPE:
        pIndexer_->loadPropertyDataForSorting(property, (float*&)data, size);
        break;

    case DOUBLE_PROPERTY_TYPE:
        pIndexer_->loadPropertyDataForSorting(property, (double*&)data, size);
        break;

    case STRING_PROPERTY_TYPE:
        pIndexer_->convertStringPropertyDataForSorting(property, (uint32_t*&)data, size);
        break;

    default:
        break;
    }

    if (data)
        sortDataCache_[property].reset(new PropertyData(type, data, size));
    else
        sortDataCache_[property].reset();
}

boost::shared_ptr<PropertyData> SortPropertyCache::getSortPropertyData(const std::string& propertyName, PropertyDataType propertyType)
{
    boost::mutex::scoped_lock lock(this->mutex_);
    if (dirty_)
    {
        for (SortDataCache::iterator iter = sortDataCache_.begin();
            iter != sortDataCache_.end(); ++iter)
        {
            LOG(INFO) << "dirty sort data cache on property: " << iter->first;
            if (iter->second) loadSortData(iter->first, iter->second->type_);
        }
        dirty_ = false;
    }

    SortDataCache::iterator iter = sortDataCache_.find(propertyName) ;
    if (iter == sortDataCache_.end() || !iter->second)
    {
        LOG(INFO) << "first load sort data cache on property: " << propertyName;
        loadSortData(propertyName, propertyType);
    }

    return sortDataCache_[propertyName];
}

boost::shared_ptr<PropertyData> SortPropertyCache::getCTRPropertyData(const std::string& propertyName, PropertyDataType propertyType)
{
    boost::mutex::scoped_lock lock(this->mutex_);

    bool updateCache = false;

    SortDataCache::iterator iter = sortDataCache_.find(propertyName) ;
    if (iter == sortDataCache_.end())
    {
        LOG(INFO) << "first load sort data cache on property: " << propertyName;
        updateCache = true;
    }
    else if (!(iter->second) ||(iter->second->elapsedFromLastLoad() > updateInterval_))
    {
        //LOG(INFO) << "Refresh sort data cache for property: " << propertyName
        //          << " after "<<iter->second->elapsedFromLastLoad()<<" seconds";
        updateCache = true;
    }

    if (updateCache)
    {
        void* data = NULL;
        size_t size = 0;
        pCTRManager_->loadCtrDataInt64((uint64_t*&)data,size);

        if (data)
        {
            sortDataCache_[propertyName].reset(new PropertyData(propertyType, data,size));
        }
        else
        {
            sortDataCache_[propertyName].reset();
        }
    }

    return sortDataCache_[propertyName];
}

bool SortPropertyCache::split_int(const izenelib::util::UString& szText, int64_t& out, izenelib::util::UString::EncodingType encoding, char Separator)
{
    std::string str;
    szText.convertString(str, encoding);

    size_t n = 0;
    n = str.find(Separator, 0);
    if (n != izenelib::util::UString::npos)
    {
        if (n != 0)
        {
            try
            {
                std::string tmpStr = str.substr(0, n);
                trim( tmpStr );
                out = boost::lexical_cast< int64_t >( tmpStr );
                return true;
            }
            catch( const boost::bad_lexical_cast & )
            {
                return false;
            }
        }
    }
    return false;
}

bool SortPropertyCache::split_float(const izenelib::util::UString& szText, float& out, izenelib::util::UString::EncodingType encoding, char Separator)
{
    std::string str;
    szText.convertString(str, encoding);

    size_t n = 0;
    n = str.find(Separator, 0);
    if (n != izenelib::util::UString::npos)
    {
        if (n != 0)
        {
            try
            {
                std::string tmpStr = str.substr(0, n);
                trim( tmpStr );
                out = boost::lexical_cast< float >( tmpStr );
                return true;
            }
            catch( const boost::bad_lexical_cast & )
            {
                return false;
            }
        }
    }
    return false;
}

void SortPropertyCache::updateSortData(docid_t id, const std::map<std::string, pair<PropertyDataType, izenelib::util::UString> >& rTypeFieldValue)
{
    boost::mutex::scoped_lock lock(this->mutex_);

    izenelib::util::UString::EncodingType encoding = config_->encoding_;
    std::map<std::string, pair<PropertyDataType, izenelib::util::UString> >::const_iterator iter;
    SortDataCache::const_iterator it;
    for (iter = rTypeFieldValue.begin(); iter != rTypeFieldValue.end(); iter++)
    {
        string propertyName = iter->first;
        PropertyDataType dataType = iter->second.first;
        switch(dataType)
        {
        case INT_PROPERTY_TYPE:
            {
                std::string str("");
                iter->second.second.convertString(str, encoding);
                int64_t value = 0;
                try
                {
                    value = boost::lexical_cast< int64_t >( iter->second.second );
                }
                catch( const boost::bad_lexical_cast & )
                {
                    for (int i = 0; i < EoC; i++)
                        if (split_int(iter->second.second, value, encoding, Separator[i]))
                            break;
                    if (value == 0)
                    {
                        LOG(ERROR) << "Wrong format of number value. value:"<<str;
                        break;
                    }
                }
                if ((it = sortDataCache_.find(propertyName)) != sortDataCache_.end())
                {
                    if (!it->second ||id >= it->second->size_)
                        continue;

                    int64_t* data = (int64_t*)(it->second->data_);
                    data[id] = value;
                }
            }
            break;
        case FLOAT_PROPERTY_TYPE:
            {
                std::string str("");
                iter->second.second.convertString(str, encoding);
                float value = 0.0;
                try
                {
                    value = boost::lexical_cast< float >( iter->second.second );
                }
                catch( const boost::bad_lexical_cast & )
                {
                    for (int i = 0; i < EoC; i++)
                        if (split_float(iter->second.second, value, encoding, Separator[i]))
                            break;
                    if (value == 0.0)
                    {
                        LOG(ERROR) << "Wrong format of number value. value:"<<str;
                        break;
                    }
                }
                if ((it = sortDataCache_.find(propertyName)) != sortDataCache_.end())
                {
                    if (!it->second ||id >= it->second->size_)
                        continue;

                    float* data = (float*)(it->second->data_);
                    data[id] = value;
                }
            }
            break;
        default:
            break;
        }
    }
}

SortPropertyComparator* SortPropertyCache::getComparator(SortProperty* pSortProperty)
{
    SortProperty::SortPropertyType propSortType = pSortProperty->getType();
    const std::string& propName = pSortProperty->getProperty();
    const PropertyDataType propDataType = pSortProperty->getPropertyDataType();

    boost::shared_ptr<PropertyData> propData;
    if (propSortType == SortProperty::AUTO)
    {
        propData = getSortPropertyData(propName, propDataType);
    }
    else if (propSortType == SortProperty::CTR)
    {
        if (pCTRManager_)
            propData = getCTRPropertyData(propName, propDataType);
    }
    else
    {
        // to extend
    }

    if (propData)
        return new SortPropertyComparator(propData);
    else
        return NULL;
}

Sorter::Sorter(SortPropertyCache* pCache)
    : pCache_(pCache)
    , ppSortProperties_(0)
    , reverseMul_(0)
{
}

Sorter::~Sorter()
{
    for (std::list<SortProperty*>::iterator iter = sortProperties_.begin();
            iter != sortProperties_.end(); ++iter)
        delete *iter;
    if (ppSortProperties_) delete[] ppSortProperties_;
    if (reverseMul_) delete[] reverseMul_;
}

void Sorter::addSortProperty(const string& property, PropertyDataType propertyType, bool reverse)
{
    SortProperty* pSortProperty = new SortProperty(property, propertyType, reverse);
    sortProperties_.push_back(pSortProperty);
}

void Sorter::addSortProperty(SortProperty* pSortProperty)
{
    sortProperties_.push_back(pSortProperty);
}

void Sorter::getComparators()
{
    SortProperty* pSortProperty;
    nNumProperties_ = sortProperties_.size();
    ppSortProperties_ = new SortProperty*[nNumProperties_];
    size_t i = 0;
    size_t numOfInValidComparators = 0;
    for (std::list<SortProperty*>::iterator iter = sortProperties_.begin();
            iter != sortProperties_.end(); ++iter, ++i)
    {
        pSortProperty = *iter;
        ppSortProperties_[i] = pSortProperty;
        if (pSortProperty)
        {
            switch (pSortProperty->getType())
            {
            case SortProperty::SCORE:
                pSortProperty->pComparator_= new SortPropertyComparator();
                break;
            case SortProperty::AUTO:
                {
                    if (!pSortProperty->pComparator_)
                        pSortProperty->pComparator_ = pCache_->getComparator(pSortProperty);

                    if (!pSortProperty->pComparator_)
                        ++numOfInValidComparators;
                }
                break;
            case SortProperty::CUSTOM:
                pSortProperty->pComparator_ = new SortPropertyComparator(CUSTOM_RANKING_PROPERTY_TYPE);
                break;
            case SortProperty::CTR:
                pSortProperty->pComparator_ = pCache_->getComparator(pSortProperty);
                if (!pSortProperty->pComparator_)
                    ++numOfInValidComparators;
                break;
            }
        }
    }
    if (numOfInValidComparators > 0)
    {
        SortProperty** ppSortProperties = NULL;
        if (numOfInValidComparators == nNumProperties_)
        {
            nNumProperties_ = 1;
            ppSortProperties = new SortProperty*[nNumProperties_];
            SortProperty* pSortProperty = new SortProperty("RANK", UNKNOWN_DATA_PROPERTY_TYPE);
            pSortProperty->pComparator_ = new SortPropertyComparator();
            ppSortProperties[0] = pSortProperty;
            sortProperties_.push_back(pSortProperty);
        }
        else
        {
            ppSortProperties = new SortProperty*[nNumProperties_];
            size_t j = 0;
            for (i = 0; i < nNumProperties_; ++i)
            {
                SortProperty* pSortProperty = ppSortProperties_[i];
                if (pSortProperty->pComparator_)
                {
                    ppSortProperties[j++] = pSortProperty;
                }
            }
            nNumProperties_ = j;
        }
        delete [] ppSortProperties_;
        ppSortProperties_ = ppSortProperties;
    }
    reverseMul_ = new int[nNumProperties_];
    for (i = 0; i < nNumProperties_; ++i)
    {
        reverseMul_[i] = ppSortProperties_[i]->isReverse() ? -1 : 1;
    }
}
<|endoftext|>


<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 RC 1        *
*                (c) 2006-2011 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Plugins                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include <sofa/simulation/common/Node.h>
#include <sofa/simulation/common/Simulation.h>
#include "ScriptEnvironment.h"
using namespace sofa::simulation;
#include <sofa/core/ExecParams.h>
using namespace sofa::core;

#include "Binding_Node.h"
#include "Binding_Context.h"
#include "PythonVisitor.h"
#include "PythonScriptEvent.h"

extern "C" PyObject * Node_executeVisitor(PyObject *self, PyObject * args)
{
    Node* node=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());

    PyObject* pyVisitor;
    if (!PyArg_ParseTuple(args, "O",&pyVisitor))
        Py_RETURN_NONE;
    PythonVisitor visitor(ExecParams::defaultInstance(),pyVisitor);
    node->executeVisitor(&visitor);

    Py_RETURN_NONE;
}

extern "C" PyObject * Node_getRoot(PyObject *self, PyObject * /*args*/)
{
    Node* node=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());

    // BaseNode is not binded in SofaPython, so getRoot is binded in Node instead of BaseNode
    return SP_BUILD_PYSPTR(node->getRoot());
}

// step the simulation
extern "C" PyObject * Node_simulationStep(PyObject * self, PyObject * args)
{
    Node* node=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());
    double dt;
    if (!PyArg_ParseTuple(args, "d",&dt))
        Py_RETURN_NONE;

    printf("Node_simulationStep node=%s dt=%f\n",node->getName().c_str(),(float)dt);

    getSimulation()->animate ( node, (SReal)dt );
//    simulation::getSimulation()->updateVisual( root );

    Py_RETURN_NONE;
}

extern "C" PyObject * Node_getChild(PyObject * self, PyObject * args)
{
    // BaseNode is not binded in SofaPython, so getChildNode is binded in Node instead of BaseNode
    Node* node=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());
    char *path;
    if (!PyArg_ParseTuple(args, "s",&path))
        Py_RETURN_NONE;
    if (!node || !path)
    {
        PyErr_BadArgument();
        Py_RETURN_NONE;
    }

    const objectmodel::BaseNode::Children& children = node->getChildren();
    Node *childNode = 0;
    // BaseNode ne pouvant pas être bindé en Python, et les BaseNodes des graphes étant toujours des Nodes,
    // on caste directement en Node.
    for (unsigned int i=0; i<children.size(); ++i)
        if (children[i]->getName() == path)
        {
            childNode = dynamic_cast<Node*>(children[i]);
            break;
        }
    if (!childNode)
    {
        printf("<SofaPython> Error: Node.getChildNode(%s) not found.\n",path);
        Py_RETURN_NONE;
    }
    return SP_BUILD_PYSPTR(childNode);
}

extern "C" PyObject * Node_getChildren(PyObject * self, PyObject * /*args*/)
{
    // BaseNode is not binded in SofaPython, so getChildNode is binded in Node instead of BaseNode
    Node* node=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());

    const objectmodel::BaseNode::Children& children = node->getChildren();

    // BaseNode ne pouvant pas être bindé en Python, et les BaseNodes des graphes étant toujours des Nodes,
    // on caste directement en Node.
    PyObject *list = PyList_New(children.size());

    for (unsigned int i=0; i<children.size(); ++i)
        PyList_SetItem(list,i,SP_BUILD_PYSPTR(children[i]));

    return list;
}

extern "C" PyObject * Node_getParents(PyObject * self, PyObject * /*args*/)
{
    // BaseNode is not binded in SofaPython, so getChildNode is binded in Node instead of BaseNode
    Node* node=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());

    const objectmodel::BaseNode::Children& parents = node->getParents();

    // BaseNode ne pouvant pas être bindé en Python, et les BaseNodes des graphes étant toujours des Nodes,
    // on caste directement en Node.
    PyObject *list = PyList_New(parents.size());

    for (unsigned int i=0; i<parents.size(); ++i)
        PyList_SetItem(list,i,SP_BUILD_PYSPTR(parents[i]));

    return list;
}

extern "C" PyObject * Node_createChild(PyObject *self, PyObject * args)
{
    Node* obj=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());
    char *nodeName;
    if (!PyArg_ParseTuple(args, "s",&nodeName))
        Py_RETURN_NONE;
    Node* child = obj->createChild(nodeName).get();
    ScriptEnvironment::nodeCreatedByScript(child);
    return SP_BUILD_PYSPTR(child);
}

extern "C" PyObject * Node_addObject(PyObject *self, PyObject * args)
{
    Node* node=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());
    PyObject* pyChild;
    if (!PyArg_ParseTuple(args, "O",&pyChild))
        Py_RETURN_NONE;
    BaseObject* object=dynamic_cast<BaseObject*>(((PySPtr<Base>*)pyChild)->object.get());
    if (!object)
    {
        PyErr_BadArgument();
        Py_RETURN_NONE;
    }
    node->addObject(object);

    if (node->isInitialized())
        printf("<SofaPython> WARNING Sofa.Node.addObject called on a node(%s) that is already initialized\n",node->getName().c_str());
    if (!ScriptEnvironment::isNodeCreatedByScript(node))
        printf("<SofaPython> WARNING Sofa.Node.addObject called on a node(%s) that is not created by the script\n",node->getName().c_str());

    //object->init();
    // plus besoin !! node->init(sofa::core::ExecParams::defaultInstance());

    Py_RETURN_NONE;
}

extern "C" PyObject * Node_removeObject(PyObject *self, PyObject * args)
{
    Node* node=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());
    PyObject* pyChild;
    if (!PyArg_ParseTuple(args, "O",&pyChild))
        Py_RETURN_NONE;
    BaseObject* object=dynamic_cast<BaseObject*>(((PySPtr<Base>*)pyChild)->object.get());
    if (!object)
    {
        PyErr_BadArgument();
        Py_RETURN_NONE;
    }
    node->removeObject(object);
    node->init(sofa::core::ExecParams::defaultInstance());

    Py_RETURN_NONE;
}

extern "C" PyObject * Node_addChild(PyObject *self, PyObject * args)
{
    Node* obj=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());
    PyObject* pyChild;
    if (!PyArg_ParseTuple(args, "O",&pyChild))
        Py_RETURN_NONE;
    BaseNode* child=dynamic_cast<BaseNode*>(((PySPtr<Base>*)pyChild)->object.get());
    if (!child)
    {
        PyErr_BadArgument();
        Py_RETURN_NONE;
    }
    obj->addChild(child);
    Py_RETURN_NONE;
}

extern "C" PyObject * Node_removeChild(PyObject *self, PyObject * args)
{
    Node* obj=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());
    PyObject* pyChild;
    if (!PyArg_ParseTuple(args, "O",&pyChild))
        Py_RETURN_NONE;
    BaseNode* child=dynamic_cast<BaseNode*>(((PySPtr<Base>*)pyChild)->object.get());
    if (!child)
    {
        PyErr_BadArgument();
        Py_RETURN_NONE;
    }
    obj->removeChild(child);
    Py_RETURN_NONE;
}

extern "C" PyObject * Node_moveChild(PyObject *self, PyObject * args)
{
    Node* obj=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());
    PyObject* pyChild;
    if (!PyArg_ParseTuple(args, "O",&pyChild))
        Py_RETURN_NONE;
    BaseNode* child=dynamic_cast<BaseNode*>(((PySPtr<Base>*)pyChild)->object.get());
    if (!child)
    {
        PyErr_BadArgument();
        Py_RETURN_NONE;
    }
    obj->moveChild(child);
    Py_RETURN_NONE;
}

extern "C" PyObject * Node_detachFromGraph(PyObject *self, PyObject * /*args*/)
{
    Node* node=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());
    node->detachFromGraph();
    Py_RETURN_NONE;
}

extern "C" PyObject * Node_sendScriptEvent(PyObject *self, PyObject * args)
{
    Node* node=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());
    PyObject* pyUserData;
    char* eventName;
    if (!PyArg_ParseTuple(args, "sO",&eventName,&pyUserData))
    {
        PyErr_BadArgument();
        Py_RETURN_NONE;
    }
    PythonScriptEvent event(node,eventName,pyUserData);
    // Entering c++ code that can re-enter Python code, need to release GIL
    Py_BEGIN_ALLOW_THREADS
    dynamic_cast<Node*>(node->getRoot())->propagateEvent(sofa::core::ExecParams::defaultInstance(), &event);
    Py_END_ALLOW_THREADS
    Py_RETURN_NONE;
}

SP_CLASS_METHODS_BEGIN(Node)
SP_CLASS_METHOD(Node,executeVisitor)
SP_CLASS_METHOD(Node,getRoot)
SP_CLASS_METHOD(Node,simulationStep)
SP_CLASS_METHOD(Node,getChild)
SP_CLASS_METHOD(Node,getChildren)
SP_CLASS_METHOD(Node,getParents)
SP_CLASS_METHOD(Node,createChild)
SP_CLASS_METHOD(Node,addObject)
SP_CLASS_METHOD(Node,removeObject)
SP_CLASS_METHOD(Node,addChild)
SP_CLASS_METHOD(Node,removeChild)
SP_CLASS_METHOD(Node,moveChild)
SP_CLASS_METHOD(Node,detachFromGraph)
SP_CLASS_METHOD(Node,sendScriptEvent)
SP_CLASS_METHODS_END

SP_CLASS_TYPE_SPTR(Node,Node,Context)
<commit_msg>r10094/sofa : FIX crash in Python visitors<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 RC 1        *
*                (c) 2006-2011 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Plugins                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include <sofa/simulation/common/Node.h>
#include <sofa/simulation/common/Simulation.h>
#include "ScriptEnvironment.h"
using namespace sofa::simulation;
#include <sofa/core/ExecParams.h>
using namespace sofa::core;

#include "Binding_Node.h"
#include "Binding_Context.h"
#include "PythonVisitor.h"
#include "PythonScriptEvent.h"

extern "C" PyObject * Node_executeVisitor(PyObject *self, PyObject * args)
{
    Node* node=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());

    PyObject* pyVisitor;
    if (!PyArg_ParseTuple(args, "O",&pyVisitor))
        Py_RETURN_NONE;
    PythonVisitor visitor(ExecParams::defaultInstance(),pyVisitor);
    node->executeVisitor(&visitor);

    Py_RETURN_NONE;
}

extern "C" PyObject * Node_getRoot(PyObject *self, PyObject * /*args*/)
{
    Node* node=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());

    // BaseNode is not binded in SofaPython, so getRoot is binded in Node instead of BaseNode
    return SP_BUILD_PYSPTR(node->getRoot());
}

// step the simulation
extern "C" PyObject * Node_simulationStep(PyObject * self, PyObject * args)
{
    Node* node=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());
    double dt;
    if (!PyArg_ParseTuple(args, "d",&dt))
        Py_RETURN_NONE;

    printf("Node_simulationStep node=%s dt=%f\n",node->getName().c_str(),(float)dt);

    getSimulation()->animate ( node, (SReal)dt );
//    simulation::getSimulation()->updateVisual( root );

    Py_RETURN_NONE;
}

extern "C" PyObject * Node_getChild(PyObject * self, PyObject * args)
{
    // BaseNode is not binded in SofaPython, so getChildNode is binded in Node instead of BaseNode
    Node* node=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());
    char *path;
    if (!PyArg_ParseTuple(args, "s",&path))
        Py_RETURN_NONE;
    if (!node || !path)
    {
        PyErr_BadArgument();
        Py_RETURN_NONE;
    }

    const objectmodel::BaseNode::Children& children = node->getChildren();
    Node *childNode = 0;
    // BaseNode ne pouvant pas être bindé en Python, et les BaseNodes des graphes étant toujours des Nodes,
    // on caste directement en Node.
    for (unsigned int i=0; i<children.size(); ++i)
        if (children[i]->getName() == path)
        {
            childNode = dynamic_cast<Node*>(children[i]);
            break;
        }
    if (!childNode)
    {
        printf("<SofaPython> Error: Node.getChildNode(%s) not found.\n",path);
        Py_RETURN_NONE;
    }
    return SP_BUILD_PYSPTR(childNode);
}

extern "C" PyObject * Node_getChildren(PyObject * self, PyObject * /*args*/)
{
    // BaseNode is not binded in SofaPython, so getChildNode is binded in Node instead of BaseNode
    Node* node=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());

    const objectmodel::BaseNode::Children& children = node->getChildren();

    // BaseNode ne pouvant pas être bindé en Python, et les BaseNodes des graphes étant toujours des Nodes,
    // on caste directement en Node.
    PyObject *list = PyList_New(children.size());

    for (unsigned int i=0; i<children.size(); ++i)
        PyList_SetItem(list,i,SP_BUILD_PYSPTR(children[i]));

    return list;
}

extern "C" PyObject * Node_getParents(PyObject * self, PyObject * /*args*/)
{
    // BaseNode is not binded in SofaPython, so getChildNode is binded in Node instead of BaseNode
    Node* node=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());

    const objectmodel::BaseNode::Children& parents = node->getParents();

    // BaseNode ne pouvant pas être bindé en Python, et les BaseNodes des graphes étant toujours des Nodes,
    // on caste directement en Node.
    PyObject *list = PyList_New(parents.size());

    for (unsigned int i=0; i<parents.size(); ++i)
        PyList_SetItem(list,i,SP_BUILD_PYSPTR(parents[i]));

    return list;
}

extern "C" PyObject * Node_createChild(PyObject *self, PyObject * args)
{
    Node* obj=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());
    char *nodeName;
    if (!PyArg_ParseTuple(args, "s",&nodeName))
        Py_RETURN_NONE;
    Node* child = obj->createChild(nodeName).get();
    ScriptEnvironment::nodeCreatedByScript(child);
    return SP_BUILD_PYSPTR(child);
}

extern "C" PyObject * Node_addObject(PyObject *self, PyObject * args)
{
    Node* node=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());
    PyObject* pyChild;
    if (!PyArg_ParseTuple(args, "O",&pyChild))
        Py_RETURN_NONE;
    BaseObject* object=dynamic_cast<BaseObject*>(((PySPtr<Base>*)pyChild)->object.get());
    if (!object)
    {
        PyErr_BadArgument();
        Py_RETURN_NONE;
    }
    node->addObject(object);

    if (node->isInitialized())
        printf("<SofaPython> WARNING Sofa.Node.addObject called on a node(%s) that is already initialized\n",node->getName().c_str());
    if (!ScriptEnvironment::isNodeCreatedByScript(node))
        printf("<SofaPython> WARNING Sofa.Node.addObject called on a node(%s) that is not created by the script\n",node->getName().c_str());

    //object->init();
    // plus besoin !! node->init(sofa::core::ExecParams::defaultInstance());

    Py_RETURN_NONE;
}

extern "C" PyObject * Node_removeObject(PyObject *self, PyObject * args)
{
    Node* node=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());
    PyObject* pyChild;
    if (!PyArg_ParseTuple(args, "O",&pyChild))
        Py_RETURN_NONE;
    BaseObject* object=dynamic_cast<BaseObject*>(((PySPtr<Base>*)pyChild)->object.get());
    if (!object)
    {
        PyErr_BadArgument();
        Py_RETURN_NONE;
    }
    node->removeObject(object);
    node->init(sofa::core::ExecParams::defaultInstance());

    Py_RETURN_NONE;
}

extern "C" PyObject * Node_addChild(PyObject *self, PyObject * args)
{
    Node* obj=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());
    PyObject* pyChild;
    if (!PyArg_ParseTuple(args, "O",&pyChild))
        Py_RETURN_NONE;
    BaseNode* child=dynamic_cast<BaseNode*>(((PySPtr<Base>*)pyChild)->object.get());
    if (!child)
    {
        PyErr_BadArgument();
        Py_RETURN_NONE;
    }
    obj->addChild(child);
    Py_RETURN_NONE;
}

extern "C" PyObject * Node_removeChild(PyObject *self, PyObject * args)
{
    Node* obj=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());
    PyObject* pyChild;
    if (!PyArg_ParseTuple(args, "O",&pyChild))
        Py_RETURN_NONE;
    BaseNode* child=dynamic_cast<BaseNode*>(((PySPtr<Base>*)pyChild)->object.get());
    if (!child)
    {
        PyErr_BadArgument();
        Py_RETURN_NONE;
    }
    obj->removeChild(child);
    Py_RETURN_NONE;
}

extern "C" PyObject * Node_moveChild(PyObject *self, PyObject * args)
{
    Node* obj=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());
    PyObject* pyChild;
    if (!PyArg_ParseTuple(args, "O",&pyChild))
        Py_RETURN_NONE;
    BaseNode* child=dynamic_cast<BaseNode*>(((PySPtr<Base>*)pyChild)->object.get());
    if (!child)
    {
        PyErr_BadArgument();
        Py_RETURN_NONE;
    }
    obj->moveChild(child);
    Py_RETURN_NONE;
}

extern "C" PyObject * Node_detachFromGraph(PyObject *self, PyObject * /*args*/)
{
    Node* node=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());
    node->detachFromGraph();
    Py_RETURN_NONE;
}

extern "C" PyObject * Node_sendScriptEvent(PyObject *self, PyObject * args)
{
    Node* node=dynamic_cast<Node*>(((PySPtr<Base>*)self)->object.get());
    PyObject* pyUserData;
    char* eventName;
    if (!PyArg_ParseTuple(args, "sO",&eventName,&pyUserData))
    {
        PyErr_BadArgument();
        Py_RETURN_NONE;
    }
    PythonScriptEvent event(node,eventName,pyUserData);
    // Entering c++ code that can re-enter Python code, need to release GIL
//    Py_BEGIN_ALLOW_THREADS
    dynamic_cast<Node*>(node->getRoot())->propagateEvent(sofa::core::ExecParams::defaultInstance(), &event);
//    Py_END_ALLOW_THREADS
    Py_RETURN_NONE;
}

SP_CLASS_METHODS_BEGIN(Node)
SP_CLASS_METHOD(Node,executeVisitor)
SP_CLASS_METHOD(Node,getRoot)
SP_CLASS_METHOD(Node,simulationStep)
SP_CLASS_METHOD(Node,getChild)
SP_CLASS_METHOD(Node,getChildren)
SP_CLASS_METHOD(Node,getParents)
SP_CLASS_METHOD(Node,createChild)
SP_CLASS_METHOD(Node,addObject)
SP_CLASS_METHOD(Node,removeObject)
SP_CLASS_METHOD(Node,addChild)
SP_CLASS_METHOD(Node,removeChild)
SP_CLASS_METHOD(Node,moveChild)
SP_CLASS_METHOD(Node,detachFromGraph)
SP_CLASS_METHOD(Node,sendScriptEvent)
SP_CLASS_METHODS_END

SP_CLASS_TYPE_SPTR(Node,Node,Context)
<|endoftext|>


<commit_before>
#include "integrators/symplectic_partitioned_runge_kutta_integrator.hpp"

#include <algorithm>
#include <vector>

#include "geometry/sign.hpp"
#include "glog/logging.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "testing_utilities/numerics.hpp"

using principia::testing_utilities::AbsoluteError;
using testing::Lt;

namespace principia {
namespace integrators {

namespace {

inline void compute_harmonic_oscillator_force(double const t,
                                              std::vector<double> const& q,
                                              std::vector<double>* result) {
  (*result)[0] = -q[0];
}

inline void compute_harmonice_oscillator_velocity(std::vector<double> const& p,
                                                  std::vector<double>* result) {
  (*result)[0] = p[0];
}

}  // namespace

class SPRKTest : public testing::Test {
 protected:
  void SetUp() override {}

  SPRKIntegrator             integrator_;
  SPRKIntegrator::Parameters parameters_;
  SPRKIntegrator::Solution   solution_;
};

TEST_F(SPRKTest, HarmonicOscillator) {
  parameters_.q0 = {1.0};
  parameters_.p0 = {0.0};
  parameters_.t0 = 0.0;
#ifdef _DEBUG
  parameters_.tmax = 100.0;
#else
  parameters_.tmax = 1000.0;
#endif
  parameters_.Δt = 1.0E-4;
  parameters_.coefficients = integrator_.Order5Optimal();
  parameters_.sampling_period = 1;
  integrator_.Solve(&compute_harmonic_oscillator_force,
                    &compute_harmonice_oscillator_velocity,
                    parameters_, &solution_);
  double q_error = 0;
  double p_error = 0;
  for (size_t i = 0; i < solution_.time.quantities.size(); ++i) {
    q_error = std::max(q_error,
                       std::abs(solution_.position[0].quantities[i] -
                                std::cos(solution_.time.quantities[i])));
    p_error = std::max(p_error,
                       std::abs(solution_.momentum[0].quantities[i] +
                                std::sin(solution_.time.quantities[i])));
  }
  LOG(ERROR) << "q_error = " << q_error;
  LOG(ERROR) << "p_error = " << p_error;
  EXPECT_THAT(AbsoluteError(0, q_error), Lt(2E-16 * parameters_.tmax));
  EXPECT_THAT(AbsoluteError(0, p_error), Lt(2E-16 * parameters_.tmax));
}

}  // namespace integrators
}  // namespace principia
<commit_msg>some stuff<commit_after>
#include "integrators/symplectic_partitioned_runge_kutta_integrator.hpp"

#include <algorithm>
#include <vector>

#include "geometry/sign.hpp"
#include "glog/logging.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "testing_utilities/numerics.hpp"

using principia::testing_utilities::AbsoluteError;
using testing::Lt;

namespace principia {
namespace integrators {

namespace {

inline void compute_harmonic_oscillator_force(double const t,
                                              std::vector<double> const& q,
                                              std::vector<double>* result) {
  (*result)[0] = -q[0];
}

inline void compute_harmonice_oscillator_velocity(std::vector<double> const& p,
                                                  std::vector<double>* result) {
  (*result)[0] = p[0];
}

}  // namespace

class SPRKTest : public testing::Test {
 protected:
  void SetUp() override {}

  SPRKIntegrator             integrator_;
  SPRKIntegrator::Parameters parameters_;
  SPRKIntegrator::Solution   solution_;
};

TEST_F(SPRKTest, HarmonicOscillator) {
  parameters_.q0 = {1.0};
  parameters_.p0 = {0.0};
  parameters_.t0 = 0.0;
#ifdef _DEBUG
  parameters_.tmax = 100.0;
#else
  parameters_.tmax = 1000.0;
#endif
  parameters_.Δt = 1.0E-4;
  parameters_.coefficients = integrator_.Order5Optimal();
  parameters_.sampling_period = 1;
  integrator_.Solve(&compute_harmonic_oscillator_force,
                    &compute_harmonice_oscillator_velocity,
                    parameters_, &solution_);
  double q_error = 0;
  double p_error = 0;
  for (size_t i = 0; i < solution_.time.quantities.size(); ++i) {
    q_error = std::max(q_error,
                       std::abs(solution_.position[0].quantities[i] -
                                std::cos(solution_.time.quantities[i])));
    p_error = std::max(p_error,
                       std::abs(solution_.momentum[0].quantities[i] +
                                std::sin(solution_.time.quantities[i])));
  }
  LOG(ERROR) << "q_error = " << q_error;
  LOG(ERROR) << "p_error = " << p_error;
  EXPECT_THAT(AbsoluteError(0, q_error), Lt(2E-16 * parameters_.tmax));
  EXPECT_THAT(AbsoluteError(0, p_error), Lt(2E-16 * parameters_.tmax));
}

TEST_F(SPRKTest, Convergence) {
  parameters_.tmax = 100;
  parameters_.coefficients = integrator_.Order5Optimal();
  parameters_.sampling_period = 0;
  int const step_sizes = 5;
  std::vector<double> log_step_sizes(step_sizes);
  std::vector<double> log_q_errors(step_sizes);
  std::vector<double> log_p_errors(step_sizes);
  parameters_.Δt = 1;
  for(int i = 0; i < step_sizes; ++i, parameters_.Δt /= 10) {
    integrator_.Solve(&compute_harmonic_oscillator_force,
                      &compute_harmonice_oscillator_velocity,
                      parameters_, &solution_);
    log_step_sizes[i] = std::log(parameters_.Δt);
    log_q_errors[i] = std::log(
        std::abs(solution_.position[0].quantities[0] -
                 std::cos(solution_.time.quantities[0])));
    log_p_errors[i] = std::log(
        std::abs(solution_.position[0].quantities[0] -
                 std::sin(solution_.time.quantities[0])));
  }

}

}  // namespace integrators
}  // namespace principia
<|endoftext|>


<commit_before><commit_msg>coverity#1224982 out of bound<commit_after><|endoftext|>


<commit_before>#include "stdafx.h"

#include "P23.MetaTrader4.Manager.ClrWrapper.h"

IList<P23::MetaTrader4::Manager::Contracts::TradeRecord^>^ P23::MetaTrader4::Manager::ClrWrapper::ReportsRequest(P23::MetaTrader4::Manager::Contracts::ReportGroupRequest^ request, IList<int>^ logins)
{
	if (request == nullptr)
		throw gcnew ArgumentNullException("request");

	if (logins == nullptr)
		throw gcnew ArgumentNullException("logins");

	if (logins->Count == 0)
		throw gcnew ArgumentException("At least one login should be provided", "logins");

	int total = 0;
	ReportGroupRequest* convertedRequest = Convert(request);
	convertedRequest->total = logins->Count;

	int* unmanagedLogins = Convert(logins);
	TradeRecord* records = _manager->Manager->ReportsRequest(convertedRequest, unmanagedLogins, &total);
	IList<P23::MetaTrader4::Manager::Contracts::TradeRecord^>^ result = gcnew List<P23::MetaTrader4::Manager::Contracts::TradeRecord^>();
	for (int i = 0; i < total; i++)
		result->Add(Convert(&records[i]));

	_manager->Manager->MemFree(records);
	delete convertedRequest;
	delete[] unmanagedLogins;

	return result;
}

IList<P23::MetaTrader4::Manager::Contracts::DailyReport^>^ P23::MetaTrader4::Manager::ClrWrapper::DailyReportsRequest(P23::MetaTrader4::Manager::Contracts::DailyGroupRequest^ request, IList<int>^ logins)
{
	if (request == nullptr)
		throw gcnew ArgumentNullException("request");

	if (logins == nullptr)
		throw gcnew ArgumentNullException("logins");

	if (logins->Count == 0)
		throw gcnew ArgumentException("At least one login should be provided", "logins");

	if (request->To - request->From < (unsigned int)NumberOfSecondsInDay)
		throw gcnew ArgumentException("Minimum difference between To and From should be 24 hours", "request");

	int total = 0;
	DailyGroupRequest* convertedRequest = Convert(request);
	convertedRequest->total = logins->Count;

	DailyReport* records = _manager->Manager->DailyReportsRequest(convertedRequest, Convert(logins), &total);
	IList<P23::MetaTrader4::Manager::Contracts::DailyReport^>^ result = gcnew List<P23::MetaTrader4::Manager::Contracts::DailyReport^>();
	for (int i = 0; i < total; i++)
		result->Add(Convert(&records[i]));

	_manager->Manager->MemFree(records);

	return result;
}

//--- external command
int P23::MetaTrader4::Manager::ClrWrapper::ExternalCommand(String^ dataIn, int sizeIn, String^ dataOut, int sizeOut)
{
	throw gcnew NotImplementedException();
	//return _manager->Manager->ExternalCommand(Convert(dataIn), sizeIn,, Convert(dataOut), sizeOut);
}

//--- plugins
int P23::MetaTrader4::Manager::ClrWrapper::PluginUpdate(PluginWithParameters^ plugin)
{
	if (plugin == nullptr)
		throw gcnew ArgumentNullException("plugin");

	return _manager->Manager->PluginUpdate(Convert(plugin));
}
<commit_msg>implement ClrWrapper::ExternalCommand<commit_after>#include "stdafx.h"

#include "P23.MetaTrader4.Manager.ClrWrapper.h"

IList<P23::MetaTrader4::Manager::Contracts::TradeRecord^>^ P23::MetaTrader4::Manager::ClrWrapper::ReportsRequest(P23::MetaTrader4::Manager::Contracts::ReportGroupRequest^ request, IList<int>^ logins)
{
	if (request == nullptr)
		throw gcnew ArgumentNullException("request");

	if (logins == nullptr)
		throw gcnew ArgumentNullException("logins");

	if (logins->Count == 0)
		throw gcnew ArgumentException("At least one login should be provided", "logins");

	int total = 0;
	ReportGroupRequest* convertedRequest = Convert(request);
	convertedRequest->total = logins->Count;

	int* unmanagedLogins = Convert(logins);
	TradeRecord* records = _manager->Manager->ReportsRequest(convertedRequest, unmanagedLogins, &total);
	IList<P23::MetaTrader4::Manager::Contracts::TradeRecord^>^ result = gcnew List<P23::MetaTrader4::Manager::Contracts::TradeRecord^>();
	for (int i = 0; i < total; i++)
		result->Add(Convert(&records[i]));

	_manager->Manager->MemFree(records);
	delete convertedRequest;
	delete[] unmanagedLogins;

	return result;
}

IList<P23::MetaTrader4::Manager::Contracts::DailyReport^>^ P23::MetaTrader4::Manager::ClrWrapper::DailyReportsRequest(P23::MetaTrader4::Manager::Contracts::DailyGroupRequest^ request, IList<int>^ logins)
{
	if (request == nullptr)
		throw gcnew ArgumentNullException("request");

	if (logins == nullptr)
		throw gcnew ArgumentNullException("logins");

	if (logins->Count == 0)
		throw gcnew ArgumentException("At least one login should be provided", "logins");

	if (request->To - request->From < (unsigned int)NumberOfSecondsInDay)
		throw gcnew ArgumentException("Minimum difference between To and From should be 24 hours", "request");

	int total = 0;
	DailyGroupRequest* convertedRequest = Convert(request);
	convertedRequest->total = logins->Count;

	DailyReport* records = _manager->Manager->DailyReportsRequest(convertedRequest, Convert(logins), &total);
	IList<P23::MetaTrader4::Manager::Contracts::DailyReport^>^ result = gcnew List<P23::MetaTrader4::Manager::Contracts::DailyReport^>();
	for (int i = 0; i < total; i++)
		result->Add(Convert(&records[i]));

	_manager->Manager->MemFree(records);

	return result;
}

//--- external command
int P23::MetaTrader4::Manager::ClrWrapper::ExternalCommand(String^ dataIn, int sizeIn, String^ dataOut, int sizeOut)
{
	//throw gcnew NotImplementedException();
	char* outDataPointer = Convert(dataOut);
	return _manager->Manager->ExternalCommand(Convert(dataIn), sizeIn, &outDataPointer, &sizeOut);
}

//--- plugins
int P23::MetaTrader4::Manager::ClrWrapper::PluginUpdate(PluginWithParameters^ plugin)
{
	if (plugin == nullptr)
		throw gcnew ArgumentNullException("plugin");

	return _manager->Manager->PluginUpdate(Convert(plugin));
}
<|endoftext|>