<commit_before>// Copyright (C) 2011, 2012  Strahinja Val Markovic  <val@markovic.io>
//
// This file is part of YouCompleteMe.
//
// YouCompleteMe is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// YouCompleteMe 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with YouCompleteMe.  If not, see <http://www.gnu.org/licenses/>.

#include "TranslationUnit.h"
#include "CompletionData.h"
#include "standard.h"
#include "exceptions.h"
#include "ClangUtils.h"

#include <boost/shared_ptr.hpp>
#include <boost/type_traits/remove_pointer.hpp>

using boost::unique_lock;
using boost::mutex;
using boost::try_to_lock_t;
using boost::shared_ptr;
using boost::remove_pointer;

namespace YouCompleteMe {

typedef shared_ptr <
remove_pointer< CXCodeCompleteResults >::type > CodeCompleteResultsWrap;

TranslationUnit::TranslationUnit()
  : filename_( "" ),
    clang_translation_unit_( NULL ) {
}

TranslationUnit::TranslationUnit(
  const std::string &filename,
  const std::vector< UnsavedFile > &unsaved_files,
  const std::vector< std::string > &flags,
  CXIndex clang_index )
  : filename_( filename ),
    clang_translation_unit_( NULL ) {
  std::vector< const char * > pointer_flags;
  pointer_flags.reserve( flags.size() );

  foreach ( const std::string & flag, flags ) {
    pointer_flags.push_back( flag.c_str() );
  }

  std::vector< CXUnsavedFile > cxunsaved_files =
    ToCXUnsavedFiles( unsaved_files );

  clang_translation_unit_ = clang_parseTranslationUnit(
                              clang_index,
                              filename.c_str(),
                              &pointer_flags[ 0 ],
                              pointer_flags.size(),
                              &cxunsaved_files[ 0 ],
                              cxunsaved_files.size(),
                              clang_defaultEditingTranslationUnitOptions() );

  if ( !clang_translation_unit_ )
    boost_throw( ClangParseError() );

  // Only with a reparse is the preable precompiled. I do not know why...
  // TODO: report this bug on the clang tracker
  Reparse( cxunsaved_files );
}

TranslationUnit::~TranslationUnit() {
  Destroy();
}

void TranslationUnit::Destroy() {
  unique_lock< mutex > lock( clang_access_mutex_ );

  if ( clang_translation_unit_ ) {
    clang_disposeTranslationUnit( clang_translation_unit_ );
    clang_translation_unit_ = NULL;
  }
}

std::vector< Diagnostic > TranslationUnit::LatestDiagnostics() {
  std::vector< Diagnostic > diagnostics;

  if ( !clang_translation_unit_ )
    return diagnostics;

  unique_lock< mutex > lock( diagnostics_mutex_ );

  // We don't need the latest diags after we return them once so we swap the
  // internal data with a new, empty diag vector. This vector is then returned
  // and on C++11 compilers a move ctor is invoked, thus no copy is created.
  // Theoretically, just returning the value of a
  // [boost::|std::]move(latest_diagnostics_) call _should_ leave the
  // latest_diagnostics_ vector in an emtpy, valid state but I'm not going to
  // rely on that. I just had to look this up in the standard to be sure, and
  // future readers of this code (myself included) should not be forced to do
  // that to understand what the hell is going on.

  std::swap( latest_diagnostics_, diagnostics );
  return diagnostics;
}

bool TranslationUnit::IsCurrentlyUpdating() const {
  // We return true when the TU is invalid; an invalid TU also acts a sentinel,
  // preventing other threads from trying to use it.
  if ( !clang_translation_unit_ )
    return true;

  unique_lock< mutex > lock( clang_access_mutex_, try_to_lock_t() );
  return !lock.owns_lock();
}

void TranslationUnit::Reparse(
  const std::vector< UnsavedFile > &unsaved_files ) {
  std::vector< CXUnsavedFile > cxunsaved_files =
    ToCXUnsavedFiles( unsaved_files );

  Reparse( cxunsaved_files );
}

void TranslationUnit::ReparseForIndexing(
  const std::vector< UnsavedFile > &unsaved_files ) {
  std::vector< CXUnsavedFile > cxunsaved_files =
    ToCXUnsavedFiles( unsaved_files );

  Reparse( cxunsaved_files,
           CXTranslationUnit_PrecompiledPreamble |
           CXTranslationUnit_SkipFunctionBodies );
}

std::vector< CompletionData > TranslationUnit::CandidatesForLocation(
  int line,
  int column,
  const std::vector< UnsavedFile > &unsaved_files ) {
  unique_lock< mutex > lock( clang_access_mutex_ );

  if ( !clang_translation_unit_ )
    return std::vector< CompletionData >();

  std::vector< CXUnsavedFile > cxunsaved_files =
    ToCXUnsavedFiles( unsaved_files );

  // codeCompleteAt reparses the TU if the underlying source file has changed on
  // disk since the last time the TU was updated and there are no unsaved files.
  // If there are unsaved files, then codeCompleteAt will parse the in-memory
  // file contents we are giving it. In short, it is NEVER a good idea to call
  // clang_reparseTranslationUnit right before a call to clang_codeCompleteAt.
  // This only makes clang reparse the whole file TWICE, which has a huge impact
  // on latency. At the time of writing, it seems that most users of libclang
  // in the open-source world don't realize this (I checked). Some don't even
  // call reparse*, but parse* which is even less efficient.

  CodeCompleteResultsWrap results(
    clang_codeCompleteAt( clang_translation_unit_,
                          filename_.c_str(),
                          line,
                          column,
                          &cxunsaved_files[ 0 ],
                          cxunsaved_files.size(),
                          clang_defaultCodeCompleteOptions() ),
    clang_disposeCodeCompleteResults );

  std::vector< CompletionData > candidates = ToCompletionDataVector(
                                               results.get() );
  return candidates;
}

Location TranslationUnit::GetDeclarationLocation(
  int line,
  int column,
  const std::vector< UnsavedFile > &unsaved_files ) {
  ReparseForIndexing( unsaved_files );
  unique_lock< mutex > lock( clang_access_mutex_ );

  if ( !clang_translation_unit_ )
    return Location();

  CXCursor cursor = GetCursor( line, column );

  if ( !CursorIsValid( cursor ) )
    return Location();

  CXCursor referenced_cursor = clang_getCursorReferenced( cursor );

  if ( !CursorIsValid( referenced_cursor ) )
    return Location();

  return LocationFromSourceLocation(
           clang_getCursorLocation( referenced_cursor ) );
}

Location TranslationUnit::GetDefinitionLocation(
  int line,
  int column,
  const std::vector< UnsavedFile > &unsaved_files ) {
  ReparseForIndexing( unsaved_files );
  unique_lock< mutex > lock( clang_access_mutex_ );

  if ( !clang_translation_unit_ )
    return Location();

  CXCursor cursor = GetCursor( line, column );

  if ( !CursorIsValid( cursor ) )
    return Location();

  CXCursor definition_cursor = clang_getCursorDefinition( cursor );

  if ( !CursorIsValid( definition_cursor ) )
    return Location();

  return LocationFromSourceLocation(
           clang_getCursorLocation( definition_cursor ) );
}

// Argument taken as non-const ref because we need to be able to pass a
// non-const pointer to clang. This function (and clang too) will not modify the
// param though.
void TranslationUnit::Reparse(
  std::vector< CXUnsavedFile > &unsaved_files ) {
  Reparse( unsaved_files, clang_defaultEditingTranslationUnitOptions() );
}

// Argument taken as non-const ref because we need to be able to pass a
// non-const pointer to clang. This function (and clang too) will not modify the
// param though.
void TranslationUnit::Reparse( std::vector< CXUnsavedFile > &unsaved_files,
                               uint parse_options ) {
  unique_lock< mutex > lock( clang_access_mutex_ );

  if ( !clang_translation_unit_ )
    return;

  int failure = clang_reparseTranslationUnit( clang_translation_unit_,
                                              unsaved_files.size(),
                                              &unsaved_files[ 0 ],
                                              parse_options );

  if ( failure ) {
    Destroy();
    boost_throw( ClangParseError() );
  }

  UpdateLatestDiagnostics();
}

// Should only be called while holding the clang_access_mutex_
void TranslationUnit::UpdateLatestDiagnostics() {
  unique_lock< mutex > lock( diagnostics_mutex_ );

  latest_diagnostics_.clear();
  uint num_diagnostics = clang_getNumDiagnostics( clang_translation_unit_ );
  latest_diagnostics_.reserve( num_diagnostics );

  for ( uint i = 0; i < num_diagnostics; ++i ) {
    Diagnostic diagnostic =
      DiagnosticWrapToDiagnostic(
        DiagnosticWrap( clang_getDiagnostic( clang_translation_unit_, i ),
                        clang_disposeDiagnostic ) );

    if ( diagnostic.kind_ != 'I' )
      latest_diagnostics_.push_back( diagnostic );
  }
}

CXCursor TranslationUnit::GetCursor( int line, int column ) {
  // ASSUMES A LOCK IS ALREADY HELD ON clang_access_mutex_!
  if ( !clang_translation_unit_ )
    return clang_getNullCursor();

  CXFile file = clang_getFile( clang_translation_unit_, filename_.c_str() );
  CXSourceLocation source_location = clang_getLocation(
                                       clang_translation_unit_,
                                       file,
                                       line,
                                       column );

  return clang_getCursor( clang_translation_unit_, source_location );
}

Location TranslationUnit::LocationFromSourceLocation(
  CXSourceLocation source_location ) {
  // ASSUMES A LOCK IS ALREADY HELD ON clang_access_mutex_!
  if ( !clang_translation_unit_ )
    return Location();

  CXFile file;
  uint line;
  uint column;
  uint offset;
  clang_getExpansionLocation( source_location, &file, &line, &column, &offset );
  return Location( CXFileToFilepath( file ), line, column );
}

} // namespace YouCompleteMe
<commit_msg>Possible fix for random hang on Vim close<commit_after>// Copyright (C) 2011, 2012  Strahinja Val Markovic  <val@markovic.io>
//
// This file is part of YouCompleteMe.
//
// YouCompleteMe is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// YouCompleteMe 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with YouCompleteMe.  If not, see <http://www.gnu.org/licenses/>.

#include "TranslationUnit.h"
#include "CompletionData.h"
#include "standard.h"
#include "exceptions.h"
#include "ClangUtils.h"

#include <boost/shared_ptr.hpp>
#include <boost/type_traits/remove_pointer.hpp>

using boost::unique_lock;
using boost::mutex;
using boost::try_to_lock_t;
using boost::shared_ptr;
using boost::remove_pointer;

namespace YouCompleteMe {

typedef shared_ptr <
remove_pointer< CXCodeCompleteResults >::type > CodeCompleteResultsWrap;

TranslationUnit::TranslationUnit()
  : filename_( "" ),
    clang_translation_unit_( NULL ) {
}

TranslationUnit::TranslationUnit(
  const std::string &filename,
  const std::vector< UnsavedFile > &unsaved_files,
  const std::vector< std::string > &flags,
  CXIndex clang_index )
  : filename_( filename ),
    clang_translation_unit_( NULL ) {
  std::vector< const char * > pointer_flags;
  pointer_flags.reserve( flags.size() );

  foreach ( const std::string & flag, flags ) {
    pointer_flags.push_back( flag.c_str() );
  }

  std::vector< CXUnsavedFile > cxunsaved_files =
    ToCXUnsavedFiles( unsaved_files );

  clang_translation_unit_ = clang_parseTranslationUnit(
                              clang_index,
                              filename.c_str(),
                              &pointer_flags[ 0 ],
                              pointer_flags.size(),
                              &cxunsaved_files[ 0 ],
                              cxunsaved_files.size(),
                              clang_defaultEditingTranslationUnitOptions() );

  if ( !clang_translation_unit_ )
    boost_throw( ClangParseError() );

  // Only with a reparse is the preable precompiled. I do not know why...
  // TODO: report this bug on the clang tracker
  Reparse( cxunsaved_files );
}

TranslationUnit::~TranslationUnit() {
  Destroy();
}

void TranslationUnit::Destroy() {
  unique_lock< mutex > lock( clang_access_mutex_ );

  if ( clang_translation_unit_ ) {
    clang_disposeTranslationUnit( clang_translation_unit_ );
    clang_translation_unit_ = NULL;
  }
}

std::vector< Diagnostic > TranslationUnit::LatestDiagnostics() {
  std::vector< Diagnostic > diagnostics;

  if ( !clang_translation_unit_ )
    return diagnostics;

  unique_lock< mutex > lock( diagnostics_mutex_ );

  // We don't need the latest diags after we return them once so we swap the
  // internal data with a new, empty diag vector. This vector is then returned
  // and on C++11 compilers a move ctor is invoked, thus no copy is created.
  // Theoretically, just returning the value of a
  // [boost::|std::]move(latest_diagnostics_) call _should_ leave the
  // latest_diagnostics_ vector in an emtpy, valid state but I'm not going to
  // rely on that. I just had to look this up in the standard to be sure, and
  // future readers of this code (myself included) should not be forced to do
  // that to understand what the hell is going on.

  std::swap( latest_diagnostics_, diagnostics );
  return diagnostics;
}

bool TranslationUnit::IsCurrentlyUpdating() const {
  // We return true when the TU is invalid; an invalid TU also acts a sentinel,
  // preventing other threads from trying to use it.
  if ( !clang_translation_unit_ )
    return true;

  unique_lock< mutex > lock( clang_access_mutex_, try_to_lock_t() );
  return !lock.owns_lock();
}

void TranslationUnit::Reparse(
  const std::vector< UnsavedFile > &unsaved_files ) {
  std::vector< CXUnsavedFile > cxunsaved_files =
    ToCXUnsavedFiles( unsaved_files );

  Reparse( cxunsaved_files );
}

void TranslationUnit::ReparseForIndexing(
  const std::vector< UnsavedFile > &unsaved_files ) {
  std::vector< CXUnsavedFile > cxunsaved_files =
    ToCXUnsavedFiles( unsaved_files );

  Reparse( cxunsaved_files,
           CXTranslationUnit_PrecompiledPreamble |
           CXTranslationUnit_SkipFunctionBodies );
}

std::vector< CompletionData > TranslationUnit::CandidatesForLocation(
  int line,
  int column,
  const std::vector< UnsavedFile > &unsaved_files ) {
  unique_lock< mutex > lock( clang_access_mutex_ );

  if ( !clang_translation_unit_ )
    return std::vector< CompletionData >();

  std::vector< CXUnsavedFile > cxunsaved_files =
    ToCXUnsavedFiles( unsaved_files );

  // codeCompleteAt reparses the TU if the underlying source file has changed on
  // disk since the last time the TU was updated and there are no unsaved files.
  // If there are unsaved files, then codeCompleteAt will parse the in-memory
  // file contents we are giving it. In short, it is NEVER a good idea to call
  // clang_reparseTranslationUnit right before a call to clang_codeCompleteAt.
  // This only makes clang reparse the whole file TWICE, which has a huge impact
  // on latency. At the time of writing, it seems that most users of libclang
  // in the open-source world don't realize this (I checked). Some don't even
  // call reparse*, but parse* which is even less efficient.

  CodeCompleteResultsWrap results(
    clang_codeCompleteAt( clang_translation_unit_,
                          filename_.c_str(),
                          line,
                          column,
                          &cxunsaved_files[ 0 ],
                          cxunsaved_files.size(),
                          clang_defaultCodeCompleteOptions() ),
    clang_disposeCodeCompleteResults );

  std::vector< CompletionData > candidates = ToCompletionDataVector(
                                               results.get() );
  return candidates;
}

Location TranslationUnit::GetDeclarationLocation(
  int line,
  int column,
  const std::vector< UnsavedFile > &unsaved_files ) {
  ReparseForIndexing( unsaved_files );
  unique_lock< mutex > lock( clang_access_mutex_ );

  if ( !clang_translation_unit_ )
    return Location();

  CXCursor cursor = GetCursor( line, column );

  if ( !CursorIsValid( cursor ) )
    return Location();

  CXCursor referenced_cursor = clang_getCursorReferenced( cursor );

  if ( !CursorIsValid( referenced_cursor ) )
    return Location();

  return LocationFromSourceLocation(
           clang_getCursorLocation( referenced_cursor ) );
}

Location TranslationUnit::GetDefinitionLocation(
  int line,
  int column,
  const std::vector< UnsavedFile > &unsaved_files ) {
  ReparseForIndexing( unsaved_files );
  unique_lock< mutex > lock( clang_access_mutex_ );

  if ( !clang_translation_unit_ )
    return Location();

  CXCursor cursor = GetCursor( line, column );

  if ( !CursorIsValid( cursor ) )
    return Location();

  CXCursor definition_cursor = clang_getCursorDefinition( cursor );

  if ( !CursorIsValid( definition_cursor ) )
    return Location();

  return LocationFromSourceLocation(
           clang_getCursorLocation( definition_cursor ) );
}

// Argument taken as non-const ref because we need to be able to pass a
// non-const pointer to clang. This function (and clang too) will not modify the
// param though.
void TranslationUnit::Reparse(
  std::vector< CXUnsavedFile > &unsaved_files ) {
  Reparse( unsaved_files, clang_defaultEditingTranslationUnitOptions() );
}

// Argument taken as non-const ref because we need to be able to pass a
// non-const pointer to clang. This function (and clang too) will not modify the
// param though.
void TranslationUnit::Reparse( std::vector< CXUnsavedFile > &unsaved_files,
                               uint parse_options ) {
  int failure = 0;
  {
    unique_lock< mutex > lock( clang_access_mutex_ );

    if ( !clang_translation_unit_ )
      return;

    failure = clang_reparseTranslationUnit( clang_translation_unit_,
                                            unsaved_files.size(),
                                            &unsaved_files[ 0 ],
                                            parse_options );
  }

  if ( failure ) {
    Destroy();
    boost_throw( ClangParseError() );
  }

  UpdateLatestDiagnostics();
}

void TranslationUnit::UpdateLatestDiagnostics() {
  unique_lock< mutex > lock1( clang_access_mutex_ );
  unique_lock< mutex > lock2( diagnostics_mutex_ );

  latest_diagnostics_.clear();
  uint num_diagnostics = clang_getNumDiagnostics( clang_translation_unit_ );
  latest_diagnostics_.reserve( num_diagnostics );

  for ( uint i = 0; i < num_diagnostics; ++i ) {
    Diagnostic diagnostic =
      DiagnosticWrapToDiagnostic(
        DiagnosticWrap( clang_getDiagnostic( clang_translation_unit_, i ),
                        clang_disposeDiagnostic ) );

    if ( diagnostic.kind_ != 'I' )
      latest_diagnostics_.push_back( diagnostic );
  }
}

CXCursor TranslationUnit::GetCursor( int line, int column ) {
  // ASSUMES A LOCK IS ALREADY HELD ON clang_access_mutex_!
  if ( !clang_translation_unit_ )
    return clang_getNullCursor();

  CXFile file = clang_getFile( clang_translation_unit_, filename_.c_str() );
  CXSourceLocation source_location = clang_getLocation(
                                       clang_translation_unit_,
                                       file,
                                       line,
                                       column );

  return clang_getCursor( clang_translation_unit_, source_location );
}

Location TranslationUnit::LocationFromSourceLocation(
  CXSourceLocation source_location ) {
  // ASSUMES A LOCK IS ALREADY HELD ON clang_access_mutex_!
  if ( !clang_translation_unit_ )
    return Location();

  CXFile file;
  uint line;
  uint column;
  uint offset;
  clang_getExpansionLocation( source_location, &file, &line, &column, &offset );
  return Location( CXFileToFilepath( file ), line, column );
}

} // namespace YouCompleteMe
<|endoftext|>


<commit_before>#ifndef __CALLBACK_OBJECT_HPP_INCLUDED
#define __CALLBACK_OBJECT_HPP_INCLUDED

#include "cpp/ylikuutio/common/any_value.hpp"
#include "callback_engine.hpp"
#include "callback_parameter.hpp"
#include "cpp/ylikuutio/common/globals.hpp"

// Include standard headers
#include <cmath>         // NAN
#include <string>        // std::string
#include <unordered_map> // std::unordered_map
#include <vector>        // std::vector

namespace callback_system
{
    class CallbackObject
    {
        // CallbackObject is an object that contains a single callback.

        public:
            // constructor.
            CallbackObject(callback_system::CallbackEngine* callback_engine_pointer);

            // constructor.
            CallbackObject(InputParametersToAnyValueCallback callback, callback_system::CallbackEngine* callback_engine_pointer);

            // destructor.
            ~CallbackObject();

            // add reference to an input variable.
            // this does not store the value to an appropriate hashmap.
            // storing the value must be done before or after this call.
            // each type has its own namespace!
            // void add_input_parameter(std::string name, AnyValue any_value, bool is_reference);

            friend class CallbackEngine;

        private:
            // execute this callback.
            AnyValue execute();

            // this method sets a callback parameter pointer.
            void set_callback_parameter_pointer(uint32_t childID, void* parent_pointer);

            callback_system::CallbackEngine* callback_engine_pointer; // pointer to the callback engine.

            void bind_to_parent();

            uint32_t childID;                     // callback object ID, returned by `callback_system::CallbackEngine->get_callback_objectID()`.

            std::string output_type;
            std::string output_variable_name;
            std::vector<callback_system::CallbackParameter*> callback_parameter_pointer_vector;

            InputParametersToAnyValueCallback callback;
    };
}

#endif
<commit_msg>`std::vector<void*> callback_parameter_vector`.<commit_after>#ifndef __CALLBACK_OBJECT_HPP_INCLUDED
#define __CALLBACK_OBJECT_HPP_INCLUDED

#include "cpp/ylikuutio/common/any_value.hpp"
#include "callback_engine.hpp"
#include "callback_parameter.hpp"
#include "cpp/ylikuutio/common/globals.hpp"

// Include standard headers
#include <cmath>         // NAN
#include <string>        // std::string
#include <unordered_map> // std::unordered_map
#include <vector>        // std::vector

namespace callback_system
{
    class CallbackObject
    {
        // CallbackObject is an object that contains a single callback.

        public:
            // constructor.
            CallbackObject(callback_system::CallbackEngine* callback_engine_pointer);

            // constructor.
            CallbackObject(InputParametersToAnyValueCallback callback, callback_system::CallbackEngine* callback_engine_pointer);

            // destructor.
            ~CallbackObject();

            // add reference to an input variable.
            // this does not store the value to an appropriate hashmap.
            // storing the value must be done before or after this call.
            // each type has its own namespace!
            // void add_input_parameter(std::string name, AnyValue any_value, bool is_reference);

            friend class CallbackEngine;

        private:
            // execute this callback.
            AnyValue execute();

            // this method sets a callback parameter pointer.
            void set_callback_parameter_pointer(uint32_t childID, void* parent_pointer);

            callback_system::CallbackEngine* callback_engine_pointer; // pointer to the callback engine.

            void bind_to_parent();

            uint32_t childID;                     // callback object ID, returned by `callback_system::CallbackEngine->get_callback_objectID()`.

            std::vector<void*> callback_parameter_vector;

            std::string output_type;
            std::string output_variable_name;
            std::vector<callback_system::CallbackParameter*> callback_parameter_pointer_vector;

            InputParametersToAnyValueCallback callback;
    };
}

#endif
<|endoftext|>


<commit_before>/* coding: utf-8
 *
 */
#include <xpcc/architecture/platform.hpp>
#include <avr/sleep.h>
#include <avr/power.h>

#define UART_ENABLED 0

// IO #########################################################################
//
//                     +------------+
// (MOTION/INT1) PD3  1|o           |24  PC1
//               PD4  2|            |23  PC0 (ADC0/VOLTAGE)
//               GND  3|            |22  ADC7
//               VCC  4|            |21  GND
//               GND  5|            |20  AREF
//               VCC  6|            |19  ADC6
//       (XLAT1) PB6  7|            |18  AVCC
//       (XLAT2) PB7  8|            |17  PB5 (SCK)
//                     +------------+
//
//                     +------------+
//              PD5   9|           o|32  PD2 (BUTTON/INT0)
//       (XLAT) PD6  10|            |31  PD1 (TXD)
//      (BLANK) PD7  11|            |30  PD0 (RXD)
//      (GSCLK) PB0  12|            |29  PC6 (RESET)
//              PB1  13|            |28  PC5
//      (VPROG) PB2  14|            |27  PC4
//       (MOSI) PB3  15|            |26  PC3
//       (MISO) PB4  16|            |25  PC2
//                     +------------+

GPIO__INPUT(RXD, D, 0);
GPIO__OUTPUT(TXD, D, 1);

GPIO__INPUT(BUTTON, D, 2);
GPIO__INPUT(MOTION, D, 3);

GPIO__OUTPUT(VPROG, B, 2);
GPIO__OUTPUT(XLAT, D, 6);
GPIO__OUTPUT(BLANK, D, 7);
GPIO__OUTPUT(GSCLK, B, 0);

GPIO__INPUT(VOLTAGE, C, 0);

GPIO__INPUT(RESET, C, 6);
GPIO__OUTPUT(SCK, B, 5);
GPIO__OUTPUT(MOSI, B, 3);
GPIO__INPUT(MISO, B, 4);

// LED FADER ##################################################################
#include <xpcc/driver/ui/led.hpp>

typedef xpcc::atmega::SpiMaster LedSpi;
typedef xpcc::TLC594X< 32, LedSpi, XLAT, VPROG > controller;

// 10 white LEDs in the front
uint8_t whiteChannels[10] = {15,14,13,12,11,31,30,29,28,27};
xpcc::led::TLC594XMultipleLed< controller > white(whiteChannels, 10);

// six red LEDs in the back, four are constant
uint8_t redChannels[4] = {4,5,9,7};
xpcc::led::TLC594XMultipleLed< controller > red(redChannels, 4);

// two are pulsing
uint8_t redPulsingChannels[2] = {10,8};
xpcc::led::TLC594XMultipleLed< controller > redPulsingLed(redPulsingChannels, 2);
xpcc::led::Pulse redPulsing(&redPulsingLed, 1458);

// two position lights
uint8_t positionChannels[2] = {0,3};
xpcc::led::TLC594XMultipleLed< controller > position(positionChannels, 2);

// two beacon lights
xpcc::led::TLC594XLed< controller > beaconLed(6);
xpcc::led::Indicator beacon(&beaconLed, 2467, 0.28f, 130, 200);

// two strobe lights
uint8_t strobeChannels[2] = {1,2};
xpcc::led::TLC594XMultipleLed< controller > strobeLed(strobeChannels, 2);
xpcc::led::DoubleIndicator strobe(&strobeLed, 1825, 0.06f, 0.075f, 0.05f, 0, 20);

// blue stripes
uint8_t blueChannels[7] = {20,21,22,23,24,25,26};
xpcc::led::TLC594XMultipleLed< controller > blue(blueChannels, 7);

// io light
xpcc::led::TLC594XLed< controller > io(16);

// UART #######################################################################
#if UART_ENABLED
typedef xpcc::atmega::BufferedUart0 Uart;
Uart uart(38400);

#	include <xpcc/io/iodevice_wrapper.hpp>
#	include <xpcc/io/iostream.hpp>
xpcc::IODeviceWrapper<Uart> device(uart);
xpcc::IOStream stream(device);
#	define UART_STREAM(x) stream << x << xpcc::endl
#	define UART(x) uart.write(x)
#else
#	define UART_STREAM(x)
#	define UART(x)
#endif

// TIMEOUTS ###################################################################
#include <xpcc/workflow.hpp>
const uint16_t fadeTime = 5000;
xpcc::Timeout<> fadeOutTimer(fadeTime);
xpcc::Timeout<> fadeInTimer(fadeTime);

bool halfBrightness = false;
const uint8_t lowBrightness = 2;
const uint8_t highBrightness = 16;

const uint16_t motionTimeout = 10000;
xpcc::Timeout<> motionTimer(motionTimeout);
bool inMotion = true;
bool inMotionPrev = false;

const uint16_t buttonLongPressTime = 1000;
const uint16_t buttonShortPressTime = 50;
xpcc::Timeout<> buttonLongTimer(buttonLongPressTime);
xpcc::Timeout<> buttonShortTimer(buttonShortPressTime);

enum
{
	BUTTON_NO_PRESS,
	BUTTON_SHORT_PRESS,
	BUTTON_LONG_PRESS,
} buttonStatus = BUTTON_SHORT_PRESS;
bool depressed;

// INTERRUPTS #################################################################
ISR(TIMER2_COMPA_vect)
{
	xpcc::Clock::increment();

	controller::writeChannels();
}

ISR(TIMER0_OVF_vect)
{
	BLANK::reset();
}

ISR(TIMER0_COMPB_vect)
{
	BLANK::set();
}

ISR(INT1_vect)
{
	// restart the motion timer with 10 seconds
	motionTimer.restart(10000);
	inMotion = true;

//	UART('m');
}

ISR(INT0_vect)
{
	// true button is "closed", false button is "open"
	depressed = !BUTTON::read();
	static bool depressedPrev = false;
	UART_STREAM("Button=" << depressed);

	if (depressed != depressedPrev)
	{
		depressedPrev = depressed;
		motionTimer.restart(10000);
		inMotion = true;

		if (depressed)
		{
			buttonShortTimer.restart(buttonShortPressTime);
			buttonLongTimer.restart(buttonLongPressTime);
			io.on();
		}
		else
		{
			io.off();
			if (buttonLongTimer.isExpired())
			{
				buttonStatus = BUTTON_LONG_PRESS;
				UART_STREAM("Long Press");
			}
			else
			{
				EIMSK |= (1 << INT1);
				if (buttonShortTimer.isExpired())
				{
					buttonStatus = BUTTON_SHORT_PRESS;
					UART_STREAM("Short Press");
				}
				else
				{
					buttonStatus = BUTTON_NO_PRESS;
					UART_STREAM("No Press");
				}
			}
		}
	}
}

MAIN_FUNCTION // ##############################################################
{
	// Pull-up on Mode, Button and Motion pins
	BUTTON::setInput(xpcc::atmega::PULLUP);
	MOTION::setInput(xpcc::atmega::PULLUP);
	RESET::setInput(xpcc::atmega::PULLUP);
	TXD::setOutput();
	RXD::setInput();
	VOLTAGE::setInput();
	BLANK::setOutput(xpcc::gpio::LOW);
	SCK::setOutput();
	MOSI::setOutput();
	MISO::setInput();
	VPROG::setOutput(xpcc::gpio::LOW);
	XLAT::setOutput(xpcc::gpio::LOW);

	LedSpi::initialize(LedSpi::MODE_0, LedSpi::PRESCALER_2);
	set_sleep_mode(SLEEP_MODE_IDLE);

	// Set up interupts for the motion sensor and button
	// set external interrupt on any logical change for Button/Int0 and Motion/Int1
	EICRA = (1 << ISC00) | (1 << ISC10);
	// enable both external interrupts
	EIMSK = (1 << INT0) | (1 << INT1);

	// Fast PWM Mode, clear at Bottom
	TCCR0A = (1<<WGM00) | (1<<WGM01);
	// Grayscale counter going at 8000kHz/4096 = 1.953125kHz
	// this period should be slightly slower
	// 8000kHz / 64 / 65 = 1.92kHz
	TCCR0B = (1<<CS01) | (1<<CS00) | (1<<WGM02);
	OCR0A = 65;
	OCR0B = 64;
	// Enable Output Compare Match interrupt B
	TIMSK0 = (1<<OCIE0B) | (1<<TOIE0);

	// Enable 1ms interrupt
	// CTC Mode
	TCCR2A = (1<<WGM21);
	// 8000kHz / 64 / 125 = 1kHz = 1ms
	TCCR2B = (1<<CS22);
	OCR2A = 125;
	// Enable Overflow Interrupt
	TIMSK2 = (1<<OCIE2A);

	xpcc::atmega::enableInterrupts();
	UART_STREAM("\n\nRESTART\n");

	// 1.24V * 31.5 / (0.5kOhm) = 78.12mA
	// 64 / 78.12mA * 20mA = 16.41
	controller::initialize(0, highBrightness, true, false);

	while (1)
	{
		white.run();
		red.run();
		redPulsing.run();
		position.run();
		beacon.run();
		strobe.run();
		blue.run();
		io.run();

		if (motionTimer.isExpired())
		{
			inMotion = false;
		}

		if (buttonStatus == BUTTON_LONG_PRESS)
		{
			buttonStatus = BUTTON_NO_PRESS;
			// disable motion sensor
			EIMSK &= ~(1 << INT1);
			inMotion = false;
		}

		if (inMotion != inMotionPrev)
		{
			inMotionPrev = inMotion;

			if (inMotion)
			{
				UART_STREAM("switching on");
				white.on(fadeTime);
				red.on(fadeTime);
				blue.on(fadeTime);
				position.on(fadeTime);

				fadeInTimer.restart(fadeTime);
			}
			else
			{
				UART_STREAM("switching off");
				white.off(fadeTime);
				red.off(fadeTime);
				blue.off(fadeTime);
				position.off(fadeTime);

				redPulsing.stop();
				beacon.stop();
				strobe.stop();

				fadeOutTimer.restart(fadeTime);
			}
		}

		if (buttonStatus == BUTTON_SHORT_PRESS)
		{
			buttonStatus = BUTTON_NO_PRESS;

			uint8_t brightness = halfBrightness ? lowBrightness : highBrightness;
			controller::setAllDotCorrection(brightness, false);
			if (!halfBrightness)
			{
				controller::setDotCorrection(6, 2*highBrightness);
				controller::setDotCorrection(11, 0x3f);
				controller::setDotCorrection(12, 0x3f);
				controller::setDotCorrection(13, 0x3f);
				controller::setDotCorrection(14, 0x3f);
				controller::setDotCorrection(15, 0x3f);
				controller::setDotCorrection(27, 0x3f);
				controller::setDotCorrection(28, 0x3f);
				controller::setDotCorrection(29, 0x3f);
				controller::setDotCorrection(30, 0x3f);
				controller::setDotCorrection(31, 0x3f);
				controller::setDotCorrection(4, 6);
				controller::setDotCorrection(5, 6);
				controller::setDotCorrection(7, 6);
				controller::setDotCorrection(9, 6);
			}
			controller::setDotCorrection(16, 1);
			{
				xpcc::atomic::Lock lock;
				controller::writeDotCorrection();
			}
			UART_STREAM("brightness=" << brightness);
			halfBrightness = !halfBrightness;
		}

		if (depressed && buttonLongTimer.isExpired())
		{
			io.off();
		}

		if (inMotion && !beacon.isRunning() && fadeInTimer.isExpired())
		{
			redPulsing.start();
			beacon.start();
			strobe.start();
		}

		if (!inMotion && fadeOutTimer.isExpired())
		{
			// turn off all LED driver outputs
			BLANK::set(xpcc::gpio::HIGH);
			// go to deep sleep
			set_sleep_mode(SLEEP_MODE_PWR_DOWN);
			sleep_mode();

			UART_STREAM("wakeup");
			// put mode back to idle
			set_sleep_mode(SLEEP_MODE_IDLE);
		}
		else
		{
			sleep_mode();
		}
	}
}
<commit_msg>Add wake up filter to light up only after a certain time of continuos motion. Fix button state after wakeup.<commit_after>/* coding: utf-8
 *
 */
#include <xpcc/architecture/platform.hpp>
#include <avr/sleep.h>
#include <avr/power.h>

#define UART_ENABLED 0

// IO #########################################################################
//
//                     +------------+
// (MOTION/INT1) PD3  1|o           |24  PC1
//               PD4  2|            |23  PC0 (ADC0/VOLTAGE)
//               GND  3|            |22  ADC7
//               VCC  4|            |21  GND
//               GND  5|            |20  AREF
//               VCC  6|            |19  ADC6
//       (XLAT1) PB6  7|            |18  AVCC
//       (XLAT2) PB7  8|            |17  PB5 (SCK)
//                     +------------+
//
//                     +------------+
//              PD5   9|           o|32  PD2 (BUTTON/INT0)
//       (XLAT) PD6  10|            |31  PD1 (TXD)
//      (BLANK) PD7  11|            |30  PD0 (RXD)
//      (GSCLK) PB0  12|            |29  PC6 (RESET)
//              PB1  13|            |28  PC5
//      (VPROG) PB2  14|            |27  PC4
//       (MOSI) PB3  15|            |26  PC3
//       (MISO) PB4  16|            |25  PC2
//                     +------------+

GPIO__INPUT(RXD, D, 0);
GPIO__OUTPUT(TXD, D, 1);

GPIO__INPUT(BUTTON, D, 2);
GPIO__INPUT(MOTION, D, 3);

GPIO__OUTPUT(VPROG, B, 2);
GPIO__OUTPUT(XLAT, D, 6);
GPIO__OUTPUT(BLANK, D, 7);
GPIO__OUTPUT(GSCLK, B, 0);

GPIO__INPUT(VOLTAGE, C, 0);

GPIO__INPUT(RESET, C, 6);
GPIO__OUTPUT(SCK, B, 5);
GPIO__OUTPUT(MOSI, B, 3);
GPIO__INPUT(MISO, B, 4);

// LED FADER ##################################################################
#include <xpcc/driver/ui/led.hpp>

typedef xpcc::atmega::SpiMaster LedSpi;
typedef xpcc::TLC594X< 32, LedSpi, XLAT, VPROG > controller;

// 10 white LEDs in the front
uint8_t whiteChannels[10] = {15,14,13,12,11,31,30,29,28,27};
xpcc::led::TLC594XMultipleLed< controller > white(whiteChannels, 10);

// six red LEDs in the back, four are constant
uint8_t redChannels[4] = {4,5,9,7};
xpcc::led::TLC594XMultipleLed< controller > red(redChannels, 4);

// two are pulsing
uint8_t redPulsingChannels[2] = {10,8};
xpcc::led::TLC594XMultipleLed< controller > redPulsingLed(redPulsingChannels, 2);
xpcc::led::Pulse redPulsing(&redPulsingLed, 1458);

// two position lights
uint8_t positionChannels[2] = {0,3};
xpcc::led::TLC594XMultipleLed< controller > position(positionChannels, 2);

// two beacon lights
xpcc::led::TLC594XLed< controller > beaconLed(6);
xpcc::led::Indicator beacon(&beaconLed, 2467, 0.28f, 130, 200);

// two strobe lights
uint8_t strobeChannels[2] = {1,2};
xpcc::led::TLC594XMultipleLed< controller > strobeLed(strobeChannels, 2);
xpcc::led::DoubleIndicator strobe(&strobeLed, 1825, 0.06f, 0.075f, 0.05f, 0, 20);

// blue stripes
uint8_t blueChannels[7] = {20,21,22,23,24,25,26};
xpcc::led::TLC594XMultipleLed< controller > blue(blueChannels, 7);

// io light
xpcc::led::TLC594XLed< controller > io(16);

// UART #######################################################################
#if UART_ENABLED
typedef xpcc::atmega::BufferedUart0 Uart;
Uart uart(38400);

#	include <xpcc/io/iodevice_wrapper.hpp>
#	include <xpcc/io/iostream.hpp>
xpcc::IODeviceWrapper<Uart> device(uart);
xpcc::IOStream stream(device);
#	define UART_STREAM(x) stream << x << xpcc::endl
#	define UART(x) uart.write(x)
#else
#	define UART_STREAM(x)
#	define UART(x)
#endif

// TIMEOUTS ###################################################################
#include <xpcc/workflow.hpp>
const uint16_t fadeTime = 5000;
xpcc::Timeout<> fadeOutTimer(fadeTime);
xpcc::Timeout<> fadeInTimer(fadeTime);

bool halfBrightness = true;
const uint8_t lowBrightness = 2;
const uint8_t highBrightness = 16;

const uint16_t motionTimeout = 10000;
xpcc::Timeout<> motionTimer(motionTimeout);
bool inMotion = true;
bool inMotionPrev = false;

const uint16_t buttonLongPressTime = 1000;
const uint16_t buttonShortPressTime = 50;
xpcc::Timeout<> buttonLongTimer(buttonLongPressTime);
xpcc::Timeout<> buttonShortTimer(buttonShortPressTime);

bool justWokeUp = false;
const uint16_t motionWakeTime = 2000;
const uint16_t motionWakeIntervalTime = 200;
xpcc::Timeout<> motionWakeTimer(motionWakeTime);
xpcc::Timeout<> motionWakeIntervalTimer(motionWakeIntervalTime);

enum
{
	BUTTON_NO_PRESS,
	BUTTON_DEPRESSED,
	BUTTON_SHORT_PRESS,
	BUTTON_LONG_PRESS,
} buttonState = BUTTON_SHORT_PRESS;
bool depressed;

// INTERRUPTS #################################################################
ISR(TIMER2_COMPA_vect)
{
	xpcc::Clock::increment();

	controller::writeChannels();
}

ISR(TIMER0_OVF_vect)
{
	BLANK::reset();
}

ISR(TIMER0_COMPB_vect)
{
	BLANK::set();
}

ISR(INT1_vect)
{
	// restart the motion timer with 10 seconds
	if (justWokeUp)
	{
		if (motionWakeTimer.isExpired() && !motionWakeIntervalTimer.isExpired())
		{
			justWokeUp = false;
			inMotion = true;
			motionTimer.restart(10000);
		}

		motionWakeIntervalTimer.restart(motionWakeIntervalTime);
		fadeOutTimer.restart(motionWakeIntervalTime);
	}
	else
	{
		inMotion = true;
		motionTimer.restart(10000);
	}
//	UART('m');
}

ISR(INT0_vect)
{
	// true button is "closed", false button is "open"
	depressed = !BUTTON::read();
	static bool depressedPrev = false;
	UART_STREAM("Button=" << depressed);

	if (depressed != depressedPrev)
	{
		depressedPrev = depressed;
		motionTimer.restart(10000);
		inMotion = true;

		if (depressed)
		{
			buttonShortTimer.restart(buttonShortPressTime);
			buttonLongTimer.restart(buttonLongPressTime);
			buttonState = BUTTON_DEPRESSED;
			io.on();
		}
		else
		{
			if (buttonState == BUTTON_DEPRESSED && !justWokeUp)
			{
				if (buttonLongTimer.isExpired())
				{
					buttonState = BUTTON_LONG_PRESS;
					UART_STREAM("Long Press");
				}
				else
				{
					if (buttonShortTimer.isExpired())
					{
						buttonState = BUTTON_SHORT_PRESS;
						UART_STREAM("Short Press");
					}
					else
					{
						buttonState = BUTTON_NO_PRESS;
						UART_STREAM("No Press");
					}
				}
			}

			io.off();
			EIMSK |= (1 << INT1);
			justWokeUp = false;
		}
	}
}

MAIN_FUNCTION // ##############################################################
{
	// Pull-up on Mode, Button and Motion pins
	BUTTON::setInput(xpcc::atmega::PULLUP);
	MOTION::setInput(xpcc::atmega::PULLUP);
	RESET::setInput(xpcc::atmega::PULLUP);
	TXD::setOutput();
	RXD::setInput();
	VOLTAGE::setInput();
	BLANK::setOutput(xpcc::gpio::LOW);
	SCK::setOutput();
	MOSI::setOutput();
	MISO::setInput();
	VPROG::setOutput(xpcc::gpio::LOW);
	XLAT::setOutput(xpcc::gpio::LOW);

	LedSpi::initialize(LedSpi::MODE_0, LedSpi::PRESCALER_2);
	set_sleep_mode(SLEEP_MODE_IDLE);

	// Set up interupts for the motion sensor and button
	// set external interrupt on any logical change for Button/Int0 and Motion/Int1
	EICRA = (1 << ISC00) | (1 << ISC10);
	// enable both external interrupts
	EIMSK = (1 << INT0) | (1 << INT1);

	// Fast PWM Mode, clear at Bottom
	TCCR0A = (1<<WGM00) | (1<<WGM01);
	// Grayscale counter going at 8000kHz/4096 = 1.953125kHz
	// this period should be slightly slower
	// 8000kHz / 64 / 65 = 1.92kHz
	TCCR0B = (1<<CS01) | (1<<CS00) | (1<<WGM02);
	OCR0A = 65;
	OCR0B = 64;
	// Enable Output Compare Match interrupt B
	TIMSK0 = (1<<OCIE0B) | (1<<TOIE0);

	// Enable 1ms interrupt
	// CTC Mode
	TCCR2A = (1<<WGM21);
	// 8000kHz / 64 / 125 = 1kHz = 1ms
	TCCR2B = (1<<CS22);
	OCR2A = 125;
	// Enable Overflow Interrupt
	TIMSK2 = (1<<OCIE2A);

	xpcc::atmega::enableInterrupts();
	UART_STREAM("\n\nRESTART\n");

	// 1.24V * 31.5 / (0.5kOhm) = 78.12mA
	// 64 / 78.12mA * 20mA = 16.41
	controller::initialize(0, highBrightness, true, false);

	while (1)
	{
		if (motionTimer.isExpired())
		{
			inMotion = false;
		}

		if (buttonState == BUTTON_LONG_PRESS)
		{
			buttonState = BUTTON_NO_PRESS;
			// disable motion sensor
			EIMSK &= ~(1 << INT1);
			inMotion = false;
		}

		if (inMotion != inMotionPrev)
		{
			inMotionPrev = inMotion;

			if (inMotion)
			{
				UART_STREAM("switching on");
				white.on(fadeTime);
				red.on(fadeTime);
				blue.on(fadeTime);
				position.on(fadeTime);

				fadeInTimer.restart(fadeTime);
			}
			else
			{
				UART_STREAM("switching off");
				white.off(fadeTime);
				red.off(fadeTime);
				blue.off(fadeTime);
				position.off(fadeTime);

				redPulsing.stop();
				beacon.stop();
				strobe.stop();

				fadeOutTimer.restart(fadeTime);
			}
		}

		if (buttonState == BUTTON_SHORT_PRESS)
		{
			buttonState = BUTTON_NO_PRESS;

			uint8_t brightness = halfBrightness ? lowBrightness : highBrightness;
			controller::setAllDotCorrection(brightness, false);
			if (!halfBrightness)
			{
				controller::setDotCorrection(6, 2*highBrightness);
				controller::setDotCorrection(11, 0x3f);
				controller::setDotCorrection(12, 0x3f);
				controller::setDotCorrection(13, 0x3f);
				controller::setDotCorrection(14, 0x3f);
				controller::setDotCorrection(15, 0x3f);
				controller::setDotCorrection(27, 0x3f);
				controller::setDotCorrection(28, 0x3f);
				controller::setDotCorrection(29, 0x3f);
				controller::setDotCorrection(30, 0x3f);
				controller::setDotCorrection(31, 0x3f);
				controller::setDotCorrection(4, 6);
				controller::setDotCorrection(5, 6);
				controller::setDotCorrection(7, 6);
				controller::setDotCorrection(9, 6);
			}
			controller::setDotCorrection(16, 1);
			{
				xpcc::atomic::Lock lock;
				controller::writeDotCorrection();
			}
			UART_STREAM("brightness=" << brightness);
			halfBrightness = !halfBrightness;
		}

		if (buttonState == BUTTON_DEPRESSED && buttonLongTimer.isExpired())
		{
			io.off();
		}

		if (inMotion && !beacon.isRunning() && fadeInTimer.isExpired())
		{
			redPulsing.start();
			beacon.start();
			strobe.start();
		}

		white.run();
		red.run();
		redPulsing.run();
		position.run();
		beacon.run();
		strobe.run();
		blue.run();
		io.run();

		if (!inMotion && fadeOutTimer.isExpired())
		{
			// turn off all LED driver outputs
			BLANK::set(xpcc::gpio::HIGH);
			// go to deep sleep
			set_sleep_mode(SLEEP_MODE_PWR_DOWN);
			justWokeUp = true;
			sleep_mode();
			// put mode back to idle
			set_sleep_mode(SLEEP_MODE_IDLE);

			UART_STREAM("wakeup");
			motionWakeTimer.restart(motionWakeTime);
		}
		else
		{
			sleep_mode();
		}
	}
}
<|endoftext|>


<commit_before>#include"../header/simplify.hpp"
#include"../../lib/header/algorithm/algorithm.hpp"
#include"../header/CQCircuit.hpp"
#include"../header/IQBit.hpp"
using namespace nQCircuit;
using namespace std;

namespace
{
	bool disjoint(const CQGate &lhs,const CQGate &rhs)
	{
		bool both{false};
		return nAlgorithm::find_if_val<size_t>(0,lhs.gate_size(),[&](const auto i){
			return lhs[i]->info()==QBit::NOT&&rhs[i]->info()==QBit::NOT
				||(lhs[i]->info()==QBit::CONTROLLED_NOT&&rhs[i]->info()==QBit::WHITE_CONTROLLED_NOT||lhs[i]->info()==QBit::WHITE_CONTROLLED_NOT&&rhs[i]->info()==QBit::CONTROLLED_NOT)
				||((lhs[i]->info()==QBit::NOT&&rhs[i]->info()==QBit::EMPTY||lhs[i]->info()==QBit::EMPTY&&rhs[i]->info()==QBit::NOT)&&!(both=!both));
		})!=lhs.gate_size();
	}

	inline size_t diff_pos(const CQGate &lhs,const CQGate &rhs)
	{
		return nAlgorithm::find_if_val<size_t>(0,lhs.gate_size(),[&](const size_t subscript){return *lhs[subscript]!=*rhs[subscript];});
	}

	inline bool is_1_diff(const CQGate &lhs,const CQGate &rhs)
	{
		return nAlgorithm::count_if_val<size_t>(0,lhs.gate_size(),[&](const size_t subscript){return *lhs[subscript]!=*rhs[subscript];})==1;
	}
}

namespace nQCircuit
{
	bool ABA_B(CQCircuit &val)
	{
		if(val.size())
			for(size_t i{0};i!=val.size()-1;++i)
				for(size_t j{i+1};j!=val.size();++j)
					if(val[i]==val[j])
					{
						if(nAlgorithm::all_of_val(i+1,j,[&,i](const size_t subscript){return disjoint(val[i],val[subscript]);}))
						{
							val.erase(j);
							val.erase(i);
							return true;
						}
						break;
					}
		return false;
	}

	bool diff_1_bit(CQCircuit &val)
	{
		if(val.size())
			for(size_t i{0};i!=val.size()-1;++i)
				for(size_t j{i+1};j!=val.size();++j)
					if(is_1_diff(val[i],val[j]))
					{
						const auto pos{diff_pos(val[i],val[j])};
						val[i][pos]=make_Q_empty_bit();
						val[j][pos]=make_Q_empty_bit();
						return true;
					}
		return false;
	}

	bool simplify_all(CQCircuit &val)
	{
		return ABA_B(val)||diff_1_bit(val);
	}
}<commit_msg>add ()<commit_after>#include"../header/simplify.hpp"
#include"../../lib/header/algorithm/algorithm.hpp"
#include"../header/CQCircuit.hpp"
#include"../header/IQBit.hpp"
using namespace nQCircuit;
using namespace std;

namespace
{
	bool disjoint(const CQGate &lhs,const CQGate &rhs)
	{
		bool both{false};
		return nAlgorithm::find_if_val<size_t>(0,lhs.gate_size(),[&](const auto i){
			return ((lhs[i]->info()==QBit::NOT)&&(rhs[i]->info()==QBit::NOT))
				||(((lhs[i]->info()==QBit::CONTROLLED_NOT)&&(rhs[i]->info()==QBit::WHITE_CONTROLLED_NOT))
				   ||((lhs[i]->info()==QBit::WHITE_CONTROLLED_NOT)&&(rhs[i]->info()==QBit::CONTROLLED_NOT)))
				||((((lhs[i]->info()==QBit::NOT)&&(rhs[i]->info()==QBit::EMPTY))
					||((lhs[i]->info()==QBit::EMPTY)&&(rhs[i]->info()==QBit::NOT)))
				   &&!(both=!both));
		})!=lhs.gate_size();
	}

	inline size_t diff_pos(const CQGate &lhs,const CQGate &rhs)
	{
		return nAlgorithm::find_if_val<size_t>(0,lhs.gate_size(),[&](const size_t subscript){return *lhs[subscript]!=*rhs[subscript];});
	}

	inline bool is_1_diff(const CQGate &lhs,const CQGate &rhs)
	{
		return nAlgorithm::count_if_val<size_t>(0,lhs.gate_size(),[&](const size_t subscript){return *lhs[subscript]!=*rhs[subscript];})==1;
	}
}

namespace nQCircuit
{
	bool ABA_B(CQCircuit &val)
	{
		if(val.size())
			for(size_t i{0};i!=val.size()-1;++i)
				for(size_t j{i+1};j!=val.size();++j)
					if(val[i]==val[j])
					{
						if(nAlgorithm::all_of_val(i+1,j,[&,i](const size_t subscript){return disjoint(val[i],val[subscript]);}))
						{
							val.erase(j);
							val.erase(i);
							return true;
						}
						break;
					}
		return false;
	}

	bool diff_1_bit(CQCircuit &val)
	{
		if(val.size())
			for(size_t i{0};i!=val.size()-1;++i)
				for(size_t j{i+1};j!=val.size();++j)
					if(is_1_diff(val[i],val[j]))
					{
						const auto pos{diff_pos(val[i],val[j])};
						val[i][pos]=make_Q_empty_bit();
						val[j][pos]=make_Q_empty_bit();
						return true;
					}
		return false;
	}

	bool simplify_all(CQCircuit &val)
	{
		return ABA_B(val)||diff_1_bit(val);
	}
}<|endoftext|>


<commit_before>#include <boost/test/test_case_template.hpp>
#include <boost/test/unit_test.hpp>

#include "args.hpp"
#include "coordinates.hpp"
#include "equal_json.hpp"
#include "fixture.hpp"

#include "osrm/coordinate.hpp"
#include "osrm/engine_config.hpp"
#include "osrm/json_container.hpp"
#include "osrm/json_container.hpp"
#include "osrm/osrm.hpp"
#include "osrm/route_parameters.hpp"
#include "osrm/status.hpp"

BOOST_AUTO_TEST_SUITE(route)

BOOST_AUTO_TEST_CASE(test_route_same_coordinates_fixture)
{
    const auto args = get_args();
    auto osrm = getOSRM(args.at(0));

    using namespace osrm;

    RouteParameters params;
    params.steps = true;
    params.coordinates.push_back(get_dummy_location());
    params.coordinates.push_back(get_dummy_location());

    json::Object result;
    const auto rc = osrm.Route(params, result);
    BOOST_CHECK(rc == Status::Ok);

    // unset snapping dependent hint
    for (auto &itr : result.values["waypoints"].get<json::Array>().values)
        itr.get<json::Object>().values["hint"] = "";

    const auto location = json::Array{{{7.437070}, {43.749247}}};

    json::Object reference{
        {{"code", "Ok"},
         {"waypoints",
          json::Array{
              {json::Object{
                   {{"name", "Boulevard du Larvotto"}, {"location", location}, {"hint", ""}}},
               json::Object{
                   {{"name", "Boulevard du Larvotto"}, {"location", location}, {"hint", ""}}}}}},
         {"routes",
          json::Array{{json::Object{
              {{"distance", 0.},
               {"duration", 0.},
               {"geometry", "yw_jGupkl@??"},
               {"legs",
                json::Array{{json::Object{
                    {{"distance", 0.},
                     {"duration", 0.},
                     {"summary", ""},
                     {"steps",
                      json::Array{{{json::Object{{{"duration", 0.},
                                                  {"distance", 0.},
                                                  {"geometry", "yw_jGupkl@??"},
                                                  {"name", "Boulevard du Larvotto"},
                                                  {"mode", "driving"},
                                                  {"maneuver",
                                                   json::Object{{
                                                       {"location", location},
                                                       {"bearing_before", 0},
                                                       {"bearing_after", 0},
                                                       {"type", "depart"},
                                                   }}},
                                                  {"intersections",
                                                   json::Array{{json::Object{
                                                       {{"location", location},
                                                        {"bearings", json::Array{{0}}},
                                                        {"entry", json::Array{{json::True()}}},
                                                        {"out", 0}}}}}}}}},

                                   json::Object{{{"duration", 0.},
                                                 {"distance", 0.},
                                                 {"geometry", "yw_jGupkl@"},
                                                 {"name", "Boulevard du Larvotto"},
                                                 {"mode", "driving"},
                                                 {"maneuver",
                                                  json::Object{{{"location", location},
                                                                {"bearing_before", 0},
                                                                {"bearing_after", 0},
                                                                {"type", "arrive"}}}},
                                                 {"intersections",
                                                  json::Array{{json::Object{
                                                      {{"location", location},
                                                       {"bearings", json::Array{{180}}},
                                                       {"entry", json::Array{{json::True()}}},
                                                       {"in", 0}}}}}}

                                   }}}}}}}}}}}}}}}}};

    CHECK_EQUAL_JSON(reference, result);
}

BOOST_AUTO_TEST_CASE(test_route_same_coordinates)
{
    const auto args = get_args();
    auto osrm = getOSRM(args.at(0));

    using namespace osrm;

    RouteParameters params;
    params.steps = true;
    params.coordinates.push_back(get_dummy_location());
    params.coordinates.push_back(get_dummy_location());
    params.coordinates.push_back(get_dummy_location());

    json::Object result;
    const auto rc = osrm.Route(params, result);
    BOOST_CHECK(rc == Status::Ok);

    const auto code = result.values.at("code").get<json::String>().value;
    BOOST_CHECK_EQUAL(code, "Ok");

    const auto &waypoints = result.values.at("waypoints").get<json::Array>().values;
    BOOST_CHECK(waypoints.size() == params.coordinates.size());

    for (const auto &waypoint : waypoints)
    {
        const auto &waypoint_object = waypoint.get<json::Object>();

        // nothing can be said about name, empty or contains name of the street
        const auto name = waypoint_object.values.at("name").get<json::String>().value;
        BOOST_CHECK(((void)name, true));

        const auto location = waypoint_object.values.at("location").get<json::Array>().values;
        const auto longitude = location[0].get<json::Number>().value;
        const auto latitude = location[1].get<json::Number>().value;
        BOOST_CHECK(longitude >= -180. && longitude <= 180.);
        BOOST_CHECK(latitude >= -90. && latitude <= 90.);

        const auto hint = waypoint_object.values.at("hint").get<json::String>().value;
        BOOST_CHECK(!hint.empty());
    }

    const auto &routes = result.values.at("routes").get<json::Array>().values;
    BOOST_REQUIRE_GT(routes.size(), 0);

    for (const auto &route : routes)
    {
        const auto &route_object = route.get<json::Object>();

        const auto distance = route_object.values.at("distance").get<json::Number>().value;
        BOOST_CHECK_EQUAL(distance, 0);

        const auto duration = route_object.values.at("duration").get<json::Number>().value;
        BOOST_CHECK_EQUAL(duration, 0);

        // geometries=polyline by default
        const auto geometry = route_object.values.at("geometry").get<json::String>().value;
        BOOST_CHECK(!geometry.empty());

        const auto &legs = route_object.values.at("legs").get<json::Array>().values;
        BOOST_CHECK(!legs.empty());

        for (const auto &leg : legs)
        {
            const auto &leg_object = leg.get<json::Object>();

            const auto distance = leg_object.values.at("distance").get<json::Number>().value;
            BOOST_CHECK_EQUAL(distance, 0);

            const auto duration = leg_object.values.at("duration").get<json::Number>().value;
            BOOST_CHECK_EQUAL(duration, 0);

            // nothing can be said about summary, empty or contains human readable summary
            const auto summary = leg_object.values.at("summary").get<json::String>().value;
            BOOST_CHECK(((void)summary, true));

            const auto &steps = leg_object.values.at("steps").get<json::Array>().values;
            BOOST_CHECK(!steps.empty());

            std::size_t step_count = 0;

            for (const auto &step : steps)
            {
                const auto &step_object = step.get<json::Object>();

                const auto distance = step_object.values.at("distance").get<json::Number>().value;
                BOOST_CHECK_EQUAL(distance, 0);

                const auto duration = step_object.values.at("duration").get<json::Number>().value;
                BOOST_CHECK_EQUAL(duration, 0);

                // geometries=polyline by default
                const auto geometry = step_object.values.at("geometry").get<json::String>().value;
                BOOST_CHECK(!geometry.empty());

                // nothing can be said about name, empty or contains way name
                const auto name = step_object.values.at("name").get<json::String>().value;
                BOOST_CHECK(((void)name, true));

                // nothing can be said about mode, contains mode of transportation
                const auto mode = step_object.values.at("mode").get<json::String>().value;
                BOOST_CHECK(!name.empty());

                const auto &maneuver = step_object.values.at("maneuver").get<json::Object>().values;

                const auto type = maneuver.at("type").get<json::String>().value;
                BOOST_CHECK(!type.empty());

                const auto &intersections =
                    step_object.values.at("intersections").get<json::Array>().values;

                for (auto &intersection : intersections)
                {
                    const auto &intersection_object = intersection.get<json::Object>().values;
                    const auto location =
                        intersection_object.at("location").get<json::Array>().values;
                    const auto longitude = location[0].get<json::Number>().value;
                    const auto latitude = location[1].get<json::Number>().value;
                    BOOST_CHECK(longitude >= -180. && longitude <= 180.);
                    BOOST_CHECK(latitude >= -90. && latitude <= 90.);

                    const auto &bearings =
                        intersection_object.at("bearings").get<json::Array>().values;
                    BOOST_CHECK(!bearings.empty());
                    const auto &entries = intersection_object.at("entry").get<json::Array>().values;
                    BOOST_CHECK(bearings.size() == entries.size());

                    for (const auto bearing : bearings)
                        BOOST_CHECK(0. <= bearing.get<json::Number>().value &&
                                    bearing.get<json::Number>().value <= 360.);

                    if (step_count > 0)
                    {
                        const auto in = intersection_object.at("in").get<json::Number>().value;
                        BOOST_CHECK(in < bearings.size());
                    }
                    if (step_count + 1 < steps.size())
                    {
                        const auto out = intersection_object.at("out").get<json::Number>().value;
                        BOOST_CHECK(out < bearings.size());
                    }
                }

                // modifier is optional
                // TODO(daniel-j-h):

                // exit is optional
                // TODO(daniel-j-h):
                ++step_count;
            }
        }
    }
}

BOOST_AUTO_TEST_CASE(test_route_response_for_locations_in_small_component)
{
    const auto args = get_args();
    auto osrm = getOSRM(args.at(0));

    using namespace osrm;

    const auto locations = get_locations_in_small_component();

    RouteParameters params;
    params.coordinates.push_back(locations.at(0));
    params.coordinates.push_back(locations.at(1));
    params.coordinates.push_back(locations.at(2));

    json::Object result;
    const auto rc = osrm.Route(params, result);
    BOOST_CHECK(rc == Status::Ok);

    const auto code = result.values.at("code").get<json::String>().value;
    BOOST_CHECK_EQUAL(code, "Ok");

    const auto &waypoints = result.values.at("waypoints").get<json::Array>().values;
    BOOST_CHECK_EQUAL(waypoints.size(), params.coordinates.size());

    for (const auto &waypoint : waypoints)
    {
        const auto &waypoint_object = waypoint.get<json::Object>();

        const auto location = waypoint_object.values.at("location").get<json::Array>().values;
        const auto longitude = location[0].get<json::Number>().value;
        const auto latitude = location[1].get<json::Number>().value;
        BOOST_CHECK(longitude >= -180. && longitude <= 180.);
        BOOST_CHECK(latitude >= -90. && latitude <= 90.);
    }
}

BOOST_AUTO_TEST_CASE(test_route_response_for_locations_in_big_component)
{
    const auto args = get_args();
    auto osrm = getOSRM(args.at(0));

    using namespace osrm;

    const auto locations = get_locations_in_big_component();

    RouteParameters params;
    params.coordinates.push_back(locations.at(0));
    params.coordinates.push_back(locations.at(1));
    params.coordinates.push_back(locations.at(2));

    json::Object result;
    const auto rc = osrm.Route(params, result);
    BOOST_CHECK(rc == Status::Ok);

    const auto code = result.values.at("code").get<json::String>().value;
    BOOST_CHECK_EQUAL(code, "Ok");

    const auto &waypoints = result.values.at("waypoints").get<json::Array>().values;
    BOOST_CHECK_EQUAL(waypoints.size(), params.coordinates.size());

    for (const auto &waypoint : waypoints)
    {
        const auto &waypoint_object = waypoint.get<json::Object>();

        const auto location = waypoint_object.values.at("location").get<json::Array>().values;
        const auto longitude = location[0].get<json::Number>().value;
        const auto latitude = location[1].get<json::Number>().value;
        BOOST_CHECK(longitude >= -180. && longitude <= 180.);
        BOOST_CHECK(latitude >= -90. && latitude <= 90.);
    }
}

BOOST_AUTO_TEST_CASE(test_route_response_for_locations_across_components)
{
    const auto args = get_args();
    auto osrm = getOSRM(args.at(0));

    using namespace osrm;

    const auto big_component = get_locations_in_big_component();
    const auto small_component = get_locations_in_small_component();

    RouteParameters params;
    params.coordinates.push_back(small_component.at(0));
    params.coordinates.push_back(big_component.at(0));
    params.coordinates.push_back(small_component.at(1));
    params.coordinates.push_back(big_component.at(1));

    json::Object result;
    const auto rc = osrm.Route(params, result);
    BOOST_CHECK(rc == Status::Ok);

    const auto code = result.values.at("code").get<json::String>().value;
    BOOST_CHECK_EQUAL(code, "Ok");

    const auto &waypoints = result.values.at("waypoints").get<json::Array>().values;
    BOOST_CHECK_EQUAL(waypoints.size(), params.coordinates.size());

    for (const auto &waypoint : waypoints)
    {
        const auto &waypoint_object = waypoint.get<json::Object>();

        const auto location = waypoint_object.values.at("location").get<json::Array>().values;
        const auto longitude = location[0].get<json::Number>().value;
        const auto latitude = location[1].get<json::Number>().value;
        BOOST_CHECK(longitude >= -180. && longitude <= 180.);
        BOOST_CHECK(latitude >= -90. && latitude <= 90.);
    }
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>With empty summaries no longer the case, update library tests accordingly<commit_after>#include <boost/test/test_case_template.hpp>
#include <boost/test/unit_test.hpp>

#include "args.hpp"
#include "coordinates.hpp"
#include "equal_json.hpp"
#include "fixture.hpp"

#include "osrm/coordinate.hpp"
#include "osrm/engine_config.hpp"
#include "osrm/json_container.hpp"
#include "osrm/json_container.hpp"
#include "osrm/osrm.hpp"
#include "osrm/route_parameters.hpp"
#include "osrm/status.hpp"

BOOST_AUTO_TEST_SUITE(route)

BOOST_AUTO_TEST_CASE(test_route_same_coordinates_fixture)
{
    const auto args = get_args();
    auto osrm = getOSRM(args.at(0));

    using namespace osrm;

    RouteParameters params;
    params.steps = true;
    params.coordinates.push_back(get_dummy_location());
    params.coordinates.push_back(get_dummy_location());

    json::Object result;
    const auto rc = osrm.Route(params, result);
    BOOST_CHECK(rc == Status::Ok);

    // unset snapping dependent hint
    for (auto &itr : result.values["waypoints"].get<json::Array>().values)
        itr.get<json::Object>().values["hint"] = "";

    const auto location = json::Array{{{7.437070}, {43.749247}}};

    json::Object reference{
        {{"code", "Ok"},
         {"waypoints",
          json::Array{
              {json::Object{
                   {{"name", "Boulevard du Larvotto"}, {"location", location}, {"hint", ""}}},
               json::Object{
                   {{"name", "Boulevard du Larvotto"}, {"location", location}, {"hint", ""}}}}}},
         {"routes",
          json::Array{{json::Object{
              {{"distance", 0.},
               {"duration", 0.},
               {"geometry", "yw_jGupkl@??"},
               {"legs",
                json::Array{{json::Object{
                    {{"distance", 0.},
                     {"duration", 0.},
                     {"summary", "Boulevard du Larvotto"},
                     {"steps",
                      json::Array{{{json::Object{{{"duration", 0.},
                                                  {"distance", 0.},
                                                  {"geometry", "yw_jGupkl@??"},
                                                  {"name", "Boulevard du Larvotto"},
                                                  {"mode", "driving"},
                                                  {"maneuver",
                                                   json::Object{{
                                                       {"location", location},
                                                       {"bearing_before", 0},
                                                       {"bearing_after", 0},
                                                       {"type", "depart"},
                                                   }}},
                                                  {"intersections",
                                                   json::Array{{json::Object{
                                                       {{"location", location},
                                                        {"bearings", json::Array{{0}}},
                                                        {"entry", json::Array{{json::True()}}},
                                                        {"out", 0}}}}}}}}},

                                   json::Object{{{"duration", 0.},
                                                 {"distance", 0.},
                                                 {"geometry", "yw_jGupkl@"},
                                                 {"name", "Boulevard du Larvotto"},
                                                 {"mode", "driving"},
                                                 {"maneuver",
                                                  json::Object{{{"location", location},
                                                                {"bearing_before", 0},
                                                                {"bearing_after", 0},
                                                                {"type", "arrive"}}}},
                                                 {"intersections",
                                                  json::Array{{json::Object{
                                                      {{"location", location},
                                                       {"bearings", json::Array{{180}}},
                                                       {"entry", json::Array{{json::True()}}},
                                                       {"in", 0}}}}}}

                                   }}}}}}}}}}}}}}}}};

    CHECK_EQUAL_JSON(reference, result);
}

BOOST_AUTO_TEST_CASE(test_route_same_coordinates)
{
    const auto args = get_args();
    auto osrm = getOSRM(args.at(0));

    using namespace osrm;

    RouteParameters params;
    params.steps = true;
    params.coordinates.push_back(get_dummy_location());
    params.coordinates.push_back(get_dummy_location());
    params.coordinates.push_back(get_dummy_location());

    json::Object result;
    const auto rc = osrm.Route(params, result);
    BOOST_CHECK(rc == Status::Ok);

    const auto code = result.values.at("code").get<json::String>().value;
    BOOST_CHECK_EQUAL(code, "Ok");

    const auto &waypoints = result.values.at("waypoints").get<json::Array>().values;
    BOOST_CHECK(waypoints.size() == params.coordinates.size());

    for (const auto &waypoint : waypoints)
    {
        const auto &waypoint_object = waypoint.get<json::Object>();

        // nothing can be said about name, empty or contains name of the street
        const auto name = waypoint_object.values.at("name").get<json::String>().value;
        BOOST_CHECK(((void)name, true));

        const auto location = waypoint_object.values.at("location").get<json::Array>().values;
        const auto longitude = location[0].get<json::Number>().value;
        const auto latitude = location[1].get<json::Number>().value;
        BOOST_CHECK(longitude >= -180. && longitude <= 180.);
        BOOST_CHECK(latitude >= -90. && latitude <= 90.);

        const auto hint = waypoint_object.values.at("hint").get<json::String>().value;
        BOOST_CHECK(!hint.empty());
    }

    const auto &routes = result.values.at("routes").get<json::Array>().values;
    BOOST_REQUIRE_GT(routes.size(), 0);

    for (const auto &route : routes)
    {
        const auto &route_object = route.get<json::Object>();

        const auto distance = route_object.values.at("distance").get<json::Number>().value;
        BOOST_CHECK_EQUAL(distance, 0);

        const auto duration = route_object.values.at("duration").get<json::Number>().value;
        BOOST_CHECK_EQUAL(duration, 0);

        // geometries=polyline by default
        const auto geometry = route_object.values.at("geometry").get<json::String>().value;
        BOOST_CHECK(!geometry.empty());

        const auto &legs = route_object.values.at("legs").get<json::Array>().values;
        BOOST_CHECK(!legs.empty());

        for (const auto &leg : legs)
        {
            const auto &leg_object = leg.get<json::Object>();

            const auto distance = leg_object.values.at("distance").get<json::Number>().value;
            BOOST_CHECK_EQUAL(distance, 0);

            const auto duration = leg_object.values.at("duration").get<json::Number>().value;
            BOOST_CHECK_EQUAL(duration, 0);

            // nothing can be said about summary, empty or contains human readable summary
            const auto summary = leg_object.values.at("summary").get<json::String>().value;
            BOOST_CHECK(((void)summary, true));

            const auto &steps = leg_object.values.at("steps").get<json::Array>().values;
            BOOST_CHECK(!steps.empty());

            std::size_t step_count = 0;

            for (const auto &step : steps)
            {
                const auto &step_object = step.get<json::Object>();

                const auto distance = step_object.values.at("distance").get<json::Number>().value;
                BOOST_CHECK_EQUAL(distance, 0);

                const auto duration = step_object.values.at("duration").get<json::Number>().value;
                BOOST_CHECK_EQUAL(duration, 0);

                // geometries=polyline by default
                const auto geometry = step_object.values.at("geometry").get<json::String>().value;
                BOOST_CHECK(!geometry.empty());

                // nothing can be said about name, empty or contains way name
                const auto name = step_object.values.at("name").get<json::String>().value;
                BOOST_CHECK(((void)name, true));

                // nothing can be said about mode, contains mode of transportation
                const auto mode = step_object.values.at("mode").get<json::String>().value;
                BOOST_CHECK(!name.empty());

                const auto &maneuver = step_object.values.at("maneuver").get<json::Object>().values;

                const auto type = maneuver.at("type").get<json::String>().value;
                BOOST_CHECK(!type.empty());

                const auto &intersections =
                    step_object.values.at("intersections").get<json::Array>().values;

                for (auto &intersection : intersections)
                {
                    const auto &intersection_object = intersection.get<json::Object>().values;
                    const auto location =
                        intersection_object.at("location").get<json::Array>().values;
                    const auto longitude = location[0].get<json::Number>().value;
                    const auto latitude = location[1].get<json::Number>().value;
                    BOOST_CHECK(longitude >= -180. && longitude <= 180.);
                    BOOST_CHECK(latitude >= -90. && latitude <= 90.);

                    const auto &bearings =
                        intersection_object.at("bearings").get<json::Array>().values;
                    BOOST_CHECK(!bearings.empty());
                    const auto &entries = intersection_object.at("entry").get<json::Array>().values;
                    BOOST_CHECK(bearings.size() == entries.size());

                    for (const auto bearing : bearings)
                        BOOST_CHECK(0. <= bearing.get<json::Number>().value &&
                                    bearing.get<json::Number>().value <= 360.);

                    if (step_count > 0)
                    {
                        const auto in = intersection_object.at("in").get<json::Number>().value;
                        BOOST_CHECK(in < bearings.size());
                    }
                    if (step_count + 1 < steps.size())
                    {
                        const auto out = intersection_object.at("out").get<json::Number>().value;
                        BOOST_CHECK(out < bearings.size());
                    }
                }

                // modifier is optional
                // TODO(daniel-j-h):

                // exit is optional
                // TODO(daniel-j-h):
                ++step_count;
            }
        }
    }
}

BOOST_AUTO_TEST_CASE(test_route_response_for_locations_in_small_component)
{
    const auto args = get_args();
    auto osrm = getOSRM(args.at(0));

    using namespace osrm;

    const auto locations = get_locations_in_small_component();

    RouteParameters params;
    params.coordinates.push_back(locations.at(0));
    params.coordinates.push_back(locations.at(1));
    params.coordinates.push_back(locations.at(2));

    json::Object result;
    const auto rc = osrm.Route(params, result);
    BOOST_CHECK(rc == Status::Ok);

    const auto code = result.values.at("code").get<json::String>().value;
    BOOST_CHECK_EQUAL(code, "Ok");

    const auto &waypoints = result.values.at("waypoints").get<json::Array>().values;
    BOOST_CHECK_EQUAL(waypoints.size(), params.coordinates.size());

    for (const auto &waypoint : waypoints)
    {
        const auto &waypoint_object = waypoint.get<json::Object>();

        const auto location = waypoint_object.values.at("location").get<json::Array>().values;
        const auto longitude = location[0].get<json::Number>().value;
        const auto latitude = location[1].get<json::Number>().value;
        BOOST_CHECK(longitude >= -180. && longitude <= 180.);
        BOOST_CHECK(latitude >= -90. && latitude <= 90.);
    }
}

BOOST_AUTO_TEST_CASE(test_route_response_for_locations_in_big_component)
{
    const auto args = get_args();
    auto osrm = getOSRM(args.at(0));

    using namespace osrm;

    const auto locations = get_locations_in_big_component();

    RouteParameters params;
    params.coordinates.push_back(locations.at(0));
    params.coordinates.push_back(locations.at(1));
    params.coordinates.push_back(locations.at(2));

    json::Object result;
    const auto rc = osrm.Route(params, result);
    BOOST_CHECK(rc == Status::Ok);

    const auto code = result.values.at("code").get<json::String>().value;
    BOOST_CHECK_EQUAL(code, "Ok");

    const auto &waypoints = result.values.at("waypoints").get<json::Array>().values;
    BOOST_CHECK_EQUAL(waypoints.size(), params.coordinates.size());

    for (const auto &waypoint : waypoints)
    {
        const auto &waypoint_object = waypoint.get<json::Object>();

        const auto location = waypoint_object.values.at("location").get<json::Array>().values;
        const auto longitude = location[0].get<json::Number>().value;
        const auto latitude = location[1].get<json::Number>().value;
        BOOST_CHECK(longitude >= -180. && longitude <= 180.);
        BOOST_CHECK(latitude >= -90. && latitude <= 90.);
    }
}

BOOST_AUTO_TEST_CASE(test_route_response_for_locations_across_components)
{
    const auto args = get_args();
    auto osrm = getOSRM(args.at(0));

    using namespace osrm;

    const auto big_component = get_locations_in_big_component();
    const auto small_component = get_locations_in_small_component();

    RouteParameters params;
    params.coordinates.push_back(small_component.at(0));
    params.coordinates.push_back(big_component.at(0));
    params.coordinates.push_back(small_component.at(1));
    params.coordinates.push_back(big_component.at(1));

    json::Object result;
    const auto rc = osrm.Route(params, result);
    BOOST_CHECK(rc == Status::Ok);

    const auto code = result.values.at("code").get<json::String>().value;
    BOOST_CHECK_EQUAL(code, "Ok");

    const auto &waypoints = result.values.at("waypoints").get<json::Array>().values;
    BOOST_CHECK_EQUAL(waypoints.size(), params.coordinates.size());

    for (const auto &waypoint : waypoints)
    {
        const auto &waypoint_object = waypoint.get<json::Object>();

        const auto location = waypoint_object.values.at("location").get<json::Array>().values;
        const auto longitude = location[0].get<json::Number>().value;
        const auto latitude = location[1].get<json::Number>().value;
        BOOST_CHECK(longitude >= -180. && longitude <= 180.);
        BOOST_CHECK(latitude >= -90. && latitude <= 90.);
    }
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2016 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include "catch.hpp"

#define DLL_SVM_SUPPORT

#include "dll/conv_rbm.hpp"
#include "dll/dbn.hpp"
#include "dll/rectifier_layer.hpp"
#include "dll/lcn_layer.hpp"
#include "dll/mp_layer.hpp"
#include "dll/avgp_layer.hpp"

#include "mnist/mnist_reader.hpp"
#include "mnist/mnist_utils.hpp"

TEST_CASE("unit/cdbn/lcn/mnist/1", "[cdbn][lcn][svm][unit]") {
    using dbn_t =
        dll::dbn_desc<dll::dbn_layers<
              dll::conv_rbm_desc_square<1, 28, 20, 12, dll::parallel_mode, dll::momentum, dll::batch_size<10>>::layer_t
            , dll::conv_rbm_desc_square<20, 12, 20, 10, dll::parallel_mode, dll::momentum, dll::batch_size<10>>::layer_t
            , dll::lcn_layer_desc<9>::layer_t
        >>::dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<double, 1, 28, 28>>(100);
    REQUIRE(!dataset.training_images.empty());

    mnist::binarize_dataset(dataset);

    auto dbn = std::make_unique<dbn_t>();

    dbn->display();

    dbn->pretrain(dataset.training_images, 20);

    auto result = dbn->svm_train(dataset.training_images, dataset.training_labels);
    REQUIRE(result);

    auto test_error = dll::test_set(dbn, dataset.training_images, dataset.training_labels, dll::svm_predictor());
    std::cout << "test_error:" << test_error << std::endl;
    REQUIRE(test_error < 0.1);
}

TEST_CASE("unit/cdbn/lcn/mnist/2", "[cdbn][lcn][svm][unit]") {
    using dbn_t =
        dll::dbn_desc<dll::dbn_layers<
              dll::conv_rbm_desc_square<1, 28, 20, 12, dll::parallel_mode, dll::momentum, dll::batch_size<10>>::layer_t
            , dll::rectifier_layer_desc<>::layer_t
            , dll::lcn_layer_desc<7>::layer_t
            , dll::conv_rbm_desc_square<20, 12, 20, 10, dll::visible<dll::unit_type::GAUSSIAN>, dll::parallel_mode, dll::momentum, dll::batch_size<10>>::layer_t
        >>::dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<double, 1, 28, 28>>(200);
    REQUIRE(!dataset.training_images.empty());

    mnist::binarize_dataset(dataset);

    auto dbn = std::make_unique<dbn_t>();

    dbn->display();

    dbn->template layer_get<3>().learning_rate *= 3.0;
    dbn->template layer_get<3>().initial_momentum = 0.9;
    dbn->template layer_get<3>().momentum = 0.9;

    dbn->pretrain(dataset.training_images, 50);

    auto result = dbn->svm_train(dataset.training_images, dataset.training_labels);
    REQUIRE(result);

    auto test_error = dll::test_set(dbn, dataset.training_images, dataset.training_labels, dll::svm_predictor());
    std::cout << "test_error:" << test_error << std::endl;
    REQUIRE(test_error < 0.5); //Note: This is not very stable
}

TEST_CASE("unit/cdbn/lcn/mnist/3", "[cdbn][lcn][svm][unit]") {
    using dbn_t =
        dll::dbn_desc<dll::dbn_layers<
              dll::conv_rbm_desc_square<1, 28, 20, 12, dll::parallel_mode, dll::momentum, dll::batch_size<10>>::layer_t
            , dll::conv_rbm_desc_square<20, 12, 20, 10, dll::parallel_mode, dll::momentum, dll::batch_size<10>>::layer_t
            , dll::rectifier_layer_desc<>::layer_t
            , dll::lcn_layer_desc<5>::layer_t
            , dll::mp_layer_3d_desc<20, 10, 10, 2, 2, 1>::layer_t
        >>::dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<double, 1, 28, 28>>(100);
    REQUIRE(!dataset.training_images.empty());

    mnist::binarize_dataset(dataset);

    auto dbn = std::make_unique<dbn_t>();

    dbn->display();

    dbn->pretrain(dataset.training_images, 20);

    auto result = dbn->svm_train(dataset.training_images, dataset.training_labels);
    REQUIRE(result);

    auto test_error = dll::test_set(dbn, dataset.training_images, dataset.training_labels, dll::svm_predictor());
    std::cout << "test_error:" << test_error << std::endl;
    REQUIRE(test_error < 0.1);
}

TEST_CASE("unit/cdbn/lcn/mnist/4", "[cdbn][lcn][svm][unit]") {
    using dbn_t =
        dll::dbn_desc<dll::dbn_layers<
              dll::conv_rbm_desc_square<1, 28, 20, 12, dll::parallel_mode, dll::momentum, dll::batch_size<10>>::layer_t
            , dll::conv_rbm_desc_square<20, 12, 20, 10, dll::parallel_mode, dll::momentum, dll::batch_size<10>>::layer_t
            , dll::rectifier_layer_desc<>::layer_t
            , dll::lcn_layer_desc<5>::layer_t
            , dll::avgp_layer_3d_desc<20, 10, 10, 2, 2, 1>::layer_t
        >>::dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<double, 1, 28, 28>>(100);
    REQUIRE(!dataset.training_images.empty());

    mnist::binarize_dataset(dataset);

    auto dbn = std::make_unique<dbn_t>();

    dbn->display();

    dbn->pretrain(dataset.training_images, 20);

    auto result = dbn->svm_train(dataset.training_images, dataset.training_labels);
    REQUIRE(result);

    auto test_error = dll::test_set(dbn, dataset.training_images, dataset.training_labels, dll::svm_predictor());
    std::cout << "test_error:" << test_error << std::endl;
    REQUIRE(test_error < 0.1);
}

TEST_CASE("unit/cdbn/lcn/mnist/5", "[cdbn][lcn][svm][unit]") {
    using dbn_t =
        dll::dbn_desc<dll::dbn_layers<
              dll::conv_rbm_desc_square<1, 28, 20, 12, dll::parallel_mode, dll::momentum, dll::batch_size<10>>::layer_t
            , dll::conv_rbm_desc_square<20, 12, 20, 10, dll::parallel_mode, dll::momentum, dll::batch_size<10>>::layer_t
            , dll::rectifier_layer_desc<>::layer_t
            , dll::lcn_layer_desc<7>::layer_t
            , dll::avgp_layer_3d_desc<20, 10, 10, 2, 2, 1>::layer_t
        >>::dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<double, 1, 28, 28>>(150);
    REQUIRE(!dataset.training_images.empty());

    mnist::binarize_dataset(dataset);

    auto dbn = std::make_unique<dbn_t>();

    dbn->template layer_get<3>().sigma = 2.0;

    dbn->display();

    dbn->pretrain(dataset.training_images, 20);

    auto result = dbn->svm_train(dataset.training_images, dataset.training_labels);
    REQUIRE(result);

    auto test_error = dll::test_set(dbn, dataset.training_images, dataset.training_labels, dll::svm_predictor());
    std::cout << "test_error:" << test_error << std::endl;
    REQUIRE(test_error < 0.2);
}

TEST_CASE("unit/cdbn/lcn/mnist/6", "[cdbn][lcn][unit]") {
    using dbn_t =
        dll::dbn_desc<dll::dbn_layers<
              dll::conv_rbm_desc_square<1, 28, 20, 12, dll::parallel_mode, dll::momentum, dll::batch_size<10>>::layer_t
            , dll::lcn_layer_desc<7>::layer_t
            , dll::avgp_layer_3d_desc<20, 12, 12, 2, 2, 1>::layer_t
            , dll::conv_rbm_desc_square<20, 6, 20, 4, dll::parallel_mode, dll::momentum, dll::batch_size<10>>::layer_t
            , dll::lcn_layer_desc<3>::layer_t
            , dll::avgp_layer_3d_desc<20, 4, 4, 2, 2, 1>::layer_t
        >>::dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<double, 1, 28, 28>>(150);
    REQUIRE(!dataset.training_images.empty());

    mnist::binarize_dataset(dataset);

    auto dbn = std::make_unique<dbn_t>();

    dbn->display();

    dbn->pretrain(dataset.training_images, 20);
}
<commit_msg>More tests<commit_after>//=======================================================================
// Copyright (c) 2014-2016 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include "catch.hpp"

#define DLL_SVM_SUPPORT

#include "dll/conv_rbm.hpp"
#include "dll/dbn.hpp"
#include "dll/rectifier_layer.hpp"
#include "dll/lcn_layer.hpp"
#include "dll/mp_layer.hpp"
#include "dll/avgp_layer.hpp"

#include "mnist/mnist_reader.hpp"
#include "mnist/mnist_utils.hpp"

TEST_CASE("unit/cdbn/lcn/mnist/1", "[cdbn][lcn][svm][unit]") {
    using dbn_t =
        dll::dbn_desc<dll::dbn_layers<
              dll::conv_rbm_desc_square<1, 28, 20, 12, dll::parallel_mode, dll::momentum, dll::batch_size<10>>::layer_t
            , dll::conv_rbm_desc_square<20, 12, 20, 10, dll::parallel_mode, dll::momentum, dll::batch_size<10>>::layer_t
            , dll::lcn_layer_desc<9>::layer_t
        >>::dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<double, 1, 28, 28>>(100);
    REQUIRE(!dataset.training_images.empty());

    mnist::binarize_dataset(dataset);

    auto dbn = std::make_unique<dbn_t>();

    dbn->display();

    dbn->pretrain(dataset.training_images, 20);

    auto result = dbn->svm_train(dataset.training_images, dataset.training_labels);
    REQUIRE(result);

    auto test_error = dll::test_set(dbn, dataset.training_images, dataset.training_labels, dll::svm_predictor());
    std::cout << "test_error:" << test_error << std::endl;
    REQUIRE(test_error < 0.1);
}

TEST_CASE("unit/cdbn/lcn/mnist/2", "[cdbn][lcn][svm][unit]") {
    using dbn_t =
        dll::dbn_desc<dll::dbn_layers<
              dll::conv_rbm_desc_square<1, 28, 20, 12, dll::parallel_mode, dll::momentum, dll::batch_size<10>>::layer_t
            , dll::rectifier_layer_desc<>::layer_t
            , dll::lcn_layer_desc<7>::layer_t
            , dll::conv_rbm_desc_square<20, 12, 20, 10, dll::visible<dll::unit_type::GAUSSIAN>, dll::parallel_mode, dll::momentum, dll::batch_size<10>>::layer_t
        >>::dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<double, 1, 28, 28>>(200);
    REQUIRE(!dataset.training_images.empty());

    mnist::binarize_dataset(dataset);

    auto dbn = std::make_unique<dbn_t>();

    dbn->display();

    dbn->template layer_get<3>().learning_rate *= 3.0;
    dbn->template layer_get<3>().initial_momentum = 0.9;
    dbn->template layer_get<3>().momentum = 0.9;

    dbn->pretrain(dataset.training_images, 50);

    auto result = dbn->svm_train(dataset.training_images, dataset.training_labels);
    REQUIRE(result);

    auto test_error = dll::test_set(dbn, dataset.training_images, dataset.training_labels, dll::svm_predictor());
    std::cout << "test_error:" << test_error << std::endl;
    REQUIRE(test_error < 0.5); //Note: This is not very stable
}

TEST_CASE("unit/cdbn/lcn/mnist/3", "[cdbn][lcn][svm][unit]") {
    using dbn_t =
        dll::dbn_desc<dll::dbn_layers<
              dll::conv_rbm_desc_square<1, 28, 20, 12, dll::parallel_mode, dll::momentum, dll::batch_size<10>>::layer_t
            , dll::conv_rbm_desc_square<20, 12, 20, 10, dll::parallel_mode, dll::momentum, dll::batch_size<10>>::layer_t
            , dll::rectifier_layer_desc<>::layer_t
            , dll::lcn_layer_desc<5>::layer_t
            , dll::mp_layer_3d_desc<20, 10, 10, 2, 2, 1>::layer_t
        >>::dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<double, 1, 28, 28>>(100);
    REQUIRE(!dataset.training_images.empty());

    mnist::binarize_dataset(dataset);

    auto dbn = std::make_unique<dbn_t>();

    dbn->display();

    dbn->pretrain(dataset.training_images, 20);

    auto result = dbn->svm_train(dataset.training_images, dataset.training_labels);
    REQUIRE(result);

    auto test_error = dll::test_set(dbn, dataset.training_images, dataset.training_labels, dll::svm_predictor());
    std::cout << "test_error:" << test_error << std::endl;
    REQUIRE(test_error < 0.1);
}

TEST_CASE("unit/cdbn/lcn/mnist/4", "[cdbn][lcn][svm][unit]") {
    using dbn_t =
        dll::dbn_desc<dll::dbn_layers<
              dll::conv_rbm_desc_square<1, 28, 20, 12, dll::parallel_mode, dll::momentum, dll::batch_size<10>>::layer_t
            , dll::conv_rbm_desc_square<20, 12, 20, 10, dll::parallel_mode, dll::momentum, dll::batch_size<10>>::layer_t
            , dll::rectifier_layer_desc<>::layer_t
            , dll::lcn_layer_desc<5>::layer_t
            , dll::avgp_layer_3d_desc<20, 10, 10, 2, 2, 1>::layer_t
        >>::dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<double, 1, 28, 28>>(100);
    REQUIRE(!dataset.training_images.empty());

    mnist::binarize_dataset(dataset);

    auto dbn = std::make_unique<dbn_t>();

    dbn->display();

    dbn->pretrain(dataset.training_images, 20);

    auto result = dbn->svm_train(dataset.training_images, dataset.training_labels);
    REQUIRE(result);

    auto test_error = dll::test_set(dbn, dataset.training_images, dataset.training_labels, dll::svm_predictor());
    std::cout << "test_error:" << test_error << std::endl;
    REQUIRE(test_error < 0.1);
}

TEST_CASE("unit/cdbn/lcn/mnist/5", "[cdbn][lcn][svm][unit]") {
    using dbn_t =
        dll::dbn_desc<dll::dbn_layers<
              dll::conv_rbm_desc_square<1, 28, 20, 12, dll::parallel_mode, dll::momentum, dll::batch_size<10>>::layer_t
            , dll::conv_rbm_desc_square<20, 12, 20, 10, dll::parallel_mode, dll::momentum, dll::batch_size<10>>::layer_t
            , dll::rectifier_layer_desc<>::layer_t
            , dll::lcn_layer_desc<7>::layer_t
            , dll::avgp_layer_3d_desc<20, 10, 10, 2, 2, 1>::layer_t
        >>::dbn_t;

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<double, 1, 28, 28>>(150);
    REQUIRE(!dataset.training_images.empty());

    mnist::binarize_dataset(dataset);

    auto dbn = std::make_unique<dbn_t>();

    dbn->template layer_get<3>().sigma = 2.0;

    dbn->display();

    dbn->pretrain(dataset.training_images, 20);

    auto result = dbn->svm_train(dataset.training_images, dataset.training_labels);
    REQUIRE(result);

    auto test_error = dll::test_set(dbn, dataset.training_images, dataset.training_labels, dll::svm_predictor());
    std::cout << "test_error:" << test_error << std::endl;
    REQUIRE(test_error < 0.2);
}

TEST_CASE("unit/cdbn/lcn/mnist/6", "[cdbn][lcn][unit]") {
    using dbn_t =
        dll::dbn_desc<dll::dbn_layers<
              dll::conv_rbm_desc_square<1, 28, 20, 12, dll::parallel_mode, dll::momentum, dll::batch_size<10>>::layer_t
            , dll::lcn_layer_desc<5>::layer_t
            , dll::avgp_layer_3d_desc<20, 12, 12, 2, 2, 1>::layer_t
            , dll::conv_rbm_desc_square<20, 6, 20, 4, dll::parallel_mode, dll::momentum, dll::batch_size<10>>::layer_t
            , dll::lcn_layer_desc<3>::layer_t
            , dll::avgp_layer_3d_desc<20, 4, 4, 2, 2, 1>::layer_t
        >>::dbn_t;

    REQUIRE(!dll::layer_traits<dbn_t::layer_type<1>>::is_pretrained());
    REQUIRE(!dll::layer_traits<dbn_t::layer_type<1>>::is_trained());
    REQUIRE(!dll::layer_traits<dbn_t::layer_type<2>>::is_pretrained());
    REQUIRE(!dll::layer_traits<dbn_t::layer_type<2>>::is_trained());

    auto dataset = mnist::read_dataset_direct<std::vector, etl::fast_dyn_matrix<double, 1, 28, 28>>(150);
    REQUIRE(!dataset.training_images.empty());

    mnist::binarize_dataset(dataset);

    auto dbn = std::make_unique<dbn_t>();

    dbn->template layer_get<1>().sigma = 1.0;
    dbn->template layer_get<4>().sigma = 1.0;

    dbn->display();

    dbn->pretrain(dataset.training_images, 20);
}
<|endoftext|>


<commit_before><commit_msg>fdo63235 - correct usage of marker-start/-end for svg path data<commit_after><|endoftext|>