<commit_before>/*===========================================================================*\
 *                                                                           *
 *                               OpenMesh                                    *
 *      Copyright (C) 2001-2012 by Computer Graphics Group, RWTH Aachen      *
 *                           www.openmesh.org                                *
 *                                                                           *
 *---------------------------------------------------------------------------*
 *  This file is part of OpenMesh.                                           *
 *                                                                           *
 *  OpenMesh 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 3 of           *
 *  the License, or (at your option) any later version with the              *
 *  following exceptions:                                                    *
 *                                                                           *
 *  If other files instantiate templates or use macros                       *
 *  or inline functions from this file, or you compile this file and         *
 *  link it with other files to produce an executable, this file does        *
 *  not by itself cause the resulting executable to be covered by the        *
 *  GNU Lesser General Public License. This exception does not however       *
 *  invalidate any other reasons why the executable file might be            *
 *  covered by the GNU Lesser General Public License.                        *
 *                                                                           *
 *  OpenMesh 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 LesserGeneral Public          *
 *  License along with OpenMesh.  If not,                                    *
 *  see <http://www.gnu.org/licenses/>.                                      *
 *                                                                           *
\*===========================================================================*/

/*===========================================================================*\
 *                                                                           *
 *   $Revision$                                                         *
 *   $Date$                   *
 *                                                                           *
\*===========================================================================*/

//=============================================================================
//
//  Implements the baseclass for IOManager writer modules
//
//=============================================================================

#ifndef __BASEWRITER_HH__
#define __BASEWRITER_HH__

//=== INCLUDES ================================================================

// STD C++
#include <iostream>
#include <string>

// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/IO/Options.hh>
#include <OpenMesh/Core/IO/exporter/BaseExporter.hh>

//== NAMESPACES ===============================================================

namespace OpenMesh {
namespace IO {

//=== IMPLEMENTATION ==========================================================

/**
   Base class for all writer modules. The module should register itself at
   the IOManager by calling the register_module function.
*/
class OPENMESHDLLEXPORT BaseWriter
{
public:

  typedef unsigned int Option;

  /// Destructor
  virtual ~BaseWriter() {};

  /// Return short description of the supported file format.
  virtual std::string get_description() const = 0;

  /// Return file format's extension.
  virtual std::string get_extensions() const = 0;

  /// Returns true if writer can parse _filename (checks extension)
  virtual bool can_u_write(const std::string& _filename) const;

  /// Write to file _filename. Data source specified by BaseExporter _be.
  virtual bool write(const std::string& _filename,
		     BaseExporter& _be,
                     Options _opt,
                     std::streamsize _precision = 6) const = 0;

  /// Write to std::ostream  _os. Data source specified by BaseExporter _be.
  virtual bool write(std::ostream& _os,
		     BaseExporter& _be,
                     Options _opt,
                     std::streamsize _precision = 6) const = 0;

  /// Returns expected size of file if binary format is supported else 0.
  virtual size_t binary_size(BaseExporter&, Options) const { return 0; }

protected:

  bool check(BaseExporter& _be, Options _opt) const
  {
    return (_opt.check(Options::VertexNormal ) <= _be.has_vertex_normals())
       &&  (_opt.check(Options::VertexTexCoord)<= _be.has_vertex_texcoords())
       &&  (_opt.check(Options::VertexColor)   <= _be.has_vertex_colors())
       &&  (_opt.check(Options::FaceNormal)    <= _be.has_face_normals())
       &&  (_opt.check(Options::FaceColor)     <= _be.has_face_colors());
  }
};

//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================
<commit_msg>- added some documentation to the BaseWriter<commit_after>/*===========================================================================*\
 *                                                                           *
 *                               OpenMesh                                    *
 *      Copyright (C) 2001-2012 by Computer Graphics Group, RWTH Aachen      *
 *                           www.openmesh.org                                *
 *                                                                           *
 *---------------------------------------------------------------------------*
 *  This file is part of OpenMesh.                                           *
 *                                                                           *
 *  OpenMesh 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 3 of           *
 *  the License, or (at your option) any later version with the              *
 *  following exceptions:                                                    *
 *                                                                           *
 *  If other files instantiate templates or use macros                       *
 *  or inline functions from this file, or you compile this file and         *
 *  link it with other files to produce an executable, this file does        *
 *  not by itself cause the resulting executable to be covered by the        *
 *  GNU Lesser General Public License. This exception does not however       *
 *  invalidate any other reasons why the executable file might be            *
 *  covered by the GNU Lesser General Public License.                        *
 *                                                                           *
 *  OpenMesh 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 LesserGeneral Public          *
 *  License along with OpenMesh.  If not,                                    *
 *  see <http://www.gnu.org/licenses/>.                                      *
 *                                                                           *
\*===========================================================================*/

/*===========================================================================*\
 *                                                                           *
 *   $Revision$                                                         *
 *   $Date$                   *
 *                                                                           *
\*===========================================================================*/

//=============================================================================
//
//  Implements the baseclass for IOManager writer modules
//
//=============================================================================

#ifndef __BASEWRITER_HH__
#define __BASEWRITER_HH__

//=== INCLUDES ================================================================

// STD C++
#include <iostream>
#include <string>

// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/IO/Options.hh>
#include <OpenMesh/Core/IO/exporter/BaseExporter.hh>

//== NAMESPACES ===============================================================

namespace OpenMesh {
namespace IO {

//=== IMPLEMENTATION ==========================================================

/**
   Base class for all writer modules. The module should register itself at
   the IOManager by calling the register_module function.
*/
class OPENMESHDLLEXPORT BaseWriter
{
public:

  typedef unsigned int Option;

  /// Destructor
  virtual ~BaseWriter() {};

  /// Return short description of the supported file format.
  virtual std::string get_description() const = 0;

  /// Return file format's extension.
  virtual std::string get_extensions() const = 0;

  /// Returns true if writer can parse _filename (checks extension)
  virtual bool can_u_write(const std::string& _filename) const;

  /** Write to a file
   * @param _filename write to file with the given filename
   * @param _be BaseExporter, which specifies the data source
   * @param _opt writing options
   * @param _precision can be used to specify the precision of the floating point notation.
   */
  virtual bool write(const std::string& _filename,
		     BaseExporter& _be,
                     Options _opt,
                     std::streamsize _precision = 6) const = 0;

  /** Write to a std::ostream
   * @param _os write to std::ostream
   * @param _be BaseExporter, which specifies the data source
   * @param _opt writing options
   * @param _precision can be used to specify the precision of the floating point notation.
   */
  virtual bool write(std::ostream& _os,
		     BaseExporter& _be,
                     Options _opt,
                     std::streamsize _precision = 6) const = 0;

  /// Returns expected size of file if binary format is supported else 0.
  virtual size_t binary_size(BaseExporter&, Options) const { return 0; }

protected:

  bool check(BaseExporter& _be, Options _opt) const
  {
    return (_opt.check(Options::VertexNormal ) <= _be.has_vertex_normals())
       &&  (_opt.check(Options::VertexTexCoord)<= _be.has_vertex_texcoords())
       &&  (_opt.check(Options::VertexColor)   <= _be.has_vertex_colors())
       &&  (_opt.check(Options::FaceNormal)    <= _be.has_face_normals())
       &&  (_opt.check(Options::FaceColor)     <= _be.has_face_colors());
  }
};

//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================
<|endoftext|>


<commit_before>#ifndef RBX_VARIABLE_SCOPE_HPP
#define RBX_VARIABLE_SCOPE_HPP

#include "vm/object_utils.hpp"

#include "builtin/object.hpp"
#include "builtin/tuple.hpp"

namespace rubinius {

  class CompiledMethod;
  class Module;
  struct CallFrame;

  /**
   *  Variable information.
   */
  class VariableScope : public Object {
  public:
    const static object_type type = VariableScopeType;

  private:    /* Instance variables */
    /** Block given to method */
    Object*         block_;   // slot
    /** Method this scope is for. */
    CompiledMethod* method_;  // slot
    Module*         module_;  // slot
    VariableScope*  parent_;  // slot
    Tuple*          heap_locals_; // slot
    Object*         last_match_; // slot

  public:
    Object* self_;    // slot

    int number_of_locals_;
    bool isolated_;
    Object** locals_;
    int block_as_method_;

  public: /* Accessors */
    attr_accessor(block, Object);
    attr_accessor(method, CompiledMethod);
    attr_accessor(module, Module);
    attr_accessor(parent, VariableScope);
    attr_accessor(self, Object);
    attr_accessor(heap_locals, Tuple);
    attr_accessor(last_match, Object);

    static void init(STATE);
    static void bootstrap_methods(STATE);

    void fixup() { }

    bool isolated() {
      return isolated_;
    }

    Object** stack_locals() {
      return locals_;
    }

    bool block_as_method_p() {
      return block_as_method_ == 1;
    }

    void set_block_as_method(bool val) {
      block_as_method_ = (val ? 1 : 0);
    }

    /**
     *  Initialize scope for methods.
     */
    void prepare(Object* self, Module* mod, Object* block, CompiledMethod* method, int num) {
      rubinius::abort();
      init_header(UnspecifiedZone, InvalidType);
      klass_ = 0;
      ivars_ = 0;

      parent_ = nil<VariableScope>();
      self_ = self;
      method_ = method;
      module_ = mod;
      block_ = block;
      number_of_locals_ = num;

      for(int i = 0; i < num; i++) {
        locals_[i] = Qnil;
      }
    }

    void update_parent(VariableScope* vs) {
      parent_ = vs;
    }

    void set_local(STATE, int pos, Object* val) {
      if(isolated_) {
        heap_locals_->put(state, pos, val);
      } else {
        locals_[pos] = val;
      }
    }

    void set_local(int pos, Object* val) {
      assert(isolated_ == false);
      locals_[pos] = val;
    }

    Object* get_local(STATE, int pos) {
      if(isolated_) {
        return heap_locals_->at(state, pos);
      }
      return locals_[pos];
    }

    Object* get_local(int pos) {
      if(isolated_) {
        return heap_locals_->at(pos);
      }
      return locals_[pos];
    }

    int number_of_locals() {
      return number_of_locals_;
    }

    VariableScope* promote(STATE);

    // Ruby.primitive :variable_scope_of_sender
    static VariableScope* of_sender(STATE, CallFrame* calling_environment);

    // Ruby.primitive :variable_scope_current
    static VariableScope* current(STATE, CallFrame* calling_environment);

    // Ruby.primitive :variable_scope_locals
    Tuple* locals(STATE);

    // Ruby.primitive :variable_scope_method_visibility
    Object* method_visibility(STATE);

  public: // Rubinius Type stuff
    class Info : public TypeInfo {
    public:
      Info(object_type type) : TypeInfo(type) { }
      virtual void mark(Object* t, ObjectMark& mark);
      virtual void visit(Object*, ObjectVisitor&);
      virtual void set_field(STATE, Object*, size_t, Object*);
      virtual Object* get_field(STATE, Object*, size_t);
      virtual void auto_mark(Object*, ObjectMark&);
      virtual void auto_visit(Object*, ObjectVisitor&);
      virtual void populate_slot_locations();
    };
  };
}

#endif
<commit_msg>Cleanup unused code in VariableScope<commit_after>#ifndef RBX_VARIABLE_SCOPE_HPP
#define RBX_VARIABLE_SCOPE_HPP

#include "vm/object_utils.hpp"

#include "builtin/object.hpp"
#include "builtin/tuple.hpp"

namespace rubinius {

  class CompiledMethod;
  class Module;
  struct CallFrame;

  /**
   *  Variable information.
   */
  class VariableScope : public Object {
  public:
    const static object_type type = VariableScopeType;

  private:    /* Instance variables */
    /** Block given to method */
    Object*         block_;   // slot
    /** Method this scope is for. */
    CompiledMethod* method_;  // slot
    Module*         module_;  // slot
    VariableScope*  parent_;  // slot
    Tuple*          heap_locals_; // slot
    Object*         last_match_; // slot

  public:
    Object* self_;    // slot

    int number_of_locals_;
    bool isolated_;
    Object** locals_;
    int block_as_method_;

  public: /* Accessors */
    attr_accessor(block, Object);
    attr_accessor(method, CompiledMethod);
    attr_accessor(module, Module);
    attr_accessor(parent, VariableScope);
    attr_accessor(self, Object);
    attr_accessor(heap_locals, Tuple);
    attr_accessor(last_match, Object);

    static void init(STATE);
    static void bootstrap_methods(STATE);

    void fixup() { }

    bool isolated() {
      return isolated_;
    }

    Object** stack_locals() {
      return locals_;
    }

    bool block_as_method_p() {
      return block_as_method_ == 1;
    }

    void set_block_as_method(bool val) {
      block_as_method_ = (val ? 1 : 0);
    }

    void update_parent(VariableScope* vs) {
      parent_ = vs;
    }

    void set_local(STATE, int pos, Object* val) {
      if(isolated_) {
        heap_locals_->put(state, pos, val);
      } else {
        locals_[pos] = val;
      }
    }

    void set_local(int pos, Object* val) {
      assert(isolated_ == false);
      locals_[pos] = val;
    }

    Object* get_local(STATE, int pos) {
      if(isolated_) {
        return heap_locals_->at(state, pos);
      }
      return locals_[pos];
    }

    Object* get_local(int pos) {
      if(isolated_) {
        return heap_locals_->at(pos);
      }
      return locals_[pos];
    }

    int number_of_locals() {
      return number_of_locals_;
    }

    VariableScope* promote(STATE);

    // Ruby.primitive :variable_scope_of_sender
    static VariableScope* of_sender(STATE, CallFrame* calling_environment);

    // Ruby.primitive :variable_scope_current
    static VariableScope* current(STATE, CallFrame* calling_environment);

    // Ruby.primitive :variable_scope_locals
    Tuple* locals(STATE);

    // Ruby.primitive :variable_scope_method_visibility
    Object* method_visibility(STATE);

  public: // Rubinius Type stuff
    class Info : public TypeInfo {
    public:
      Info(object_type type) : TypeInfo(type) { }
      virtual void mark(Object* t, ObjectMark& mark);
      virtual void visit(Object*, ObjectVisitor&);
      virtual void set_field(STATE, Object*, size_t, Object*);
      virtual Object* get_field(STATE, Object*, size_t);
      virtual void auto_mark(Object*, ObjectMark&);
      virtual void auto_visit(Object*, ObjectVisitor&);
      virtual void populate_slot_locations();
    };
  };
}

#endif
<|endoftext|>


<commit_before>// Copyright © 2011, Université catholique de Louvain
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// *  Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
// *  Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#ifndef MOZART_MODTIME_H
#define MOZART_MODTIME_H

#include "../mozartcore.hh"

#ifndef MOZART_GENERATOR

namespace mozart {

namespace builtins {

/////////////////
// Time module //
/////////////////

class ModTime: public Module {
public:
  ModTime(): Module("Time") {}

  class Alarm: public Builtin<Alarm> {
  public:
    Alarm(): Builtin("alarm") {}

    static void call(VM vm, In delay, Out result) {
      auto intDelay = getArgument<nativeint>(vm, delay, "integer");

      if (intDelay <= 0) {
        result = build(vm, unit);
      } else {
        result = Variable::build(vm, vm->getTopLevelSpace());
        vm->setAlarm(intDelay, RichNode(result).getStableRef(vm));
      }
    }
  };

  class GetReferenceTime: public Builtin<GetReferenceTime> {
  public:
    GetReferenceTime(): Builtin("getReferenceTime") {}

    static void call(VM vm, Out result) {
      result = build(vm, vm->getReferenceTime());
    }
  };
};

}

}

#endif // MOZART_GENERATOR

#endif // MOZART_MODTIME_H
<commit_msg>Add Boot_Time.getMonotonicTime for benchmarking purpose<commit_after>// Copyright © 2011, Université catholique de Louvain
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// *  Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
// *  Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#ifndef MOZART_MODTIME_H
#define MOZART_MODTIME_H

#include <chrono>

#include "../mozartcore.hh"

#ifndef MOZART_GENERATOR

namespace mozart {

namespace builtins {

/////////////////
// Time module //
/////////////////

class ModTime: public Module {
public:
  ModTime(): Module("Time") {}

  class Alarm: public Builtin<Alarm> {
  public:
    Alarm(): Builtin("alarm") {}

    static void call(VM vm, In delay, Out result) {
      auto intDelay = getArgument<nativeint>(vm, delay, "integer");

      if (intDelay <= 0) {
        result = build(vm, unit);
      } else {
        result = Variable::build(vm, vm->getTopLevelSpace());
        vm->setAlarm(intDelay, RichNode(result).getStableRef(vm));
      }
    }
  };

  class GetReferenceTime: public Builtin<GetReferenceTime> {
  public:
    GetReferenceTime(): Builtin("getReferenceTime") {}

    static void call(VM vm, Out result) {
      result = build(vm, vm->getReferenceTime());
    }
  };

  class GetMonotonicTime: public Builtin<GetMonotonicTime> {
  public:
    GetMonotonicTime(): Builtin("getMonotonicTime") {}

    static void call(VM vm, Out result) {
      using namespace std::chrono;
      auto now = steady_clock::now();
      nanoseconds dur = duration_cast<nanoseconds>(now.time_since_epoch());
      result = build(vm, dur.count());
    }
  };
};

}

}

#endif // MOZART_GENERATOR

#endif // MOZART_MODTIME_H
<|endoftext|>


<commit_before>#pragma once

#include <bitset>
#include <cstring>
#include <iostream>

namespace despairagus {
	namespace bitwise {
		using std::cout;
		using std::ostream;

		template <typename A>
		class binary final {
			template<typename B>
			using conref = const B &;

			constexpr static const size_t sz{sizeof(A)};
			constexpr static const size_t szB{sz << 3};
			constexpr static const size_t szOneLess{sz - 1};

			using bitA = std::bitset<szB>;
			using byte = unsigned char;
			using bit = bool;

		public:
			explicit binary(void) = delete;

			explicit binary(conref<A> a) noexcept {
				byte *ptr = new byte[sz];
				memcpy((void *) ptr, (const void *const) &a, sz);

				for (size_t i = 0; i < sz; ++i) {
					static byte ch;
					ch = ptr[i];
					for (size_t j = 0; j < 8; ++j) {
						static bool bitVal;
						bitVal = binary<A>::getBitFromByte(ch, j);
						this->bits[binary<A>::getBitIdx(i, j)] = bitVal;
					}
				}

				delete[] ptr;
			}

			explicit binary(A &&a) noexcept : binary(a) {
			}

			template <typename... B>
			explicit binary(B... b) = delete;

			inline ~binary(void) noexcept {
				bits.~bitA();
			}

			inline void print(void) const noexcept {
				binary<A>::print(std::cout, *this);
			}

			inline bool getBit(conref<size_t> idx) const noexcept {
				return bits[idx];
			}

			inline bool getBit(size_t&& idx) const noexcept {
				return this->getBit(idx);
			}

			inline bool getBit(conref<size_t> a, conref<size_t> b) const noexcept {
				return this->getBit(binary<A>::getBitIdx((byte) a, (byte) b));
			}

			inline bool getBit(size_t &&a, size_t &&b) const noexcept {
				return this->getBit(a, b);
			}

			inline bool getBit(conref<int> idx) const noexcept {
				return this->getBit((size_t) idx);
			}

			inline bool getBit(int&& idx) const noexcept {
				return this->getBit((size_t) idx);
			}

			inline bool getBit(conref<byte> byteIdx, conref<byte> bitIdx) const noexcept {
				return binary<A>::getBit(*this, byteIdx, bitIdx);
			}

			inline bool getBit(byte&& byteIdx, byte&& bitIdx) const noexcept {
				return binary<A>::getBit(*this, byteIdx, bitIdx);
			}

			inline bool getBit(conref<int> byteIdx, conref<int> bitIdx) const noexcept {
				return binary<A>::getBit((size_t) byteIdx, (size_t) bitIdx);
			}

			inline bool getBit(int&& byteIdx, int&& bitIdx) const noexcept {
				return binary<A>::getBit(byteIdx, bitIdx);
			}

			template <typename... B>
			inline bool getBit(B... b) const noexcept = delete;

			template <typename B>
			friend inline ostream &operator<<(ostream &os, conref<binary<B>> a) noexcept {
				a.print(os, a);

				return os;
			}

			template <typename B>
			friend inline ostream &operator<<(ostream &os, binary<B> &&a) noexcept {
				return operator<<(os, a);
			}

			explicit operator bool(void) const noexcept {
				return this->bits.all();
			}

		private:
			static inline void print(std::ostream &os, conref<binary<A>> a) noexcept {
				for (size_t i = 0; i < sz; ++i) {
					for (size_t j = 0; j < 8; ++j) {
						static bit bitIdx;
						bitIdx = (bit) a.bits[getBitIdx(i, j)];
						os << bitIdx;
					}

					if (szOneLess != i) {
						os << ' ';
					}
				}
			}

			static inline bit getBitFromByte(conref<byte> data, conref<byte> bitIdx) noexcept {
				return data & (1 << bitIdx);
			}

			static inline size_t getBitIdx(conref<size_t> byteIdx, conref<size_t> bitIdx) noexcept {
				return (byteIdx << 3) + bitIdx;
			}

			static inline bit getBit(conref<binary<A>> bits, conref<size_t> byteIdx, conref<size_t> bitIdx) noexcept {
				return bits[getBitIdx(byteIdx, bitIdx)];
			}

			bitA bits;
		};
	}
}<commit_msg>change namespace for binary class to ... binary<commit_after>#pragma once

#include <bitset>
#include <cstring>
#include <iostream>

namespace despairagus {
	namespace binary {
		using std::cout;
		using std::ostream;

		template <typename A>
		class binary final {
			template<typename B>
			using conref = const B &;

			constexpr static const size_t sz{sizeof(A)};
			constexpr static const size_t szB{sz << 3};
			constexpr static const size_t szOneLess{sz - 1};

			using bitA = std::bitset<szB>;
			using byte = unsigned char;
			using bit = bool;

		public:
			explicit binary(void) = delete;

			explicit binary(conref<A> a) noexcept {
				byte *ptr = new byte[sz];
				memcpy((void *) ptr, (const void *const) &a, sz);

				for (size_t i = 0; i < sz; ++i) {
					static byte ch;
					ch = ptr[i];
					for (size_t j = 0; j < 8; ++j) {
						static bool bitVal;
						bitVal = binary<A>::getBitFromByte(ch, j);
						this->bits[binary<A>::getBitIdx(i, j)] = bitVal;
					}
				}

				delete[] ptr;
			}

			explicit binary(A &&a) noexcept : binary(a) {
			}

			template <typename... B>
			explicit binary(B... b) = delete;

			inline ~binary(void) noexcept {
				bits.~bitA();
			}

			inline void print(void) const noexcept {
				binary<A>::print(std::cout, *this);
			}

			inline bool getBit(conref<size_t> idx) const noexcept {
				return bits[idx];
			}

			inline bool getBit(size_t&& idx) const noexcept {
				return this->getBit(idx);
			}

			inline bool getBit(conref<size_t> a, conref<size_t> b) const noexcept {
				return this->getBit(binary<A>::getBitIdx((byte) a, (byte) b));
			}

			inline bool getBit(size_t &&a, size_t &&b) const noexcept {
				return this->getBit(a, b);
			}

			inline bool getBit(conref<int> idx) const noexcept {
				return this->getBit((size_t) idx);
			}

			inline bool getBit(int&& idx) const noexcept {
				return this->getBit((size_t) idx);
			}

			inline bool getBit(conref<byte> byteIdx, conref<byte> bitIdx) const noexcept {
				return binary<A>::getBit(*this, byteIdx, bitIdx);
			}

			inline bool getBit(byte&& byteIdx, byte&& bitIdx) const noexcept {
				return binary<A>::getBit(*this, byteIdx, bitIdx);
			}

			inline bool getBit(conref<int> byteIdx, conref<int> bitIdx) const noexcept {
				return binary<A>::getBit((size_t) byteIdx, (size_t) bitIdx);
			}

			inline bool getBit(int&& byteIdx, int&& bitIdx) const noexcept {
				return binary<A>::getBit(byteIdx, bitIdx);
			}

			template <typename... B>
			inline bool getBit(B... b) const noexcept = delete;

			template <typename B>
			friend inline ostream &operator<<(ostream &os, conref<binary<B>> a) noexcept {
				a.print(os, a);

				return os;
			}

			template <typename B>
			friend inline ostream &operator<<(ostream &os, binary<B> &&a) noexcept {
				return operator<<(os, a);
			}

			explicit operator bool(void) const noexcept {
				return this->bits.all();
			}

		private:
			static inline void print(std::ostream &os, conref<binary<A>> a) noexcept {
				for (size_t i = 0; i < sz; ++i) {
					for (size_t j = 0; j < 8; ++j) {
						static bit bitIdx;
						bitIdx = (bit) a.bits[getBitIdx(i, j)];
						os << bitIdx;
					}

					if (szOneLess != i) {
						os << ' ';
					}
				}
			}

			static inline bit getBitFromByte(conref<byte> data, conref<byte> bitIdx) noexcept {
				return data & (1 << bitIdx);
			}

			static inline size_t getBitIdx(conref<size_t> byteIdx, conref<size_t> bitIdx) noexcept {
				return (byteIdx << 3) + bitIdx;
			}

			static inline bit getBit(conref<binary<A>> bits, conref<size_t> byteIdx, conref<size_t> bitIdx) noexcept {
				return bits[getBitIdx(byteIdx, bitIdx)];
			}

			bitA bits;
		};
	}
}<|endoftext|>


<commit_before>#pragma once

#include <bitset>
#include <cstring>

template <typename A>
class binary final {
	template <typename B>
	using conref = const B&;

	constexpr static size_t sz{sizeof(A)};
	constexpr static auto szB{sz << 3};

	using bitA = std::bitset<szB>;
	using byte = unsigned char;
	using bit = bool;

public:
	explicit binary(void) = delete;

	explicit binary(conref<A> a) {
		byte* ptr = new byte[sz];
		memcpy((void *) ptr, (const void* const) &a, sz);

		for (size_t i = 0; i < sz; ++i) {
			static byte ch;
			ch = ptr[i];
			for (size_t j = 0; j < 8; ++j) {
				static bool bitVal;
				bitVal = binary::getBitFromByte(ch, j);
				this->bits[getBitIdx(j, i)] = bitVal;
			}
		}

		delete [] ptr;
	}

	explicit binary(A&& a) : binary(a) {}

	template <typename... B>
	explicit binary(B... b) = delete;

	~binary(void) {
		bits.~bitA();
	}

	static inline void print(std::ostream& os, binary<A> a) {
		for (size_t i = 0; i < sz; ++i) {
			for (size_t j = 0; predAndPrint(os, j); ++j) {
				static bool bit;
				bit = bits[getBitIdx(i, j)];
				os << bit;
			}
		}
	}
private:
	static inline bool getBitFromByte(byte data, byte bitIdx) {
		return data & (1 << bitIdx);
	}

	static inline size_t getBitIdx(size_t byteIdx, size_t bitIdx) {
		return (byteIdx << 3) + bitIdx;
	}

	static inline bool predAndPrint(conref<std::ostream> os, conref<size_t> idx) {
		const bool pred{idx < 8};

		if (!pred) {
			os << ' ';
		}

		return pred;
	} ;

	bitA bits;
};<commit_msg>did not work... changing back to size_t<commit_after>#pragma once

#include <bitset>
#include <cstring>

template <typename A>
class binary final {
	template <typename B>
	using conref = const B&;

	constexpr static size_t sz{sizeof(A)};
	constexpr static size_t szB{sz << 3};

	using bitA = std::bitset<szB>;
	using byte = unsigned char;
	using bit = bool;

public:
	explicit binary(void) = delete;

	explicit binary(conref<A> a) {
		byte* ptr = new byte[sz];
		memcpy((void *) ptr, (const void* const) &a, sz);

		for (size_t i = 0; i < sz; ++i) {
			static byte ch;
			ch = ptr[i];
			for (size_t j = 0; j < 8; ++j) {
				static bool bitVal;
				bitVal = binary::getBitFromByte(ch, j);
				this->bits[getBitIdx(j, i)] = bitVal;
			}
		}

		delete [] ptr;
	}

	explicit binary(A&& a) : binary(a) {}

	template <typename... B>
	explicit binary(B... b) = delete;

	~binary(void) {
		bits.~bitA();
	}

	static inline void print(std::ostream& os, binary<A> a) {
		for (size_t i = 0; i < sz; ++i) {
			for (size_t j = 0; predAndPrint(os, j); ++j) {
				static bool bit;
				bit = bits[getBitIdx(i, j)];
				os << bit;
			}
		}
	}
private:
	static inline bool getBitFromByte(byte data, byte bitIdx) {
		return data & (1 << bitIdx);
	}

	static inline size_t getBitIdx(size_t byteIdx, size_t bitIdx) {
		return (byteIdx << 3) + bitIdx;
	}

	static inline bool predAndPrint(conref<std::ostream> os, conref<size_t> idx) {
		const bool pred{idx < 8};

		if (!pred) {
			os << ' ';
		}

		return pred;
	} ;

	bitA bits;
};<|endoftext|>


<commit_before>#include "ndis56common.h"
#include "ParaNdis_GuestAnnounce.h"
#include "ParaNdis6_Driver.h"
#include "ethernetutils.h"

CGratARPPacketHolder::~CGratARPPacketHolder()
{
    PVOID buffer;
    PMDL mdl;
    if (m_NBL)
    {
        mdl = NET_BUFFER_CURRENT_MDL(NET_BUFFER_LIST_FIRST_NB(m_NBL));
        buffer = MmGetMdlVirtualAddress(mdl);
        if (mdl)
        {
            NdisFreeMdl(mdl);
        }
        if (buffer)
        {
            NdisFreeMemory(buffer, 0, 0);
        }
        NdisFreeNetBufferList(m_NBL);
    }
}

void CGratARPPacketHolder::OnLastReferenceGone()
{
    Destroy(this, m_handle);
}

EthernetArpFrame *CGratuitousArpPackets::CreateIPv4Packet(UINT32 IPV4)
{
    EthernetArpFrame *packet = (EthernetArpFrame *)ParaNdis_AllocateMemory(m_Context, sizeof(EthernetArpFrame));
    if (!packet)
    {
        DPrintf(0, ("Error could not allocate buffer for arp packet!\n"));
        return NULL;
    }
    packet->frame.ether_type = _byteswap_ushort(ETH_ETHER_TYPE_ARP);
    packet->data.hardware_type = _byteswap_ushort(ETH_HARDWARE_TYPE);
    packet->data.protocol_type = _byteswap_ushort(ETH_IP_PROTOCOL_TYPE);
    packet->data.hardware_address_length = ETH_HARDWARE_ADDRESS_SIZE;
    packet->data.protocol_address_length = ETH_IPV4_ADDRESS_SIZE;
    packet->data.operation = _byteswap_ushort(ETH_ARP_OPERATION_TYPE_REQUEST);
    for (UINT i = 0; i < ETH_HARDWARE_ADDRESS_SIZE; i++)
    {
        packet->frame.sender_hardware_address.address[i] = (UINT8)m_Context->CurrentMacAddress[i];
        packet->frame.target_hardware_address.address[i] = 0xFF;
        packet->data.sender_hardware_address.address[i] = m_Context->CurrentMacAddress[i];
        packet->data.target_hardware_address.address[i] = 0xFF;
    }
    packet->data.sender_ipv4_address.address = packet->data.target_ipv4_address.address = IPV4;
    return packet;
}

EthernetNSMFrame *CGratuitousArpPackets::CreateIPv6Packet(USHORT * IPV6)
{
    ICMPv6PseudoHeader pseudo_header;
    EthernetNSMFrame *packet = (EthernetNSMFrame *)ParaNdis_AllocateMemory(m_Context, sizeof(EthernetNSMFrame));
    if (!packet)
    {
        DPrintf(0, ("Error could not allocate buffer for arp packet!\n"));
        return NULL;
    }
    packet->frame.ether_type = _byteswap_ushort(ETH_ETHER_TYPE_IPV6);
    for (UINT i = 0; i < ETH_HARDWARE_ADDRESS_SIZE; i++)
    {
        packet->frame.sender_hardware_address.address[i] = (UINT8)m_Context->CurrentMacAddress[i];
        packet->frame.target_hardware_address.address[i] = 0xFF;
    }
    packet->data.version_trafficclass_flowlabel = _byteswap_ulong(ETH_IPV6_VERSION_TRAFFICCONTROL_FLOWLABEL);
    packet->data.payload_length = _byteswap_ushort(sizeof(packet->data.nsm));
    pseudo_header.icmpv6_length = (UINT16) _byteswap_ushort(sizeof(packet->data.nsm));
    packet->data.next_header = pseudo_header.next_header = ETH_IPV6_ICMPV6_PROTOCOL;
    packet->data.hop_limit = 0xFF;
    for (UINT i = 0; i < ETH_IPV6_USHORT_ADDRESS_SIZE; i++)
    {
        packet->data.source_address.address[i] = pseudo_header.source_address.address[i] = 0x0;
        packet->data.destination_address.address[i] = packet->data.nsm.target_address.address[i] =
            pseudo_header.destination_address.address[i] = pseudo_header.nsm.target_address.address[i] = IPV6[i];
    }
    packet->data.nsm.type = pseudo_header.nsm.type = ETH_ICMPV6_TYPE_NSM;
    packet->data.nsm.code = pseudo_header.nsm.code = 0x0;
    packet->data.nsm.checksum = pseudo_header.nsm.checksum = 0x0;
    packet->data.nsm.reserved = pseudo_header.nsm.reserved = 0x0;
    packet->data.nsm.checksum = (CheckSumCalculator(&pseudo_header, sizeof(pseudo_header)));
    return packet;
}

VOID CGratuitousArpPackets::CreateNBL(PVOID packet, UINT size, bool isIPV4)
{
    PMDL mdl = NdisAllocateMdl(m_Context->MiniportHandle, packet, size);
    if (!mdl)
    {
        DPrintf(0, ("[%s] mdl allocation failed!\n", __FUNCTION__));
        NdisFreeMemory(packet, 0, 0);
        return;
    }
    PNET_BUFFER_LIST nbl = NdisAllocateNetBufferAndNetBufferList(m_Context->BufferListsPool, 0, 0, mdl, 0, size);
    if (!nbl)
    {
        DPrintf(0, ("[%s] nbl allocation failed!\n", __FUNCTION__));
        NdisFreeMemory(packet, 0, 0);
        NdisFreeMdl(mdl);
        return;
    }
    nbl->SourceHandle = m_Context->MiniportHandle;
    CGratARPPacketHolder *GratARPPacket = new (m_Context->MiniportHandle) CGratARPPacketHolder(nbl, m_Context->MiniportHandle, isIPV4);
    nbl->NdisReserved[0] = GratARPPacket;
    m_packets.Push(GratARPPacket);
}

VOID CGratuitousArpPackets::CreateNBL(UINT32 IPV4)
{
    EthernetArpFrame * packet = CreateIPv4Packet(IPV4);
    if (packet)
    {
        CreateNBL(packet, sizeof(EthernetArpFrame), true);
    }
}

VOID CGratuitousArpPackets::CreateNBL(USHORT *IPV6)
{
    EthernetNSMFrame * packet = CreateIPv6Packet(IPV6);
    if (packet)
    {
        CreateNBL(packet, sizeof(EthernetNSMFrame), false);
    }
}

VOID CGratuitousArpPackets::SendNBLs()
{
    auto ctx = m_Context;
    m_packets.ForEach([ctx](CGratARPPacketHolder* GratARPPacket)
    {
        GratARPPacket->AddRef();
        ParaNdis6_SendNBLInternal(ctx, GratARPPacket->GetNBL(), 0, NDIS_SEND_FLAGS_DISPATCH_LEVEL);
    });
}

CGratARPPacketHolder *CGratuitousArpPackets::GetCGratArpPacketFromNBL(PNET_BUFFER_LIST NBL)
{
    return (CGratARPPacketHolder *)NBL->NdisReserved[0];
}

bool CallCompletionForNBL(PARANDIS_ADAPTER * pContext, PNET_BUFFER_LIST NBL)
{
    return !(NBL->SourceHandle == pContext->MiniportHandle && ParaNdis_CountNBLs(NBL) == 1);
}
<commit_msg>Net-KVM: Handle memory allocation failure<commit_after>#include "ndis56common.h"
#include "ParaNdis_GuestAnnounce.h"
#include "ParaNdis6_Driver.h"
#include "ethernetutils.h"

CGratARPPacketHolder::~CGratARPPacketHolder()
{
    PVOID buffer;
    PMDL mdl;
    if (m_NBL)
    {
        mdl = NET_BUFFER_CURRENT_MDL(NET_BUFFER_LIST_FIRST_NB(m_NBL));
        buffer = MmGetMdlVirtualAddress(mdl);
        if (mdl)
        {
            NdisFreeMdl(mdl);
        }
        if (buffer)
        {
            NdisFreeMemory(buffer, 0, 0);
        }
        NdisFreeNetBufferList(m_NBL);
    }
}

void CGratARPPacketHolder::OnLastReferenceGone()
{
    Destroy(this, m_handle);
}

EthernetArpFrame *CGratuitousArpPackets::CreateIPv4Packet(UINT32 IPV4)
{
    EthernetArpFrame *packet = (EthernetArpFrame *)ParaNdis_AllocateMemory(m_Context, sizeof(EthernetArpFrame));
    if (!packet)
    {
        DPrintf(0, ("Error could not allocate buffer for arp packet!\n"));
        return NULL;
    }
    packet->frame.ether_type = _byteswap_ushort(ETH_ETHER_TYPE_ARP);
    packet->data.hardware_type = _byteswap_ushort(ETH_HARDWARE_TYPE);
    packet->data.protocol_type = _byteswap_ushort(ETH_IP_PROTOCOL_TYPE);
    packet->data.hardware_address_length = ETH_HARDWARE_ADDRESS_SIZE;
    packet->data.protocol_address_length = ETH_IPV4_ADDRESS_SIZE;
    packet->data.operation = _byteswap_ushort(ETH_ARP_OPERATION_TYPE_REQUEST);
    for (UINT i = 0; i < ETH_HARDWARE_ADDRESS_SIZE; i++)
    {
        packet->frame.sender_hardware_address.address[i] = (UINT8)m_Context->CurrentMacAddress[i];
        packet->frame.target_hardware_address.address[i] = 0xFF;
        packet->data.sender_hardware_address.address[i] = m_Context->CurrentMacAddress[i];
        packet->data.target_hardware_address.address[i] = 0xFF;
    }
    packet->data.sender_ipv4_address.address = packet->data.target_ipv4_address.address = IPV4;
    return packet;
}

EthernetNSMFrame *CGratuitousArpPackets::CreateIPv6Packet(USHORT * IPV6)
{
    ICMPv6PseudoHeader pseudo_header;
    EthernetNSMFrame *packet = (EthernetNSMFrame *)ParaNdis_AllocateMemory(m_Context, sizeof(EthernetNSMFrame));
    if (!packet)
    {
        DPrintf(0, ("Error could not allocate buffer for arp packet!\n"));
        return NULL;
    }
    packet->frame.ether_type = _byteswap_ushort(ETH_ETHER_TYPE_IPV6);
    for (UINT i = 0; i < ETH_HARDWARE_ADDRESS_SIZE; i++)
    {
        packet->frame.sender_hardware_address.address[i] = (UINT8)m_Context->CurrentMacAddress[i];
        packet->frame.target_hardware_address.address[i] = 0xFF;
    }
    packet->data.version_trafficclass_flowlabel = _byteswap_ulong(ETH_IPV6_VERSION_TRAFFICCONTROL_FLOWLABEL);
    packet->data.payload_length = _byteswap_ushort(sizeof(packet->data.nsm));
    pseudo_header.icmpv6_length = (UINT16) _byteswap_ushort(sizeof(packet->data.nsm));
    packet->data.next_header = pseudo_header.next_header = ETH_IPV6_ICMPV6_PROTOCOL;
    packet->data.hop_limit = 0xFF;
    for (UINT i = 0; i < ETH_IPV6_USHORT_ADDRESS_SIZE; i++)
    {
        packet->data.source_address.address[i] = pseudo_header.source_address.address[i] = 0x0;
        packet->data.destination_address.address[i] = packet->data.nsm.target_address.address[i] =
            pseudo_header.destination_address.address[i] = pseudo_header.nsm.target_address.address[i] = IPV6[i];
    }
    packet->data.nsm.type = pseudo_header.nsm.type = ETH_ICMPV6_TYPE_NSM;
    packet->data.nsm.code = pseudo_header.nsm.code = 0x0;
    packet->data.nsm.checksum = pseudo_header.nsm.checksum = 0x0;
    packet->data.nsm.reserved = pseudo_header.nsm.reserved = 0x0;
    packet->data.nsm.checksum = (CheckSumCalculator(&pseudo_header, sizeof(pseudo_header)));
    return packet;
}

VOID CGratuitousArpPackets::CreateNBL(PVOID packet, UINT size, bool isIPV4)
{
    PMDL mdl = NdisAllocateMdl(m_Context->MiniportHandle, packet, size);
    if (!mdl)
    {
        DPrintf(0, ("[%s] mdl allocation failed!\n", __FUNCTION__));
        NdisFreeMemory(packet, 0, 0);
        return;
    }
    PNET_BUFFER_LIST nbl = NdisAllocateNetBufferAndNetBufferList(m_Context->BufferListsPool, 0, 0, mdl, 0, size);
    if (!nbl)
    {
        DPrintf(0, ("[%s] nbl allocation failed!\n", __FUNCTION__));
        NdisFreeMemory(packet, 0, 0);
        NdisFreeMdl(mdl);
        return;
    }
    nbl->SourceHandle = m_Context->MiniportHandle;
    CGratARPPacketHolder *GratARPPacket = new (m_Context->MiniportHandle) CGratARPPacketHolder(nbl, m_Context->MiniportHandle, isIPV4);
    if (!GratARPPacket)
    {
        DPrintf(0, ("[%s] Packet holder allocation failed!\n", __FUNCTION__));
        NdisFreeNetBufferList(nbl);
        NdisFreeMdl(mdl);
        NdisFreeMemory(packet, 0, 0);
        return;
    }
    nbl->NdisReserved[0] = GratARPPacket;
    m_packets.Push(GratARPPacket);
}

VOID CGratuitousArpPackets::CreateNBL(UINT32 IPV4)
{
    EthernetArpFrame * packet = CreateIPv4Packet(IPV4);
    if (packet)
    {
        CreateNBL(packet, sizeof(EthernetArpFrame), true);
    }
}

VOID CGratuitousArpPackets::CreateNBL(USHORT *IPV6)
{
    EthernetNSMFrame * packet = CreateIPv6Packet(IPV6);
    if (packet)
    {
        CreateNBL(packet, sizeof(EthernetNSMFrame), false);
    }
}

VOID CGratuitousArpPackets::SendNBLs()
{
    auto ctx = m_Context;
    m_packets.ForEach([ctx](CGratARPPacketHolder* GratARPPacket)
    {
        GratARPPacket->AddRef();
        ParaNdis6_SendNBLInternal(ctx, GratARPPacket->GetNBL(), 0, NDIS_SEND_FLAGS_DISPATCH_LEVEL);
    });
}

CGratARPPacketHolder *CGratuitousArpPackets::GetCGratArpPacketFromNBL(PNET_BUFFER_LIST NBL)
{
    return (CGratARPPacketHolder *)NBL->NdisReserved[0];
}

bool CallCompletionForNBL(PARANDIS_ADAPTER * pContext, PNET_BUFFER_LIST NBL)
{
    return !(NBL->SourceHandle == pContext->MiniportHandle && ParaNdis_CountNBLs(NBL) == 1);
}
<|endoftext|>


<commit_before>#include "core_digital.h"
#include "Arduino.h"
#include "Servo.hpp"

/*
 * bt_hc06
 * Take control of the board using JY-MCU/HC06 Bluetooth 2.0 module.
 * Remote control is operated from Android phone using simple opensource application:
 * https://play.google.com/store/apps/details?id=com.gundel.bluecontrol&hl=en
 */

#define HC06_SERIAL SERIAL_PORT_HARDWARE_OPEN1

#define PIN_SERVO_LEFT        (14u)
#define PIN_SERVO_RIGHT       (15u)

Servo servo_left;
Servo servo_right;

static void hc06_init(void)
{
  String s;

  HC06_SERIAL.begin( 9600 ) ; // Default baudrate for HC06 module

  // Test SERIAL_PORT_MONITOR output
  SERIAL_PORT_MONITOR.println("AT");
  HC06_SERIAL.print("AT");
  s=HC06_SERIAL.readString();
  SERIAL_PORT_MONITOR.println(s);

  SERIAL_PORT_MONITOR.println("AT+VERSION");
  HC06_SERIAL.print("AT+VERSION");
  s=HC06_SERIAL.readString();
  SERIAL_PORT_MONITOR.println(s);

  SERIAL_PORT_MONITOR.println("AT+NAMESAM_HC06");
  HC06_SERIAL.print("AT+NAMESAM_HC06");
  s=HC06_SERIAL.readString();
  SERIAL_PORT_MONITOR.println(s);
}

static void servos_init(void)
{
  pinMode(PIN_SERVO_LEFT, OUTPUT);
  servo_left.attach(PIN_SERVO_LEFT);    // attaches the servo connected to pin PIN_SERVO_LEFT to the servo_left object

  pinMode(PIN_SERVO_RIGHT, OUTPUT);
  servo_right.attach(PIN_SERVO_RIGHT);  // attaches the servo connected to pin PIN_SERVO_RIGHT to the servo_right object
}

// the setup function runs once when you press reset or power the board
void setup(void)
{
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);   // turn the LED on (HIGH is the voltage level)

  SERIAL_PORT_MONITOR.begin( 115200 ) ; // Output to EDBG Virtual COM Port
  hc06_init();

  servos_init();

  delay(1000);              // wait for a second
  // Show we did the setup already
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED off
}

// the loop function runs over and over again forever
void loop(void)
{
  char c;

  if ( HC06_SERIAL.available() )
  // if text arrived in from BT serial...
  {
    c=HC06_SERIAL.read();
        SERIAL_PORT_MONITOR.print("Received:");
        SERIAL_PORT_MONITOR.println(c);
    switch ( c )
    {
      case 'C': // stop everything
        servo_left.write(90); //
        servo_right.write(90); //
      break;

      case 'U':
        // move robot forward
        servo_left.write(180); //
        servo_right.write(0); //
      break;

      case 'D':
        // move robot backward
        servo_left.write(0); //
        servo_right.write(180); //
      break;

      case 'L':
        // move robot forward
        servo_left.write(180); //
        servo_right.write(180); //
      break;

      case 'R':
        // move robot backward
        servo_left.write(0); //
        servo_right.write(0); //
      break;

      default:
      break;
    }
  }
}
<commit_msg>[examples] Makes  wheel_robot_servo compile-able on every board<commit_after>#include "Arduino.h"
#include "Servo.hpp"

/*
 * bt_hc06
 * Take control of the board using JY-MCU/HC06 Bluetooth 2.0 module.
 * Remote control is operated from Android phone using simple opensource application:
 * https://play.google.com/store/apps/details?id=com.gundel.bluecontrol&hl=en
 */

#if defined SERIAL_PORT_HARDWARE_OPEN1
#define HC06_SERIAL SERIAL_PORT_HARDWARE_OPEN1
#endif // SERIAL_PORT_HARDWARE_OPEN1

#define PIN_SERVO_LEFT        (14u)
#define PIN_SERVO_RIGHT       (15u)

Servo servo_left;
Servo servo_right;

#if defined HC06_SERIAL
static void hc06_init(void)
{
  String s;

  HC06_SERIAL.begin( 9600 ) ; // Default baudrate for HC06 module

  // Test SERIAL_PORT_MONITOR output
  SERIAL_PORT_MONITOR.println("AT");
  HC06_SERIAL.print("AT");
  s=HC06_SERIAL.readString();
  SERIAL_PORT_MONITOR.println(s);

  SERIAL_PORT_MONITOR.println("AT+VERSION");
  HC06_SERIAL.print("AT+VERSION");
  s=HC06_SERIAL.readString();
  SERIAL_PORT_MONITOR.println(s);

  SERIAL_PORT_MONITOR.println("AT+NAMESAM_HC06");
  HC06_SERIAL.print("AT+NAMESAM_HC06");
  s=HC06_SERIAL.readString();
  SERIAL_PORT_MONITOR.println(s);
}
#endif // HC06_SERIAL

static void servos_init(void)
{
  pinMode(PIN_SERVO_LEFT, OUTPUT);
  servo_left.attach(PIN_SERVO_LEFT);    // attaches the servo connected to pin PIN_SERVO_LEFT to the servo_left object

  pinMode(PIN_SERVO_RIGHT, OUTPUT);
  servo_right.attach(PIN_SERVO_RIGHT);  // attaches the servo connected to pin PIN_SERVO_RIGHT to the servo_right object
}

// the setup function runs once when you press reset or power the board
void setup(void)
{
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);   // turn the LED on (HIGH is the voltage level)

  SERIAL_PORT_MONITOR.begin( 115200 ) ; // Output to EDBG Virtual COM Port
#if defined HC06_SERIAL
  hc06_init();
#endif // HC06_SERIAL

  servos_init();

  delay(1000);              // wait for a second
  // Show we did the setup already
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED off
}

// the loop function runs over and over again forever
void loop(void)
{
#if defined HC06_SERIAL
  char c;

  if ( HC06_SERIAL.available() )
  // if text arrived in from BT serial...
  {
    c=HC06_SERIAL.read();
    SERIAL_PORT_MONITOR.print("Received:");
    SERIAL_PORT_MONITOR.println(c);

    switch ( c )
    {
      case 'C': // stop everything
        servo_left.write(90); //
        servo_right.write(90); //
      break;

      case 'U':
        // move robot forward
        servo_left.write(180); //
        servo_right.write(0); //
      break;

      case 'D':
        // move robot backward
        servo_left.write(0); //
        servo_right.write(180); //
      break;

      case 'L':
        // move robot forward
        servo_left.write(180); //
        servo_right.write(180); //
      break;

      case 'R':
        // move robot backward
        servo_left.write(0); //
        servo_right.write(0); //
      break;

      default:
      break;
    }
  }
#endif // HC06_SERIAL
}
<|endoftext|>


<commit_before>#include "app/impl/collider/simple_collider.h"

#include <algorithm>
#include <iterator>

#include "core/types/null.h"
#include "core/types/weak_ptr.h"
#include "core/util/log.h"

#include "graphics/base/rect.h"
#include "graphics/base/render_object.h"
#include "graphics/base/size.h"
#include "graphics/base/v2.h"

#include "renderer/base/resource_loader_context.h"

#include "app/base/application_context.h"
#include "app/base/rigid_body.h"
#include "app/inf/collision_callback.h"

namespace ark {

namespace {

class DynamicPosition : public VV2 {
public:
    DynamicPosition(const sp<SimpleCollider::RigidBodyImpl>& rigidBody, const sp<VV>& position)
        : _rigid_body(rigidBody), _position(position), _bounds(0, 0, rigidBody->size()->width(), rigidBody->size()->height()) {
    }

    virtual V2 val() override {
        const sp<SimpleCollider::RigidBodyImpl> rigidBody = _rigid_body.ensure();
        const V position = _position->val();
        _bounds.setCenter(position.x(), position.y());
        rigidBody->collision(_bounds);
        rigidBody->update();
        return position;
    }

private:
    WeakPtr<SimpleCollider::RigidBodyImpl> _rigid_body;
    sp<VV> _position;
    Rect _bounds;
};

}

SimpleCollider::SimpleCollider(const sp<ResourceLoaderContext>& resourceLoaderContext)
    : _stub(sp<Stub>::make()), _resource_loader_context(resourceLoaderContext)
{
}

SimpleCollider::BUILDER::BUILDER(BeanFactory& factory, const document& manifest, const sp<ResourceLoaderContext>& resourceLoaderContext)
    : _resource_loader_context(resourceLoaderContext)
{
}

sp<Collider> SimpleCollider::BUILDER::build(const sp<Scope>& args)
{
    return sp<SimpleCollider>::make(_resource_loader_context);
}

sp<RigidBody> SimpleCollider::createBody(Collider::BodyType type, Collider::BodyShape shape, const sp<VV>& position, const sp<Size>& size)
{
    const sp<RigidBodyImpl> rigidBody = _stub->createRigidBody(type, shape, position, size, _stub);

    if(type == Collider::BODY_TYPE_DYNAMIC)
    {
        rigidBody->setPosition(_resource_loader_context->synchronize<V>(sp<DynamicPosition>::make(rigidBody, position)));
    }
    else if(type == Collider::BODY_TYPE_KINEMATIC)
    {
    }
    else if(type == Collider::BODY_TYPE_STATIC)
    {
    }
    return rigidBody;
}

SimpleCollider::Stub::Stub()
    : _rigid_body_base_id(0)
{
}

void SimpleCollider::Stub::insert(const sp<RigidBodyImpl>& rigidObject)
{
    const V position = rigidObject->position()->val();
    const sp<Size>& size = rigidObject->size();
    _x_axis_segment.insert(rigidObject->id(), position.x(), size->width() / 2);
    _y_axis_segment.insert(rigidObject->id(), position.y(), size->height() / 2);
}

void SimpleCollider::Stub::remove(const RigidBodyImpl& rigidBody)
{
    _x_axis_segment.remove(rigidBody.id());
    _y_axis_segment.remove(rigidBody.id());
    const auto iter = _rigid_bodies.find(rigidBody.id());
    DCHECK(iter != _rigid_bodies.end(), "RigidBody(%d) not found", rigidBody.id());
    LOGD("Removing RigidBody(%d)", rigidBody.id());
    _rigid_bodies.erase(iter);
}

sp<SimpleCollider::RigidBodyImpl> SimpleCollider::Stub::createRigidBody(Collider::BodyType type, Collider::BodyShape shape, const sp<VV>& position, const sp<Size>& size, const sp<SimpleCollider::Stub>& self)
{
    const sp<RigidBodyShadow> rigidBodyShadow = sp<RigidBodyShadow>::make(++_rigid_body_base_id, type, shape, position, size);
    const sp<RigidBodyImpl> rigidBody = sp<RigidBodyImpl>::make(position, self, rigidBodyShadow);
    _rigid_bodies[rigidBody->id()] = rigidBodyShadow;
    insert(rigidBody);
    return rigidBody;
}

const sp<SimpleCollider::RigidBodyShadow>& SimpleCollider::Stub::findRigidBody(uint32_t id) const
{
    const auto iter = _rigid_bodies.find(id);
    DCHECK(iter != _rigid_bodies.end(), "RigidBody(id = %d) does not exists", id);
    return iter->second;
}

SimpleCollider::RigidBodyImpl::RigidBodyImpl(const sp<VV>& position, const sp<Stub>& collider, const sp<RigidBodyShadow>& shadow)
    : RigidBody(shadow->id(), shadow->type(), shadow->shape(), position, shadow->size(), Null::ptr<Numeric>()), _collider(collider), _shadow(shadow)
{
}

SimpleCollider::RigidBodyImpl::~RigidBodyImpl()
{
    if(_id > 0)
        _collider->remove(*this);
}

void SimpleCollider::RigidBodyImpl::beginContact(const sp<RigidBody>& rigidBody)
{
    if(_shadow->collisionCallback())
        _shadow->collisionCallback()->onBeginContact(rigidBody);
}

void SimpleCollider::RigidBodyImpl::endContact(const sp<RigidBody>& rigidBody)
{
    if(_shadow->collisionCallback())
        _shadow->collisionCallback()->onEndContact(rigidBody);
}

const sp<CollisionCallback>& SimpleCollider::RigidBodyImpl::collisionCallback() const
{
    return _shadow->collisionCallback();
}

void SimpleCollider::RigidBodyImpl::setCollisionCallback(const sp<CollisionCallback>& collisionCallback)
{
    _shadow->setCollisionCallback(collisionCallback);
}

void SimpleCollider::RigidBodyImpl::dispose()
{
    DCHECK(_id != 0, "RigidBody has been disposed already.");
    _collider->remove(*this);
    _id = 0;
}

void SimpleCollider::RigidBodyImpl::setPosition(const sp<VV>& position)
{
    _position = position;
}

void SimpleCollider::RigidBodyImpl::collision(const Rect& rect)
{
    std::set<uint32_t> candidates;
    std::set<uint32_t> contacts = _contacts;
    const std::set<uint32_t> x = _collider->_x_axis_segment.findCandidates(rect.left(), rect.right());
    if(x.size())
    {
        const std::set<uint32_t> y = _collider->_y_axis_segment.findCandidates(rect.top(), rect.bottom());
        std::set_intersection(x.begin(), x.end(), y.begin(), y.end(), std::inserter(candidates, candidates.begin()));
        for(auto iter = candidates.begin(); iter != candidates.end();)
        {
            uint32_t id = *iter;
            if(id == _id)
            {
                iter = candidates.erase(iter);
                continue;
            }
            const sp<RigidBodyShadow>& rigidBody = _collider->findRigidBody(id);
            const sp<Size>& size = rigidBody->size();
            const V position = rigidBody->xy();
            const Rect irect(position.x() - size->width() / 2, position.y() - size->height() / 2, position.x() + size->width() / 2, position.y() + size->height() / 2);
            bool overlap = irect.overlap(rect);
            if(overlap)
            {
                auto iter2 = contacts.find(id);
                if(iter2 == contacts.end())
                    beginContact(rigidBody);
                else
                    contacts.erase(iter2);
                ++iter;
            }
            else
                iter = candidates.erase(iter);
        }
        for(uint32_t i : contacts)
        {
            if(candidates.find(i) == candidates.end())
                endContact(_collider->findRigidBody(i));
        }
        _contacts = candidates;
    }
}

void SimpleCollider::RigidBodyImpl::update()
{
    const V pos = _position->val();
    _shadow->setPosition(pos);
    _collider->_x_axis_segment.update(_id, pos.x(), _size->width());
    _collider->_y_axis_segment.update(_id, pos.y(), _size->height());
}

SimpleCollider::RigidBodyShadow::RigidBodyShadow(uint32_t id, Collider::BodyType type, Collider::BodyShape shape, const sp<VV>& pos, const sp<Size>& size)
    : RigidBody(id, type, shape, sp<VV::Impl>::make(pos->val()), size, nullptr)
{
    _position = static_cast<sp<VV::Impl>>(position());
}

void SimpleCollider::RigidBodyShadow::dispose()
{
    FATAL("RigidBody may not be disposed");
}

const sp<CollisionCallback>& SimpleCollider::RigidBodyShadow::collisionCallback() const
{
    return _collision_callback;
}

void SimpleCollider::RigidBodyShadow::setCollisionCallback(const sp<CollisionCallback>& collisionCallback)
{
    _collision_callback = collisionCallback;
}

void SimpleCollider::RigidBodyShadow::setPosition(const V& pos)
{
    _position->set(pos);
}

}
<commit_msg>simple collider bug fix<commit_after>#include "app/impl/collider/simple_collider.h"

#include <algorithm>
#include <iterator>

#include "core/types/null.h"
#include "core/types/weak_ptr.h"
#include "core/util/log.h"

#include "graphics/base/rect.h"
#include "graphics/base/render_object.h"
#include "graphics/base/size.h"
#include "graphics/base/v2.h"

#include "renderer/base/resource_loader_context.h"

#include "app/base/application_context.h"
#include "app/base/rigid_body.h"
#include "app/inf/collision_callback.h"

namespace ark {

namespace {

class DynamicPosition : public VV2 {
public:
    DynamicPosition(const sp<SimpleCollider::RigidBodyImpl>& rigidBody, const sp<VV>& position)
        : _rigid_body(rigidBody), _position(position), _bounds(0, 0, rigidBody->size()->width(), rigidBody->size()->height()) {
    }

    virtual V2 val() override {
        const sp<SimpleCollider::RigidBodyImpl> rigidBody = _rigid_body.lock();
        const V position = _position->val();
        if(rigidBody && rigidBody->id()) {
            _bounds.setCenter(position.x(), position.y());
            rigidBody->collision(_bounds);
            rigidBody->update();
        }
        return position;
    }

private:
    WeakPtr<SimpleCollider::RigidBodyImpl> _rigid_body;
    sp<VV> _position;
    Rect _bounds;
};

}

SimpleCollider::SimpleCollider(const sp<ResourceLoaderContext>& resourceLoaderContext)
    : _stub(sp<Stub>::make()), _resource_loader_context(resourceLoaderContext)
{
}

SimpleCollider::BUILDER::BUILDER(BeanFactory& factory, const document& manifest, const sp<ResourceLoaderContext>& resourceLoaderContext)
    : _resource_loader_context(resourceLoaderContext)
{
}

sp<Collider> SimpleCollider::BUILDER::build(const sp<Scope>& args)
{
    return sp<SimpleCollider>::make(_resource_loader_context);
}

sp<RigidBody> SimpleCollider::createBody(Collider::BodyType type, Collider::BodyShape shape, const sp<VV>& position, const sp<Size>& size)
{
    const sp<RigidBodyImpl> rigidBody = _stub->createRigidBody(type, shape, position, size, _stub);

    if(type == Collider::BODY_TYPE_DYNAMIC)
    {
        rigidBody->setPosition(_resource_loader_context->synchronize<V>(sp<DynamicPosition>::make(rigidBody, position)));
    }
    else if(type == Collider::BODY_TYPE_KINEMATIC)
    {
    }
    else if(type == Collider::BODY_TYPE_STATIC)
    {
    }
    return rigidBody;
}

SimpleCollider::Stub::Stub()
    : _rigid_body_base_id(0)
{
}

void SimpleCollider::Stub::insert(const sp<RigidBodyImpl>& rigidObject)
{
    const V position = rigidObject->position()->val();
    const sp<Size>& size = rigidObject->size();
    _x_axis_segment.insert(rigidObject->id(), position.x(), size->width() / 2);
    _y_axis_segment.insert(rigidObject->id(), position.y(), size->height() / 2);
}

void SimpleCollider::Stub::remove(const RigidBodyImpl& rigidBody)
{
    _x_axis_segment.remove(rigidBody.id());
    _y_axis_segment.remove(rigidBody.id());
    const auto iter = _rigid_bodies.find(rigidBody.id());
    DCHECK(iter != _rigid_bodies.end(), "RigidBody(%d) not found", rigidBody.id());
    LOGD("Removing RigidBody(%d)", rigidBody.id());
    _rigid_bodies.erase(iter);
}

sp<SimpleCollider::RigidBodyImpl> SimpleCollider::Stub::createRigidBody(Collider::BodyType type, Collider::BodyShape shape, const sp<VV>& position, const sp<Size>& size, const sp<SimpleCollider::Stub>& self)
{
    const sp<RigidBodyShadow> rigidBodyShadow = sp<RigidBodyShadow>::make(++_rigid_body_base_id, type, shape, position, size);
    const sp<RigidBodyImpl> rigidBody = sp<RigidBodyImpl>::make(position, self, rigidBodyShadow);
    _rigid_bodies[rigidBody->id()] = rigidBodyShadow;
    insert(rigidBody);
    return rigidBody;
}

const sp<SimpleCollider::RigidBodyShadow>& SimpleCollider::Stub::findRigidBody(uint32_t id) const
{
    const auto iter = _rigid_bodies.find(id);
    DCHECK(iter != _rigid_bodies.end(), "RigidBody(id = %d) does not exists", id);
    return iter->second;
}

SimpleCollider::RigidBodyImpl::RigidBodyImpl(const sp<VV>& position, const sp<Stub>& collider, const sp<RigidBodyShadow>& shadow)
    : RigidBody(shadow->id(), shadow->type(), shadow->shape(), position, shadow->size(), Null::ptr<Numeric>()), _collider(collider), _shadow(shadow)
{
}

SimpleCollider::RigidBodyImpl::~RigidBodyImpl()
{
    if(_id > 0)
        _collider->remove(*this);
}

void SimpleCollider::RigidBodyImpl::beginContact(const sp<RigidBody>& rigidBody)
{
    if(_shadow->collisionCallback())
        _shadow->collisionCallback()->onBeginContact(rigidBody);
}

void SimpleCollider::RigidBodyImpl::endContact(const sp<RigidBody>& rigidBody)
{
    if(_shadow->collisionCallback())
        _shadow->collisionCallback()->onEndContact(rigidBody);
}

const sp<CollisionCallback>& SimpleCollider::RigidBodyImpl::collisionCallback() const
{
    return _shadow->collisionCallback();
}

void SimpleCollider::RigidBodyImpl::setCollisionCallback(const sp<CollisionCallback>& collisionCallback)
{
    _shadow->setCollisionCallback(collisionCallback);
}

void SimpleCollider::RigidBodyImpl::dispose()
{
    DCHECK(_id != 0, "RigidBody has been disposed already.");
    _collider->remove(*this);
    _id = 0;
}

void SimpleCollider::RigidBodyImpl::setPosition(const sp<VV>& position)
{
    _position = position;
}

void SimpleCollider::RigidBodyImpl::collision(const Rect& rect)
{
    std::set<uint32_t> candidates;
    std::set<uint32_t> contacts = _contacts;
    const std::set<uint32_t> x = _collider->_x_axis_segment.findCandidates(rect.left(), rect.right());
    if(x.size())
    {
        const std::set<uint32_t> y = _collider->_y_axis_segment.findCandidates(rect.top(), rect.bottom());
        std::set_intersection(x.begin(), x.end(), y.begin(), y.end(), std::inserter(candidates, candidates.begin()));
        for(auto iter = candidates.begin(); iter != candidates.end();)
        {
            uint32_t id = *iter;
            if(id == _id)
            {
                iter = candidates.erase(iter);
                continue;
            }
            const sp<RigidBodyShadow>& rigidBody = _collider->findRigidBody(id);
            const sp<Size>& size = rigidBody->size();
            const V position = rigidBody->xy();
            const Rect irect(position.x() - size->width() / 2, position.y() - size->height() / 2, position.x() + size->width() / 2, position.y() + size->height() / 2);
            bool overlap = irect.overlap(rect);
            if(overlap)
            {
                auto iter2 = contacts.find(id);
                if(iter2 == contacts.end())
                    beginContact(rigidBody);
                else
                    contacts.erase(iter2);
                ++iter;
            }
            else
                iter = candidates.erase(iter);
        }
        for(uint32_t i : contacts)
        {
            if(candidates.find(i) == candidates.end())
                endContact(_collider->findRigidBody(i));
        }
        _contacts = candidates;
    }
}

void SimpleCollider::RigidBodyImpl::update()
{
    const V pos = _position->val();
    _shadow->setPosition(pos);
    _collider->_x_axis_segment.update(_id, pos.x(), _size->width());
    _collider->_y_axis_segment.update(_id, pos.y(), _size->height());
}

SimpleCollider::RigidBodyShadow::RigidBodyShadow(uint32_t id, Collider::BodyType type, Collider::BodyShape shape, const sp<VV>& pos, const sp<Size>& size)
    : RigidBody(id, type, shape, sp<VV::Impl>::make(pos->val()), size, nullptr)
{
    _position = static_cast<sp<VV::Impl>>(position());
}

void SimpleCollider::RigidBodyShadow::dispose()
{
    FATAL("RigidBody may not be disposed");
}

const sp<CollisionCallback>& SimpleCollider::RigidBodyShadow::collisionCallback() const
{
    return _collision_callback;
}

void SimpleCollider::RigidBodyShadow::setCollisionCallback(const sp<CollisionCallback>& collisionCallback)
{
    _collision_callback = collisionCallback;
}

void SimpleCollider::RigidBodyShadow::setPosition(const V& pos)
{
    _position->set(pos);
}

}
<|endoftext|>


<commit_before>#include "batch.h"
#include "../accumulator.h"
#include "../sampler.h"
#include "../util/logger.h"
#include "../util/log_search.hpp"
#include "../util/timer.h"
#include "../thread/thread.h"
#include "../minimize.h"

namespace ncv
{
        namespace detail
        {
                ///
                /// \brief restore the original sampler at destruction
                ///
                struct sampler_backup_t
                {
                        sampler_backup_t(trainer_data_t& data, size_t tsize)
                                :       m_data(data),
                                        m_tsampler_orig(data.m_tsampler)
                        {
                                // FIXED random subset of training samples
                                data.m_tsampler.setup(sampler_t::stype::uniform, tsize);
                                data.m_tsampler = sampler_t(data.m_tsampler.get());
                        }

                        ~sampler_backup_t()
                        {
                                m_data.m_tsampler = m_tsampler_orig;
                        }

                        trainer_data_t&         m_data;
                        const sampler_t         m_tsampler_orig;
                };

                static scalar_t tune(
                        trainer_data_t& data,
                        batch_optimizer optimizer,
                        size_t batch, size_t iterations, scalar_t epsilon)
                {
                        const size_t epochs = 1;
                        const size_t epoch_size = (data.m_tsampler.size() + batch - 1) / batch;

                        // construct the optimization problem
                        auto fn_size = ncv::make_opsize(data);
                        auto fn_fval = ncv::make_opfval(data);
                        auto fn_grad = ncv::make_opgrad(data);

                        auto fn_wlog = nullptr;
                        auto fn_elog = nullptr;
                        auto fn_ulog = nullptr;

                        // optimize the model
                        vector_t x = data.m_x0;

                        for (size_t epoch = 1; epoch <= epochs; epoch ++)
                        {
                                for (size_t i = 0; i < epoch_size; i ++)
                                {
                                        const sampler_backup_t sampler_data(data, batch);

                                        const opt_state_t state = ncv::minimize(
                                                fn_size, fn_fval, fn_grad, fn_wlog, fn_elog, fn_ulog,
                                                x, optimizer, iterations, epsilon);

                                        x = state.x;
                                }
                        }

                        // OK, cumulate the loss value
                        data.m_lacc.reset(x);
                        data.m_lacc.update(data.m_task, data.m_tsampler.all(), data.m_loss);
                        return data.m_lacc.value();
                }

                static trainer_result_t train(
                        trainer_data_t& data,
                        batch_optimizer optimizer,
                        size_t epochs, size_t batch, size_t iterations, scalar_t epsilon, bool verbose)
                {
                        trainer_result_t result;

                        const ncv::timer_t timer;

                        const size_t epoch_size = (data.m_tsampler.size() + batch - 1) / batch;

                        // construct the optimization problem
                        auto fn_size = ncv::make_opsize(data);
                        auto fn_fval = ncv::make_opfval(data);
                        auto fn_grad = ncv::make_opgrad(data);

                        auto fn_wlog = verbose ? ncv::make_opwlog() : nullptr;
                        auto fn_elog = verbose ? ncv::make_opelog() : nullptr;
                        auto fn_ulog = nullptr;

                        // optimize the model
                        vector_t x = data.m_x0;

                        for (size_t epoch = 1; epoch <= epochs; epoch ++)
                        {
                                for (size_t i = 0; i < epoch_size; i ++)
                                {
                                        const sampler_backup_t sampler_data(data, batch);

                                        const opt_state_t state = ncv::minimize(
                                                fn_size, fn_fval, fn_grad, fn_wlog, fn_elog, fn_ulog,
                                                x, optimizer, iterations, epsilon);

                                        x = state.x;
                                }

                                // training samples: loss value
                                data.m_lacc.reset(x);
                                data.m_lacc.update(data.m_task, data.m_tsampler.all(), data.m_loss);
                                const scalar_t tvalue = data.m_lacc.value();
                                const scalar_t terror_avg = data.m_lacc.avg_error();
                                const scalar_t terror_var = data.m_lacc.var_error();

                                // validation samples: loss value
                                data.m_lacc.reset(x);
                                data.m_lacc.update(data.m_task, data.m_vsampler.get(), data.m_loss);
                                const scalar_t vvalue = data.m_lacc.value();
                                const scalar_t verror_avg = data.m_lacc.avg_error();
                                const scalar_t verror_var = data.m_lacc.var_error();

                                // update the optimum state
                                result.update(x, tvalue, terror_avg, terror_var, vvalue, verror_avg, verror_var,
                                              epoch, scalars_t({ static_cast<scalar_t>(batch),
                                                                 static_cast<scalar_t>(iterations),
                                                                 data.m_lacc.lambda() }));

                                if (verbose)
                                log_info()
                                        << "[train = " << tvalue << "/" << terror_avg
                                        << ", valid = " << vvalue << "/" << verror_avg
                                        << ", xnorm = " << x.lpNorm<Eigen::Infinity>()
                                        << ", epoch = " << epoch << "/" << epochs
                                        << ", batch = " << batch
                                        << ", iters = " << iterations
                                        << ", lambda = " << data.m_lacc.lambda()
                                        << "] done in " << timer.elapsed() << ".";
                        }

                        return result;
                }
        }

        trainer_result_t minibatch_train(
                const model_t& model, const task_t& task, const sampler_t& tsampler, const sampler_t& vsampler, size_t nthreads,
                const loss_t& loss, const string_t& criterion,
                batch_optimizer optimizer, size_t epochs, scalar_t epsilon,
                bool verbose)
        {
                vector_t x0;
                model.save_params(x0);

                // operator to train for a given regularization factor
                const auto op = [&] (scalar_t lambda)
                {
                        accumulator_t lacc(model, nthreads, criterion, criterion_t::type::value, lambda);
                        accumulator_t gacc(model, nthreads, criterion, criterion_t::type::vgrad, lambda);

                        trainer_data_t data(task, tsampler, vsampler, loss, x0, lacc, gacc);

                        const size_t min_batch = 16 * ncv::n_threads();
                        const size_t max_batch = 16 * min_batch;

                        const indices_t batch_iterations = { 4, 8 };

                        scalar_t opt_state = std::numeric_limits<scalar_t>::max();
                        size_t opt_batch = min_batch;
                        size_t opt_iterations = 4;

                        // tune the batch size and the number of optimization iterations per batch
                        for (size_t batch = min_batch; batch <= max_batch; batch *= 2)
                        {
                                for (size_t iterations : batch_iterations)
                                {
                                        const ncv::timer_t timer;

                                        const scalar_t state =
                                                detail::tune(data, optimizer, batch, iterations, epsilon);

                                        if (verbose)
                                        log_info()
                                                << "[tuning: loss = " << state
                                                << ", batch = " << batch
                                                << ", iters = " << iterations
                                                << ", lambda = " << data.m_lacc.lambda()
                                                << "] done in " << timer.elapsed() << ".";

                                        if (state < opt_state)
                                        {
                                                opt_state = state;
                                                opt_batch = batch;
                                                opt_iterations = iterations;
                                        }
                                }
                        }

                        // train the model using the tuned parameters
                        return detail::train(data, optimizer, epochs, opt_batch, opt_iterations, epsilon, verbose);
                };

                // tune the regularization factor (if needed)
                if (accumulator_t::can_regularize(criterion))
                {
                        return log10_min_search(op, -4.0, +4.0, 0.2, 4).first;
                }

                else
                {
                        return op(0.0);
                }
        }
}

<commit_msg>faster minibatch: save copying the training samples<commit_after>#include "batch.h"
#include "../accumulator.h"
#include "../sampler.h"
#include "../util/logger.h"
#include "../util/log_search.hpp"
#include "../util/timer.h"
#include "../thread/thread.h"
#include "../minimize.h"

namespace ncv
{
        namespace detail
        {
                static void setup_minibatch(sampler_t& orig_tsampler, size_t tsize, trainer_data_t& data)
                {
                        // FIXED random subset of training samples
                        orig_tsampler.setup(sampler_t::stype::uniform, tsize);
                        data.m_tsampler = sampler_t(orig_tsampler.get());
                }

                static void reset_minibatch(sampler_t& orig_tsampler, trainer_data_t& data)
                {
                        // all available training samples
                        orig_tsampler.setup(sampler_t::stype::batch);
                        data.m_tsampler = orig_tsampler;
                }

                template
                <
                        typename toperator
                >
                static void train(trainer_data_t& data, size_t epoch_size, size_t batch, const toperator& op)
                {
                        sampler_t orig_tsampler = data.m_tsampler;

                        for (size_t i = 0; i < epoch_size; i ++)
                        {
                                setup_minibatch(orig_tsampler, batch, data);

                                op();
                        }

                        reset_minibatch(orig_tsampler, data);
                }

                static scalar_t tune(
                        trainer_data_t& data,
                        batch_optimizer optimizer,
                        size_t batch, size_t iterations, scalar_t epsilon)
                {
                        const size_t epochs = 1;
                        const size_t epoch_size = (data.m_tsampler.size() + batch - 1) / batch;

                        // construct the optimization problem
                        auto fn_size = ncv::make_opsize(data);
                        auto fn_fval = ncv::make_opfval(data);
                        auto fn_grad = ncv::make_opgrad(data);

                        auto fn_wlog = nullptr;
                        auto fn_elog = nullptr;
                        auto fn_ulog = nullptr;

                        // optimize the model
                        vector_t x = data.m_x0;

                        for (size_t epoch = 1; epoch <= epochs; epoch ++)
                        {
                                train(data, epoch_size, batch, [&] ()
                                {
                                        const opt_state_t state = ncv::minimize(
                                                fn_size, fn_fval, fn_grad, fn_wlog, fn_elog, fn_ulog,
                                                x, optimizer, iterations, epsilon);

                                        x = state.x;
                                });
                        }

                        // OK, cumulate the loss value
                        data.m_lacc.reset(x);
                        data.m_lacc.update(data.m_task, data.m_tsampler.all(), data.m_loss);
                        return data.m_lacc.value();
                }

                static trainer_result_t train(
                        trainer_data_t& data,
                        batch_optimizer optimizer,
                        size_t epochs, size_t batch, size_t iterations, scalar_t epsilon, bool verbose)
                {
                        const ncv::timer_t timer;

                        const size_t epoch_size = (data.m_tsampler.size() + batch - 1) / batch;

                        trainer_result_t result;

                        // construct the optimization problem
                        auto fn_size = ncv::make_opsize(data);
                        auto fn_fval = ncv::make_opfval(data);
                        auto fn_grad = ncv::make_opgrad(data);

                        auto fn_wlog = verbose ? ncv::make_opwlog() : nullptr;
                        auto fn_elog = verbose ? ncv::make_opelog() : nullptr;
                        auto fn_ulog = nullptr;

                        // optimize the model
                        vector_t x = data.m_x0;

                        for (size_t epoch = 1; epoch <= epochs; epoch ++)
                        {
                                train(data, epoch_size, batch, [&] ()
                                {
                                        const opt_state_t state = ncv::minimize(
                                                fn_size, fn_fval, fn_grad, fn_wlog, fn_elog, fn_ulog,
                                                x, optimizer, iterations, epsilon);

                                        x = state.x;
                                });

                                // training samples: loss value
                                data.m_lacc.reset(x);
                                data.m_lacc.update(data.m_task, data.m_tsampler.all(), data.m_loss);
                                const scalar_t tvalue = data.m_lacc.value();
                                const scalar_t terror_avg = data.m_lacc.avg_error();
                                const scalar_t terror_var = data.m_lacc.var_error();

                                // validation samples: loss value
                                data.m_lacc.reset(x);
                                data.m_lacc.update(data.m_task, data.m_vsampler.get(), data.m_loss);
                                const scalar_t vvalue = data.m_lacc.value();
                                const scalar_t verror_avg = data.m_lacc.avg_error();
                                const scalar_t verror_var = data.m_lacc.var_error();

                                // update the optimum state
                                result.update(x, tvalue, terror_avg, terror_var, vvalue, verror_avg, verror_var,
                                              epoch, scalars_t({ static_cast<scalar_t>(batch),
                                                                 static_cast<scalar_t>(iterations),
                                                                 data.m_lacc.lambda() }));

                                if (verbose)
                                log_info()
                                        << "[train = " << tvalue << "/" << terror_avg
                                        << ", valid = " << vvalue << "/" << verror_avg
                                        << ", xnorm = " << x.lpNorm<Eigen::Infinity>()
                                        << ", epoch = " << epoch << "/" << epochs
                                        << ", batch = " << batch
                                        << ", iters = " << iterations
                                        << ", lambda = " << data.m_lacc.lambda()
                                        << "] done in " << timer.elapsed() << ".";
                        }

                        return result;
                }
        }

        trainer_result_t minibatch_train(
                const model_t& model, const task_t& task, const sampler_t& tsampler, const sampler_t& vsampler, size_t nthreads,
                const loss_t& loss, const string_t& criterion,
                batch_optimizer optimizer, size_t epochs, scalar_t epsilon,
                bool verbose)
        {
                vector_t x0;
                model.save_params(x0);

                // operator to train for a given regularization factor
                const auto op = [&] (scalar_t lambda)
                {
                        accumulator_t lacc(model, nthreads, criterion, criterion_t::type::value, lambda);
                        accumulator_t gacc(model, nthreads, criterion, criterion_t::type::vgrad, lambda);

                        trainer_data_t data(task, tsampler, vsampler, loss, x0, lacc, gacc);

                        const size_t min_batch = 16 * ncv::n_threads();
                        const size_t max_batch = 16 * min_batch;

                        const indices_t batch_iterations = { 4, 8 };

                        scalar_t opt_state = std::numeric_limits<scalar_t>::max();
                        size_t opt_batch = min_batch;
                        size_t opt_iterations = 4;

                        // tune the batch size and the number of optimization iterations per batch
                        for (size_t batch = min_batch; batch <= max_batch; batch *= 2)
                        {
                                for (size_t iterations : batch_iterations)
                                {
                                        const ncv::timer_t timer;

                                        const scalar_t state =
                                                detail::tune(data, optimizer, batch, iterations, epsilon);

                                        if (verbose)
                                        log_info()
                                                << "[tuning: loss = " << state
                                                << ", batch = " << batch
                                                << ", iters = " << iterations
                                                << ", lambda = " << data.m_lacc.lambda()
                                                << "] done in " << timer.elapsed() << ".";

                                        if (state < opt_state)
                                        {
                                                opt_state = state;
                                                opt_batch = batch;
                                                opt_iterations = iterations;
                                        }
                                }
                        }

                        // train the model using the tuned parameters
                        return detail::train(data, optimizer, epochs, opt_batch, opt_iterations, epsilon, verbose);
                };

                // tune the regularization factor (if needed)
                if (accumulator_t::can_regularize(criterion))
                {
                        return log10_min_search(op, -4.0, +4.0, 0.2, 4).first;
                }

                else
                {
                        return op(0.0);
                }
        }
}

<|endoftext|>