<commit_before>/* Copyright (c) 2015 In Cheol, Kang
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:

 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "eznetpp.h"
#include "net/tcp/tcp_acceptor.h"
#include "net/tcp/tcp_socket.h"
#include "sys/io_manager.h"

eznetpp::sys::io_manager g_io_mgr(4, true);

void sig_handler(int signum) {
  g_io_mgr.stop();
}

class tcp_echosvr_session : public eznetpp::event::tcp_socket_event_handler
{
 public:
  tcp_echosvr_session(eznetpp::net::tcp::tcp_socket* sock)
  {
    _socket = sock;
  }
  virtual ~tcp_echosvr_session() = default;

 public:
  // override
  void on_recv(const std::string& msg, int len)
  {
    //printf("received %d bytes\n", len);
    ++recv_num;
    //if (recv_num % 1000 == 0)
    //  printf("[%d] received %d\n", _socket->descriptor(), recv_num);

    _socket->send_bytes(msg);
  }

  void on_send(unsigned int len)
  {
    //printf("sent %d bytes\n", len);
    ++send_num;
    //if (send_num % 1000 == 0)
    //  printf("[%d] sent %d\n", _socket->descriptor(), send_num);
  }

  void on_close(int err_no)
  {
    printf("closed the session(%d)\n", err_no);
  }

  void on_connect(int err_no)
  {
    // do not need
  };

 private:
  eznetpp::net::tcp::tcp_socket* _socket;
  unsigned int recv_num = 0;
  unsigned int send_num = 0;
};

class tcp_echo_server : public eznetpp::event::tcp_acceptor_event_handler
{
 public:
  tcp_echo_server(eznetpp::sys::io_manager* io_mgr)
  {
    _io_mgr = io_mgr;
  }
  virtual ~tcp_echo_server() = default;

  int open(int port, int backlog)
  {
    int ret = _acceptor.open(port, backlog);

    if (ret)
    {
      printf("%s\n", eznetpp::errcode::errno_to_str(ret).c_str());
      return -1;
    }

    _io_mgr->register_socket_event_handler(&_acceptor, this);

    return 0;
  }

  // override
  void on_accept(eznetpp::net::tcp::tcp_socket* sock, int err_no)
  {
    printf("on_accept\n");
    _io_mgr->register_socket_event_handler(sock, new tcp_echosvr_session(sock));
  }

  void on_close(int err_no)
  {
    printf("closed the acceptor(%d)\n", err_no);
  }

 private:
  eznetpp::sys::io_manager* _io_mgr = nullptr;
  eznetpp::net::tcp::tcp_acceptor _acceptor;
};

int main(void)
{
  signal(SIGINT, sig_handler);

  g_io_mgr.init();

  tcp_echo_server server(&g_io_mgr);
  server.open(56789, 5);

  g_io_mgr.loop();

  return 0;
}
<commit_msg>* update<commit_after>/* Copyright (c) 2015 In Cheol, Kang
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:

 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "eznetpp.h"
#include "net/tcp/tcp_acceptor.h"
#include "net/tcp/tcp_socket.h"
#include "sys/io_manager.h"

eznetpp::sys::io_manager g_io_mgr(false);

void sig_handler(int signum) {
  g_io_mgr.stop();
}

class tcp_echosvr_session : public eznetpp::event::tcp_socket_event_handler
{
 public:
  tcp_echosvr_session(eznetpp::net::tcp::tcp_socket* sock)
  {
    _socket = sock;
  }
  virtual ~tcp_echosvr_session() = default;

 public:
  // override
  void on_recv(const std::string& msg, int len)
  {
    //printf("received %d bytes\n", len);
    ++recv_num;
    //if (recv_num % 1000 == 0)
    //  printf("[%d] received %d\n", _socket->descriptor(), recv_num);

    _socket->send_bytes(msg);
  }

  void on_send(unsigned int len)
  {
    //printf("sent %d bytes\n", len);
    ++send_num;
    //if (send_num % 1000 == 0)
    //  printf("[%d] sent %d\n", _socket->descriptor(), send_num);
  }

  void on_close(int err_no)
  {
    printf("closed the session(%d)\n", err_no);
  }

  void on_connect(int err_no)
  {
    // do not need
  };

 private:
  eznetpp::net::tcp::tcp_socket* _socket;
  unsigned int recv_num = 0;
  unsigned int send_num = 0;
};

class tcp_echo_server : public eznetpp::event::tcp_acceptor_event_handler
{
 public:
  tcp_echo_server(eznetpp::sys::io_manager* io_mgr)
  {
    _io_mgr = io_mgr;
  }
  virtual ~tcp_echo_server() = default;

  int open(int port, int backlog)
  {
    int ret = _acceptor.open(port, backlog);

    if (ret)
    {
      printf("%s\n", eznetpp::errcode::errno_to_str(ret).c_str());
      return -1;
    }

    _io_mgr->register_socket_event_handler(&_acceptor, this);

    return 0;
  }

  // override
  void on_accept(eznetpp::net::tcp::tcp_socket* sock, int err_no)
  {
    printf("on_accept\n");
    _io_mgr->register_socket_event_handler(sock, new tcp_echosvr_session(sock));
  }

  void on_close(int err_no)
  {
    printf("closed the acceptor(%d)\n", err_no);
  }

 private:
  eznetpp::sys::io_manager* _io_mgr = nullptr;
  eznetpp::net::tcp::tcp_acceptor _acceptor;
};

int main(void)
{
  signal(SIGINT, sig_handler);

  g_io_mgr.init();

  tcp_echo_server server(&g_io_mgr);
  server.open(56789, 5);

  g_io_mgr.loop();

  return 0;
}
<|endoftext|>


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

#include <string>
#include <cmath>
#include <x86intrin.h>

#include <utils.hpp>
#include <Observation.hpp>

#ifndef SNR_HPP
#define SNR_HPP

namespace PulsarSearch {

template< typename T > using snrFunc = void (*)(const AstroData::Observation< T > &, const float *, float *);

// Sequential SNR
template< typename T > void snrFoldedTS(const AstroData::Observation< T > & observation, const std::vector< T > & foldedTS, std::vector< T > & snrs);
// OpenCL SNR
template< typename T > std::string * getSNROpenCL(const unsigned int nrDMsPerBlock, const unsigned int nrPeriodsPerBlock, const unsigned int nrDMsPerThread, const unsigned int nrPeriodsPerThread, std::string & dataType, const AstroData::Observation< T > & observation);
// SIMD SNR
std::string * getSNRSIMD(const unsigned int nrDMsPerThread, const unsigned int nrPeriodsPerThread, bool phi = false);

// Implementations
template< typename T > void snrFoldedTS(AstroData::Observation< T > & observation, const std::vector< T > & foldedTS, std::vector< T > & snrs) {
	for ( unsigned int period = 0; period < observation.getNrPeriods(); period++ ) {
		for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm++ ) {
			T max = 0;
			float average = 0.0f;
			float rms = 0.0f;

			for ( unsigned int bin = 0; bin < observation.getNrBins(); bin++ ) {
				T value = foldedTS[(bin * observation.getNrPeriods() * observation.getNrPaddedDMs()) + (period * observation.getNrPaddedDMs()) + dm];

				average += value;
				rms += (value * value);

				if ( value > max ) {
					max = value;
				}
			}
			average /= observation.getNrBins();
			rms = std::sqrt(rms / observation.getNrBins());

			snrs[(period * observation.getNrPaddedDMs()) + dm] = (max - average) / rms;
		}
	}
}

template< typename T > std::string * getSNROpenCL(const unsigned int nrDMsPerBlock, const unsigned int nrPeriodsPerBlock, const unsigned int nrDMsPerThread, const unsigned int nrPeriodsPerThread, std::string & dataType, const AstroData::Observation< T > & observation) {
  std::string * code = new std::string();

  // Begin kernel's template
  std::string nrPaddedDMs_s = isa::utils::toString< unsigned int >(observation.getNrPaddedDMs());
  std::string nrBinsInverse_s = isa::utils::toString< float >(1.0f / observation.getNrBins());

  *code = "__kernel void snr(__global const " + dataType + " * const restrict foldedData, __global " + dataType + " * const restrict snrs) {\n"
    "<%DEF_DM%>"
    "<%DEF_PERIOD%>"
    + dataType + " globalItem = 0;\n"
    + dataType + " average = 0;\n"
    + dataType + " rms = 0;\n"
    + dataType + " max = 0;\n"
    "\n"
    "<%COMPUTE%>"
    "}\n";
    std::string defDMsTemplate = "const unsigned int dm<%DM_NUM%> = (get_group_id(0) * " + isa::utils::toString< unsigned int >(nrDMsPerBlock * nrDMsPerThread) + ") + get_local_id(0) + <%DM_NUM%>;\n";
  std::string defPeriodsTemplate = "const unsigned int period<%PERIOD_NUM%> = (get_group_id(1) * " + isa::utils::toString< unsigned int >(nrPeriodsPerBlock * nrPeriodsPerThread) + ") + get_local_id(1) + <%PERIOD_NUM%>;\n";
  std::string computeTemplate = "average = 0;\n"
    "rms = 0;\n"
    "max = 0;\n"
    "for ( unsigned int bin = 0; bin < " + isa::utils::toString< unsigned int >(observation.getNrBins()) + "; bin++ ) {\n"
    "globalItem = foldedData[(bin * " + isa::utils::toString< unsigned int >(observation.getNrPeriods()) + " * " + nrPaddedDMs_s + ") + (period<%PERIOD_NUM%> * " + nrPaddedDMs_s + ") + dm<%DM_NUM%>];\n"
    "average += globalItem;\n"
    "rms += (globalItem * globalItem);\n"
    "max = fmax(max, globalItem);\n"
    "}\n"
    "average *= " + nrBinsInverse_s + "f;\n"
    "rms *= " + nrBinsInverse_s + "f;\n"
    "snrs[(period<%PERIOD_NUM%> * " + nrPaddedDMs_s + ") + dm<%DM_NUM%>] = (max - average) / native_sqrt(rms);\n";
  // End kernel's template

  std::string * defDM_s = new std::string();
  std::string * defPeriod_s = new std::string();
  std::string * compute_s = new std::string();

  for ( unsigned int dm = 0; dm < nrDMsPerThread; dm++ ) {
    std::string dm_s = isa::utils::toString< unsigned int >(dm);
    std::string * temp_s = 0;

    temp_s = isa::utils::replace(&defDMsTemplate, "<%DM_NUM%>", dm_s);
    defDM_s->append(*temp_s);
    delete temp_s;
  }
  for ( unsigned int period = 0; period < nrPeriodsPerThread; period++ ) {
    std::string period_s = isa::utils::toString< unsigned int >(period);
    std::string * temp_s = 0;

    temp_s = isa::utils::replace(&defPeriodsTemplate, "<%PERIOD_NUM%>", period_s);
    defPeriod_s->append(*temp_s);
    delete temp_s;

    for ( unsigned int dm = 0; dm < nrDMsPerThread; dm++ ) {
      std::string dm_s = isa::utils::toString< unsigned int >(dm);

      temp_s = isa::utils::replace(&computeTemplate, "<%PERIOD_NUM%>", period_s);
      temp_s = isa::utils::replace(temp_s, "<%DM_NUM%>", dm_s, true);
      compute_s->append(*temp_s);
      delete temp_s;
    }
  }

  code = isa::utils::replace(code, "<%DEF_DM%>", *defDM_s, true);
  code = isa::utils::replace(code, "<%DEF_PERIOD%>", *defPeriod_s, true);
  code = isa::utils::replace(code, "<%COMPUTE%>", *compute_s, true);

  return code;
}

std::string * getSNRSIMD(const unsigned int nrDMsPerThread, const unsigned int nrPeriodsPerThread, bool phi) {
  std::string * code = new std::string();
  std::string * computeTemplate = new std::string();

  // Begin kernel's template
  if ( !phi ) {
    *code = "namespace PulsarSearch {\n"
      "template< typename T > void snrAVX" + isa::utils::toString(nrDMsPerThread) + "x" + isa::utils::toString(nrPeriodsPerThread) + "(const AstroData::Observation< T > & observation, const float * const __restrict__ foldedData, float * const __restrict__ snrs) {\n"
      "{\n"
      "__m256 max = _mm256_setzero_ps();\n"
      "__m256 average = _mm256_setzero_ps();\n"
      "__m256 rms = _mm256_setzero_ps();\n"
      "#pragma omp parallel for schedule(static)\n"
      "for ( unsigned int period = 0; period < observation.getNrPeriods(); period += " + isa::utils::toString(nrPeriodsPerThread) + ") {\n"
      "#pragma omp parallel for schedule(static)\n"
      "for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm += " + isa::utils::toString(nrPeriodsPerThread) + " * 8) {\n"
      "<%COMPUTE%>"
      "}\n"
      "}\n"
      "}\n"
      "}\n"
      "}\n";
    *computeTemplate = "max = _mm256_setzero_ps();\n"
      "average = _mm256_setzero_ps();\n"
      "rms = _mm256_setzero_ps();\n"
      "\n"
      "for ( unsigned int bin = 0; bin < observation.getNrBins(); bin++ ) {\n"
      "__m256 value = _mm256_load_ps(&(foldedData[(bin * observation.getNrPeriods() * observation.getNrPaddedDMs()) + ((period + <%PERIOD_NUM%>) * observation.getNrPaddedDMs()) + dm + <%DM_NUM%>]));\n"
      "\n"
      "average = _mm256_add_ps(average, value);\n"
      "rms = _mm256_add_ps(rms, _mm256_mul_ps(value, value));\n"
      "max = _mm256_max_ps(max, value);\n"
      "}\n"
      "average = _mm256_div_ps(average, _mm256_set1_ps(observation.getNrBins()));\n"
      "rms = _mm256_sqrt_ps(_mm256_div_ps(rms, _mm256_set1_ps(observation.getNrBins())));\n"
      "_mm256_store_ps(&(snrs[((period + <%PERIOD_NUM%>) * observation.getNrPaddedDMs()) + dm + <%DM_NUM%>]),_mm256_div_ps(_mm256_sub_ps(max, average), rms));\n";
  } else {
    *code = "namespace PulsarSearch {\n"
      "template< typename T > void snrPhi" + isa::utils::toString(nrDMsPerThread) + "x" + isa::utils::toString(nrPeriodsPerThread) + "(const AstroData::Observation< T > & observation, const float * const __restrict__ foldedData, float * const __restrict__ snrs) {\n"
      "{\n"
      "__m512 max = _mm512_setzero_ps();\n"
      "__m512 average = _mm512_setzero_ps();\n"
      "__m512 rms = _mm512_setzero_ps();\n"
      "#pragma omp parallel for schedule(static)\n"
      "for ( unsigned int period = 0; period < observation.getNrPeriods(); period += " + isa::utils::toString(nrPeriodsPerThread) + ") {\n"
      "#pragma omp parallel for schedule(static)\n"
      "for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm += " + isa::utils::toString(nrPeriodsPerThread) + " * 16) {\n"
      "<%COMPUTE%>"
      "}\n"
      "}\n"
      "}\n"
      "}\n"
      "}\n";
    *computeTemplate = "max = _mm512_setzero_ps();\n"
      "average = _mm512_setzero_ps();\n"
      "rms = _mm512_setzero_ps();\n"
      "\n"
      "for ( unsigned int bin = 0; bin < observation.getNrBins(); bin++ ) {\n"
      "__m512 value = _mm512_load_ps(&(foldedData[(bin * observation.getNrPeriods() * observation.getNrPaddedDMs()) + ((period + <%PERIOD_NUM%>) * observation.getNrPaddedDMs()) + dm + <%DM_NUM%>]));\n"
      "\n"
      "average = _mm512_add_ps(average, value);\n"
      "rms = _mm512_add_ps(rms, _mm512_mul_ps(value, value));\n"
      "max = _mm512_max_ps(max, value);\n"
      "}\n"
      "average = _mm512_div_ps(average, _mm512_set1_ps(observation.getNrBins()));\n"
      "rms = _mm512_sqrt_ps(_mm512_div_ps(rms, _mm512_set1_ps(observation.getNrBins())));\n"
      "_mm512_store_ps(&(snrs[((period + <%PERIOD_NUM%>) * observation.getNrPaddedDMs()) + dm + <%DM_NUM%>]),_mm512_div_ps(_mm512_sub_ps(max, average), rms));\n";
  }
  // End kernel's template

  std::string * compute_s = new std::string();

  for ( unsigned int period = 0; period < nrPeriodsPerThread; period++ ) {
    std::string period_s = isa::utils::toString< unsigned int >(period);

    for ( unsigned int dm = 0; dm < nrDMsPerThread; dm++ ) {
      std::string dm_s = isa::utils::toString< unsigned int >(dm);
      std::string * temp_s = 0;

      temp_s = isa::utils::replace(computeTemplate, "<%PERIOD_NUM%>", period_s);
      temp_s = isa::utils::replace(temp_s, "<%DM_NUM%>", dm_s, true);
      compute_s->append(*temp_s);
      delete temp_s;
    }
  }
  code = isa::utils::replace(code, "<%COMPUTE%>", *compute_s, true);
  delete compute_s;

  delete computeTemplate;
  return code;
}

} // PulsarSearch

#endif // SNR_HPP

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

#include <string>
#include <cmath>
#include <x86intrin.h>

#include <utils.hpp>
#include <Observation.hpp>

#ifndef SNR_HPP
#define SNR_HPP

namespace PulsarSearch {

template< typename T > using snrFunc = void (*)(const AstroData::Observation &, const float *, float *);

// Sequential SNR
template< typename T > void snrFoldedTS(const AstroData::Observation & observation, const std::vector< T > & foldedTS, std::vector< T > & snrs);
// OpenCL SNR
std::string * getSNROpenCL(const unsigned int nrDMsPerBlock, const unsigned int nrPeriodsPerBlock, const unsigned int nrDMsPerThread, const unsigned int nrPeriodsPerThread, std::string & dataType, const AstroData::Observation & observation);
// SIMD SNR
std::string * getSNRSIMD(const unsigned int nrDMsPerThread, const unsigned int nrPeriodsPerThread, bool phi = false);

// Implementations
template< typename T > void snrFoldedTS(AstroData::Observation & observation, const std::vector< T > & foldedTS, std::vector< T > & snrs) {
	for ( unsigned int period = 0; period < observation.getNrPeriods(); period++ ) {
		for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm++ ) {
			T max = 0;
			float average = 0.0f;
			float rms = 0.0f;

			for ( unsigned int bin = 0; bin < observation.getNrBins(); bin++ ) {
				T value = foldedTS[(bin * observation.getNrPeriods() * observation.getNrPaddedDMs()) + (period * observation.getNrPaddedDMs()) + dm];

				average += value;
				rms += (value * value);

				if ( value > max ) {
					max = value;
				}
			}
			average /= observation.getNrBins();
			rms = std::sqrt(rms / observation.getNrBins());

			snrs[(period * observation.getNrPaddedDMs()) + dm] = (max - average) / rms;
		}
	}
}

std::string * getSNROpenCL(const unsigned int nrDMsPerBlock, const unsigned int nrPeriodsPerBlock, const unsigned int nrDMsPerThread, const unsigned int nrPeriodsPerThread, std::string & dataType, const AstroData::Observation & observation) {
  std::string * code = new std::string();

  // Begin kernel's template
  std::string nrPaddedDMs_s = isa::utils::toString< unsigned int >(observation.getNrPaddedDMs());
  std::string nrBinsInverse_s = isa::utils::toString< float >(1.0f / observation.getNrBins());

  *code = "__kernel void snr(__global const " + dataType + " * const restrict foldedData, __global " + dataType + " * const restrict snrs) {\n"
    "<%DEF_DM%>"
    "<%DEF_PERIOD%>"
    + dataType + " globalItem = 0;\n"
    + dataType + " average = 0;\n"
    + dataType + " rms = 0;\n"
    + dataType + " max = 0;\n"
    "\n"
    "<%COMPUTE%>"
    "}\n";
    std::string defDMsTemplate = "const unsigned int dm<%DM_NUM%> = (get_group_id(0) * " + isa::utils::toString< unsigned int >(nrDMsPerBlock * nrDMsPerThread) + ") + get_local_id(0) + <%DM_NUM%>;\n";
  std::string defPeriodsTemplate = "const unsigned int period<%PERIOD_NUM%> = (get_group_id(1) * " + isa::utils::toString< unsigned int >(nrPeriodsPerBlock * nrPeriodsPerThread) + ") + get_local_id(1) + <%PERIOD_NUM%>;\n";
  std::string computeTemplate = "average = 0;\n"
    "rms = 0;\n"
    "max = 0;\n"
    "for ( unsigned int bin = 0; bin < " + isa::utils::toString< unsigned int >(observation.getNrBins()) + "; bin++ ) {\n"
    "globalItem = foldedData[(bin * " + isa::utils::toString< unsigned int >(observation.getNrPeriods()) + " * " + nrPaddedDMs_s + ") + (period<%PERIOD_NUM%> * " + nrPaddedDMs_s + ") + dm<%DM_NUM%>];\n"
    "average += globalItem;\n"
    "rms += (globalItem * globalItem);\n"
    "max = fmax(max, globalItem);\n"
    "}\n"
    "average *= " + nrBinsInverse_s + "f;\n"
    "rms *= " + nrBinsInverse_s + "f;\n"
    "snrs[(period<%PERIOD_NUM%> * " + nrPaddedDMs_s + ") + dm<%DM_NUM%>] = (max - average) / native_sqrt(rms);\n";
  // End kernel's template

  std::string * defDM_s = new std::string();
  std::string * defPeriod_s = new std::string();
  std::string * compute_s = new std::string();

  for ( unsigned int dm = 0; dm < nrDMsPerThread; dm++ ) {
    std::string dm_s = isa::utils::toString< unsigned int >(dm);
    std::string * temp_s = 0;

    temp_s = isa::utils::replace(&defDMsTemplate, "<%DM_NUM%>", dm_s);
    defDM_s->append(*temp_s);
    delete temp_s;
  }
  for ( unsigned int period = 0; period < nrPeriodsPerThread; period++ ) {
    std::string period_s = isa::utils::toString< unsigned int >(period);
    std::string * temp_s = 0;

    temp_s = isa::utils::replace(&defPeriodsTemplate, "<%PERIOD_NUM%>", period_s);
    defPeriod_s->append(*temp_s);
    delete temp_s;

    for ( unsigned int dm = 0; dm < nrDMsPerThread; dm++ ) {
      std::string dm_s = isa::utils::toString< unsigned int >(dm);

      temp_s = isa::utils::replace(&computeTemplate, "<%PERIOD_NUM%>", period_s);
      temp_s = isa::utils::replace(temp_s, "<%DM_NUM%>", dm_s, true);
      compute_s->append(*temp_s);
      delete temp_s;
    }
  }

  code = isa::utils::replace(code, "<%DEF_DM%>", *defDM_s, true);
  code = isa::utils::replace(code, "<%DEF_PERIOD%>", *defPeriod_s, true);
  code = isa::utils::replace(code, "<%COMPUTE%>", *compute_s, true);

  return code;
}

std::string * getSNRSIMD(const unsigned int nrDMsPerThread, const unsigned int nrPeriodsPerThread, bool phi) {
  std::string * code = new std::string();
  std::string * computeTemplate = new std::string();

  // Begin kernel's template
  if ( !phi ) {
    *code = "namespace PulsarSearch {\n"
      "template< typename T > void snrAVX" + isa::utils::toString(nrDMsPerThread) + "x" + isa::utils::toString(nrPeriodsPerThread) + "(const AstroData::Observation & observation, const float * const __restrict__ foldedData, float * const __restrict__ snrs) {\n"
      "{\n"
      "__m256 max = _mm256_setzero_ps();\n"
      "__m256 average = _mm256_setzero_ps();\n"
      "__m256 rms = _mm256_setzero_ps();\n"
      "#pragma omp parallel for schedule(static)\n"
      "for ( unsigned int period = 0; period < observation.getNrPeriods(); period += " + isa::utils::toString(nrPeriodsPerThread) + ") {\n"
      "#pragma omp parallel for schedule(static)\n"
      "for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm += " + isa::utils::toString(nrPeriodsPerThread) + " * 8) {\n"
      "<%COMPUTE%>"
      "}\n"
      "}\n"
      "}\n"
      "}\n"
      "}\n";
    *computeTemplate = "max = _mm256_setzero_ps();\n"
      "average = _mm256_setzero_ps();\n"
      "rms = _mm256_setzero_ps();\n"
      "\n"
      "for ( unsigned int bin = 0; bin < observation.getNrBins(); bin++ ) {\n"
      "__m256 value = _mm256_load_ps(&(foldedData[(bin * observation.getNrPeriods() * observation.getNrPaddedDMs()) + ((period + <%PERIOD_NUM%>) * observation.getNrPaddedDMs()) + dm + <%DM_NUM%>]));\n"
      "\n"
      "average = _mm256_add_ps(average, value);\n"
      "rms = _mm256_add_ps(rms, _mm256_mul_ps(value, value));\n"
      "max = _mm256_max_ps(max, value);\n"
      "}\n"
      "average = _mm256_div_ps(average, _mm256_set1_ps(observation.getNrBins()));\n"
      "rms = _mm256_sqrt_ps(_mm256_div_ps(rms, _mm256_set1_ps(observation.getNrBins())));\n"
      "_mm256_store_ps(&(snrs[((period + <%PERIOD_NUM%>) * observation.getNrPaddedDMs()) + dm + <%DM_NUM%>]),_mm256_div_ps(_mm256_sub_ps(max, average), rms));\n";
  } else {
    *code = "namespace PulsarSearch {\n"
      "template< typename T > void snrPhi" + isa::utils::toString(nrDMsPerThread) + "x" + isa::utils::toString(nrPeriodsPerThread) + "(const AstroData::Observation & observation, const float * const __restrict__ foldedData, float * const __restrict__ snrs) {\n"
      "{\n"
      "__m512 max = _mm512_setzero_ps();\n"
      "__m512 average = _mm512_setzero_ps();\n"
      "__m512 rms = _mm512_setzero_ps();\n"
      "#pragma omp parallel for schedule(static)\n"
      "for ( unsigned int period = 0; period < observation.getNrPeriods(); period += " + isa::utils::toString(nrPeriodsPerThread) + ") {\n"
      "#pragma omp parallel for schedule(static)\n"
      "for ( unsigned int dm = 0; dm < observation.getNrDMs(); dm += " + isa::utils::toString(nrPeriodsPerThread) + " * 16) {\n"
      "<%COMPUTE%>"
      "}\n"
      "}\n"
      "}\n"
      "}\n"
      "}\n";
    *computeTemplate = "max = _mm512_setzero_ps();\n"
      "average = _mm512_setzero_ps();\n"
      "rms = _mm512_setzero_ps();\n"
      "\n"
      "for ( unsigned int bin = 0; bin < observation.getNrBins(); bin++ ) {\n"
      "__m512 value = _mm512_load_ps(&(foldedData[(bin * observation.getNrPeriods() * observation.getNrPaddedDMs()) + ((period + <%PERIOD_NUM%>) * observation.getNrPaddedDMs()) + dm + <%DM_NUM%>]));\n"
      "\n"
      "average = _mm512_add_ps(average, value);\n"
      "rms = _mm512_add_ps(rms, _mm512_mul_ps(value, value));\n"
      "max = _mm512_max_ps(max, value);\n"
      "}\n"
      "average = _mm512_div_ps(average, _mm512_set1_ps(observation.getNrBins()));\n"
      "rms = _mm512_sqrt_ps(_mm512_div_ps(rms, _mm512_set1_ps(observation.getNrBins())));\n"
      "_mm512_store_ps(&(snrs[((period + <%PERIOD_NUM%>) * observation.getNrPaddedDMs()) + dm + <%DM_NUM%>]),_mm512_div_ps(_mm512_sub_ps(max, average), rms));\n";
  }
  // End kernel's template

  std::string * compute_s = new std::string();

  for ( unsigned int period = 0; period < nrPeriodsPerThread; period++ ) {
    std::string period_s = isa::utils::toString< unsigned int >(period);

    for ( unsigned int dm = 0; dm < nrDMsPerThread; dm++ ) {
      std::string dm_s = isa::utils::toString< unsigned int >(dm);
      std::string * temp_s = 0;

      temp_s = isa::utils::replace(computeTemplate, "<%PERIOD_NUM%>", period_s);
      temp_s = isa::utils::replace(temp_s, "<%DM_NUM%>", dm_s, true);
      compute_s->append(*temp_s);
      delete temp_s;
    }
  }
  code = isa::utils::replace(code, "<%COMPUTE%>", *compute_s, true);
  delete compute_s;

  delete computeTemplate;
  return code;
}

} // PulsarSearch

#endif // SNR_HPP

<|endoftext|>


<commit_before>/*
 * System_stateIdle.cpp
 *
 *  Created on: Jun 19, 2014
 *      Author: Pimenta
 */

// this
#include "System.hpp"

// local
#include "Defines.hpp"

using namespace concurrency;

void System::changeToIdle() {
  FileSystem::init(localAddress.ip);
  requestSystemState();
  httpThread = Thread([this]() {
    while (state == newState) {
      httpServer();
      Thread::sleep(MS_SLEEP);
    }
  });
  httpThread.start();
}

void System::stateIdle() {
  listen();
  speak();
  detectFailure();
  executeProtocol();
}
<commit_msg>Fixing bug<commit_after>/*
 * System_stateIdle.cpp
 *
 *  Created on: Jun 19, 2014
 *      Author: Pimenta
 */

// this
#include "System.hpp"

// local
#include "Defines.hpp"
#include "FileSystem.hpp"

using namespace concurrency;

void System::changeToIdle() {
  FileSystem::init(localAddress.ip);
  requestSystemState();
  httpThread = Thread([this]() {
    while (state == newState) {
      httpServer();
      Thread::sleep(MS_SLEEP);
    }
  });
  httpThread.start();
}

void System::stateIdle() {
  listen();
  speak();
  detectFailure();
  executeProtocol();
}
<|endoftext|>


<commit_before>/*=============================================================================
	Copyright (c) 2012-2014 Richard Otis

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/

// subroutines for EZD global minimization
// Reference: Maria Emelianenko, Zi-Kui Liu, and Qiang Du.
// "A new algorithm for the automation of phase diagram calculation." Computational Materials Science 35.1 (2006): 61-74.

#include "libgibbs/include/libgibbs_pch.hpp"
#include "libgibbs/include/optimizer/utils/ezd_minimization.hpp"
#include "libgibbs/include/compositionset.hpp"
#include "libgibbs/include/constraint.hpp"
#include "libgibbs/include/models.hpp"
#include "libgibbs/include/optimizer/halton.hpp"
#include "libgibbs/include/optimizer/utils/ndsimplex.hpp"
#include "libgibbs/include/utils/cholesky.hpp"
#include <boost/bimap.hpp>
#include <boost/numeric/ublas/symmetric.hpp>
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/io.hpp>
#include <algorithm>
#include <string>
#include <map>

std::vector<std::vector<double>> AdaptiveSearchND (
                                  CompositionSet const &phase,
                                  evalconditions const& conditions,
                                  const SimplexCollection &search_region,
                                  const std::size_t depth );

namespace Optimizer
{

// TODO: Should this be a member function of GibbsOpt?
// The function calling LocateMinima definitely should be at least (needs access to all CompositionSets)
// LocateMinima finds all of the minima for a given phase's Gibbs energy
// In addition to allowing us to choose a better starting point, this will allow for automatic miscibility gap detection
void LocateMinima (
    CompositionSet const &phase,
    sublattice_set const &sublset,
    evalconditions const& conditions,
    const std::size_t depth // depth tracking for recursion
)
    {
    constexpr const std::size_t subdivisions_per_axis = 5; // TODO: make this user-configurable
    using namespace boost::numeric::ublas;

    // EZD Global Minimization (Emelianenko et al., 2006)
    // First: FIND CONCAVITY REGIONS
    std::vector<std::vector<double>> points,  minima;
    std::vector<SimplexCollection> start_simplices;
    std::vector<SimplexCollection> positive_definite_regions;
    std::vector<SimplexCollection> components_in_sublattice;

    // Get the first sublattice for this phase
    boost::multi_index::index<sublattice_set,phase_subl>::type::iterator ic0,ic1;
    int sublindex = 0;
    ic0 = boost::multi_index::get<phase_subl> ( sublset ).lower_bound ( boost::make_tuple ( phase.name(), sublindex ) );
    ic1 = boost::multi_index::get<phase_subl> ( sublset ).upper_bound ( boost::make_tuple ( phase.name(), sublindex ) );;

    // (1) Sample some points on the domain using NDSimplex
    // Because the grid is uniform, we can assume that each point is the center of an N-simplex

    // Determine number of components in each sublattice
    while ( ic0 != ic1 )
        {
        const std::size_t number_of_species = std::distance ( ic0,ic1 );
        if ( number_of_species > 0 )
            {
            NDSimplex base ( number_of_species-1 ); // construct the unit (q-1)-simplex
            components_in_sublattice.emplace_back ( base.simplex_subdivide ( subdivisions_per_axis ) );
            }
        // Next sublattice
        ++sublindex;
        ic0 = boost::multi_index::get<phase_subl> ( sublset ).lower_bound ( boost::make_tuple ( phase.name(), sublindex ) );
        ic1 = boost::multi_index::get<phase_subl> ( sublset ).end();
        }

    // Take all combinations of generated points in each sublattice
    start_simplices = lattice_complex ( components_in_sublattice );

    for ( SimplexCollection& simpcol : start_simplices )
        {
        std::cout << "(";
        std::vector<double> pt;
        for ( NDSimplex& simp : simpcol )
            {
            std::vector<double> sub_pt = simp.centroid_with_dependent_component();
            pt.insert ( pt.end(),std::make_move_iterator ( sub_pt.begin() ),std::make_move_iterator ( sub_pt.end() ) );
            }
        for ( auto i = pt.begin(); i != pt.end(); ++i )
            {
            std::cout << *i;
            if ( std::distance ( i,pt.end() ) > 1 ) std::cout << ",";
            }
        std::cout << ")" << std::endl;
        points.emplace_back ( std::move ( pt ) );
        }

    // (2) Calculate the Lagrangian Hessian for all sampled points
    for ( SimplexCollection& simpcol : start_simplices )
        {
        std::vector<double> pt;
        for ( NDSimplex& simp : simpcol )
            {
            // Generate the current point from all the simplices in each sublattice
            std::vector<double> sub_pt = simp.centroid_with_dependent_component();
            pt.insert ( pt.end(),std::make_move_iterator ( sub_pt.begin() ),std::make_move_iterator ( sub_pt.end() ) );
            }
        if ( pt.size() == 0 ) continue; // skip empty (invalid) points
        symmetric_matrix<double, lower> Hessian ( zero_matrix<double> ( pt.size(),pt.size() ) );
        try
            {
            Hessian = phase.evaluate_objective_hessian_matrix ( conditions, phase.get_variable_map(), pt );
            }
        catch ( boost::exception &e )
            {
            std::cout << boost::diagnostic_information ( e );
            throw;
            }
        catch ( std::exception &e )
            {
            std::cout << e.what();
            throw;
            }
        //std::cout << "Hessian: " << Hessian << std::endl;
        // NOTE: For this calculation we consider only the linear constraints for an isolated phase (e.g., site fraction balances)
        // (3) Save all points for which the Lagrangian Hessian is positive definite in the null space of the constraint gradient matrix
        //        NOTE: This is the projected Hessian method (Nocedal and Wright, 2006, ch. 12.4, p.349)
        //        But how do I choose the Lagrange multipliers for all the constraints? Can I calculate them?
        //        The answer is that, because the constraints are linear, there is no constraint contribution to the Hessian.
        //        That means that the Hessian of the Lagrangian is just the Hessian of the objective function.
        const std::size_t Zcolumns = pt.size() - phase.get_constraints().size();
        // Z is the constraint null space matrix = phase.get_constraint_null_space_matrix()
        //    (a) Set Hproj = transpose(Z)*(L'')*Z
        matrix<double> Hproj ( pt.size(), Zcolumns );
        Hproj = prod ( trans ( phase.get_constraint_null_space_matrix() ),
                       matrix<double> ( prod ( Hessian,phase.get_constraint_null_space_matrix() ) ) );
        //std::cout << "Hproj: " << Hproj << std::endl;
        //    (b) Verify that all diagonal elements of Hproj are strictly positive; if not, remove this point from consideration
        //        NOTE: This is a necessary but not sufficient condition that a matrix be positive definite, and it's easy to check
        //        Reference: Carlen and Carvalho, 2007, p. 148, Eq. 5.12
        //        TODO: Currently not bothering to do this; should perform a test to figure out if there would be a performance increase
        //    (c) Attempt a Cholesky factorization of Hproj; will only succeed if matrix is positive definite
        const bool is_positive_definite = cholesky_factorize ( Hproj );
        //    (d) If it succeeds, save this point; else, discard it
        if ( is_positive_definite )
            {
            positive_definite_regions.push_back ( simpcol );
            for ( double i : pt ) std::cout << i << ",";
            std::cout << ":" <<  std::endl;
            }
        }

    // positive_definite_regions is now filled
    // Perform recursive search for minima on each of the identified regions
    for ( const SimplexCollection &simpcol : positive_definite_regions )
        {
        // We start at a recursive depth of 2 because we treat LocateMinima as depth == 1
        // This allows our notation for depth to be consistent with Emelianenko et al.
        std::vector<std::vector<double>> region_minima = AdaptiveSearchND ( phase, conditions, simpcol,  2 );
        // Append this region's minima to the list of minima
        // minima.size() > 1 means there is a miscilibility gap
        minima.reserve ( minima.size() +region_minima.size() );
        minima.insert ( minima.end(), std::make_move_iterator ( region_minima.begin() ),  std::make_move_iterator ( region_minima.end() ) );
        }
    }

// namespace Optimizer
}

// Recursive function for searching composition space for minima
// Input: Simplex that bounds a positive definite search region (SimplexCollection is used for multiple sublattices)
// Input: Recursion depth
// Output: Vector of minimum points
std::vector<std::vector<double>> AdaptiveSearchND (
                                  CompositionSet const &phase,
                                  evalconditions const& conditions,
                                  const SimplexCollection &search_region,
                                  const std::size_t depth )
    {
    BOOST_ASSERT ( depth > 0 );
    constexpr const double gradient_magnitude_threshold = 1e8;
    constexpr const std::size_t subdivisions_per_axis = 2;
    constexpr const std::size_t max_depth = 5;
    std::vector<std::vector<double>> minima;
    std::vector<double> pt;

    // (1) Calculate the objective gradient (L') for the centroid of the active simplex
    for ( const NDSimplex& simp : search_region )
    {
        // Generate the current point (pt) from all the simplices in each sublattice
        std::vector<double> sub_pt = simp.centroid_with_dependent_component();
        //std::cout << "[";
        //for (double i : sub_pt) std::cout << i << ",";
        //std::cout << "]" << std::endl;
        pt.insert ( pt.end(),std::make_move_iterator ( sub_pt.begin() ),std::make_move_iterator ( sub_pt.end() ) );
    }
    //double obj = phase.evaluate_objective ( conditions, phase.get_variable_map(), &pt[0] );
    //std::cout << obj << std::endl;
    std::vector<double> gradient = phase.evaluate_internal_objective_gradient ( conditions, &pt[0] );
    double mag = 0;
    for ( auto i = gradient.begin(); i != gradient.end(); ++i )
    {
        //std::cout << "gradient[" << std::distance(gradient.begin(),i) << "] = " << *i << std::endl;
        mag += pow ( *i,2 );
    }
    // (2) If that magnitude is less than some defined epsilon, return z as a minimum
    //     Else simplex_subdivide() the active region and send to next depth (return minima from that)
    if (mag < gradient_magnitude_threshold) {
        std::cout << "new minpoint ";
        for ( auto i = pt.begin(); i != pt.end(); ++i )
        {
            std::cout << *i;
            if ( std::distance ( i,pt.end() ) > 1 ) std::cout << ",";
        }
        std::cout << " gradient sq: " << mag << std::endl;
        for ( auto i = gradient.begin(); i != gradient.end(); ++i )
        {
            std::cout << "gradient[" << std::distance(gradient.begin(),i) << "] = " << *i << std::endl;
        }
        minima.push_back(pt);
    }
    else {
        if (depth == max_depth) return minima; // we've hit max depth, return what we have (nothing)
        std::vector<SimplexCollection> simplex_combinations, new_simplices;
        // simplex_subdivide() the simplices in all the active sublattices
        for (const NDSimplex &simp : search_region) {
            simplex_combinations.emplace_back(simp.simplex_subdivide(subdivisions_per_axis));
        }
        // lattice_complex() the result to generate all the combinations in the sublattices
        new_simplices = lattice_complex(simplex_combinations);
        // send each new SimplexCollection to the next depth
        for (const SimplexCollection &sc : new_simplices) {
            std::vector<std::vector<double>> recursive_minima = AdaptiveSearchND(phase, conditions, sc, depth+1);
            // Add the found minima to the list of known minima
            minima.reserve(minima.size()+recursive_minima.size());
            minima.insert ( minima.end(), std::make_move_iterator ( recursive_minima.begin() ),  std::make_move_iterator ( recursive_minima.end() ) );
        }
    }
    return minima;
    }
// kate: indent-mode cstyle; indent-width 4; replace-tabs on;
<commit_msg>Unstable commit devising a projected gradient calculation<commit_after>/*=============================================================================
	Copyright (c) 2012-2014 Richard Otis

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/

// subroutines for EZD global minimization
// Reference: Maria Emelianenko, Zi-Kui Liu, and Qiang Du.
// "A new algorithm for the automation of phase diagram calculation." Computational Materials Science 35.1 (2006): 61-74.

#include "libgibbs/include/libgibbs_pch.hpp"
#include "libgibbs/include/optimizer/utils/ezd_minimization.hpp"
#include "libgibbs/include/compositionset.hpp"
#include "libgibbs/include/constraint.hpp"
#include "libgibbs/include/models.hpp"
#include "libgibbs/include/optimizer/halton.hpp"
#include "libgibbs/include/optimizer/utils/ndsimplex.hpp"
#include "libgibbs/include/utils/cholesky.hpp"
#include <boost/bimap.hpp>
#include <boost/numeric/ublas/symmetric.hpp>
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/io.hpp>
#include <algorithm>
#include <string>
#include <map>

std::vector<std::vector<double>> AdaptiveSearchND (
                                  CompositionSet const &phase,
                                  evalconditions const& conditions,
                                  const SimplexCollection &search_region,
                                  const std::size_t depth );

namespace Optimizer
{

// TODO: Should this be a member function of GibbsOpt?
// The function calling LocateMinima definitely should be at least (needs access to all CompositionSets)
// LocateMinima finds all of the minima for a given phase's Gibbs energy
// In addition to allowing us to choose a better starting point, this will allow for automatic miscibility gap detection
void LocateMinima (
    CompositionSet const &phase,
    sublattice_set const &sublset,
    evalconditions const& conditions,
    const std::size_t depth // depth tracking for recursion
)
    {
    constexpr const std::size_t subdivisions_per_axis = 5; // TODO: make this user-configurable
    using namespace boost::numeric::ublas;

    // EZD Global Minimization (Emelianenko et al., 2006)
    // First: FIND CONCAVITY REGIONS
    std::vector<std::vector<double>> points,  minima;
    std::vector<SimplexCollection> start_simplices;
    std::vector<SimplexCollection> positive_definite_regions;
    std::vector<SimplexCollection> components_in_sublattice;

    // Get the first sublattice for this phase
    boost::multi_index::index<sublattice_set,phase_subl>::type::iterator ic0,ic1;
    int sublindex = 0;
    ic0 = boost::multi_index::get<phase_subl> ( sublset ).lower_bound ( boost::make_tuple ( phase.name(), sublindex ) );
    ic1 = boost::multi_index::get<phase_subl> ( sublset ).upper_bound ( boost::make_tuple ( phase.name(), sublindex ) );;

    // (1) Sample some points on the domain using NDSimplex
    // Because the grid is uniform, we can assume that each point is the center of an N-simplex

    // Determine number of components in each sublattice
    while ( ic0 != ic1 )
        {
        const std::size_t number_of_species = std::distance ( ic0,ic1 );
        if ( number_of_species > 0 )
            {
            NDSimplex base ( number_of_species-1 ); // construct the unit (q-1)-simplex
            components_in_sublattice.emplace_back ( base.simplex_subdivide ( subdivisions_per_axis ) );
            }
        // Next sublattice
        ++sublindex;
        ic0 = boost::multi_index::get<phase_subl> ( sublset ).lower_bound ( boost::make_tuple ( phase.name(), sublindex ) );
        ic1 = boost::multi_index::get<phase_subl> ( sublset ).end();
        }

    // Take all combinations of generated points in each sublattice
    start_simplices = lattice_complex ( components_in_sublattice );

    for ( SimplexCollection& simpcol : start_simplices )
        {
        std::cout << "(";
        std::vector<double> pt;
        for ( NDSimplex& simp : simpcol )
            {
            std::vector<double> sub_pt = simp.centroid_with_dependent_component();
            pt.insert ( pt.end(),std::make_move_iterator ( sub_pt.begin() ),std::make_move_iterator ( sub_pt.end() ) );
            }
        for ( auto i = pt.begin(); i != pt.end(); ++i )
            {
            std::cout << *i;
            if ( std::distance ( i,pt.end() ) > 1 ) std::cout << ",";
            }
        std::cout << ")" << std::endl;
        points.emplace_back ( std::move ( pt ) );
        }

    // (2) Calculate the Lagrangian Hessian for all sampled points
    for ( SimplexCollection& simpcol : start_simplices )
        {
        std::vector<double> pt;
        for ( NDSimplex& simp : simpcol )
            {
            // Generate the current point from all the simplices in each sublattice
            std::vector<double> sub_pt = simp.centroid_with_dependent_component();
            pt.insert ( pt.end(),std::make_move_iterator ( sub_pt.begin() ),std::make_move_iterator ( sub_pt.end() ) );
            }
        if ( pt.size() == 0 ) continue; // skip empty (invalid) points
        symmetric_matrix<double, lower> Hessian ( zero_matrix<double> ( pt.size(),pt.size() ) );
        try
            {
            Hessian = phase.evaluate_objective_hessian_matrix ( conditions, phase.get_variable_map(), pt );
            }
        catch ( boost::exception &e )
            {
            std::cout << boost::diagnostic_information ( e );
            throw;
            }
        catch ( std::exception &e )
            {
            std::cout << e.what();
            throw;
            }
        //std::cout << "Hessian: " << Hessian << std::endl;
        // NOTE: For this calculation we consider only the linear constraints for an isolated phase (e.g., site fraction balances)
        // (3) Save all points for which the Lagrangian Hessian is positive definite in the null space of the constraint gradient matrix
        //        NOTE: This is the projected Hessian method (Nocedal and Wright, 2006, ch. 12.4, p.349)
        //        But how do I choose the Lagrange multipliers for all the constraints? Can I calculate them?
        //        The answer is that, because the constraints are linear, there is no constraint contribution to the Hessian.
        //        That means that the Hessian of the Lagrangian is just the Hessian of the objective function.
        const std::size_t Zcolumns = pt.size() - phase.get_constraints().size();
        // Z is the constraint null space matrix = phase.get_constraint_null_space_matrix()
        //    (a) Set Hproj = transpose(Z)*(L'')*Z
        matrix<double> Hproj ( pt.size(), Zcolumns );
        Hproj = prod ( trans ( phase.get_constraint_null_space_matrix() ),
                       matrix<double> ( prod ( Hessian,phase.get_constraint_null_space_matrix() ) ) );
        //std::cout << "Hproj: " << Hproj << std::endl;
        //    (b) Verify that all diagonal elements of Hproj are strictly positive; if not, remove this point from consideration
        //        NOTE: This is a necessary but not sufficient condition that a matrix be positive definite, and it's easy to check
        //        Reference: Carlen and Carvalho, 2007, p. 148, Eq. 5.12
        //        TODO: Currently not bothering to do this; should perform a test to figure out if there would be a performance increase
        //    (c) Attempt a Cholesky factorization of Hproj; will only succeed if matrix is positive definite
        const bool is_positive_definite = cholesky_factorize ( Hproj );
        //    (d) If it succeeds, save this point; else, discard it
        if ( is_positive_definite )
            {
            positive_definite_regions.push_back ( simpcol );
            for ( double i : pt ) std::cout << i << ",";
            std::cout << ":" <<  std::endl;
            }
        }

    // positive_definite_regions is now filled
    // Perform recursive search for minima on each of the identified regions
    for ( const SimplexCollection &simpcol : positive_definite_regions )
        {
        // We start at a recursive depth of 2 because we treat LocateMinima as depth == 1
        // This allows our notation for depth to be consistent with Emelianenko et al.
        std::vector<std::vector<double>> region_minima = AdaptiveSearchND ( phase, conditions, simpcol,  2 );
        // Append this region's minima to the list of minima
        // minima.size() > 1 means there is a miscilibility gap
        minima.reserve ( minima.size() +region_minima.size() );
        minima.insert ( minima.end(), std::make_move_iterator ( region_minima.begin() ),  std::make_move_iterator ( region_minima.end() ) );
        }
    }

// namespace Optimizer
}

// Recursive function for searching composition space for minima
// Input: Simplex that bounds a positive definite search region (SimplexCollection is used for multiple sublattices)
// Input: Recursion depth
// Output: Vector of minimum points
std::vector<std::vector<double>> AdaptiveSearchND (
                                  CompositionSet const &phase,
                                  evalconditions const& conditions,
                                  const SimplexCollection &search_region,
                                  const std::size_t depth )
    {
    using namespace boost::numeric::ublas;
    BOOST_ASSERT ( depth > 0 );
    constexpr const double gradient_magnitude_threshold = 1e3;
    constexpr const std::size_t subdivisions_per_axis = 5;
    constexpr const std::size_t max_depth = 5;
    std::vector<std::vector<double>> minima;
    std::vector<double> pt;

    // (1) Calculate the objective gradient (L') for the centroid of the active simplex
    for ( const NDSimplex& simp : search_region )
    {
        // Generate the current point (pt) from all the simplices in each sublattice
        std::vector<double> sub_pt = simp.centroid_with_dependent_component();
        //std::cout << "[";
        //for (double i : sub_pt) std::cout << i << ",";
        //std::cout << "]" << std::endl;
        pt.insert ( pt.end(),std::make_move_iterator ( sub_pt.begin() ),std::make_move_iterator ( sub_pt.end() ) );
    }
    //double obj = phase.evaluate_objective ( conditions, phase.get_variable_map(), &pt[0] );
    //std::cout << obj << std::endl;
    std::vector<double> raw_gradient = phase.evaluate_internal_objective_gradient ( conditions, &pt[0] );
    // Project the raw gradient into the null space of constraints
    // This will leave only the gradient in the feasible directions
    boost::numeric::ublas::vector<double> projected_gradient(raw_gradient.size());
    std::move(raw_gradient.begin(), raw_gradient.end(), projected_gradient.begin());
    projected_gradient = projected_gradient - prod ( phase.get_constraint_null_space_matrix(), projected_gradient );
    double mag = 0;
    for ( auto i = projected_gradient.begin(); i != projected_gradient.end(); ++i )
    {
        mag += pow ( *i,2 );
    }
    for ( auto i = projected_gradient.begin(); i != projected_gradient.end(); ++i )
    {
        std::cout << "gradient[" << std::distance(projected_gradient.begin(),i) << "] = " << *i << std::endl;
    }
    // (2) If that magnitude is less than some defined epsilon, return z as a minimum
    //     Else simplex_subdivide() the active region and send to next depth (return minima from that)
    if (mag < gradient_magnitude_threshold) {
        std::cout << "new minpoint ";
        for ( auto i = pt.begin(); i != pt.end(); ++i )
        {
            std::cout << *i;
            if ( std::distance ( i,pt.end() ) > 1 ) std::cout << ",";
        }
        std::cout << " gradient sq: " << mag << std::endl;
        for ( auto i = projected_gradient.begin(); i != projected_gradient.end(); ++i )
        {
            std::cout << "gradient[" << std::distance(projected_gradient.begin(),i) << "] = " << *i << std::endl;
        }
        minima.push_back(pt);
    }
    else {
        if (depth == max_depth) return minima; // we've hit max depth, return what we have (nothing)
        std::vector<SimplexCollection> simplex_combinations, new_simplices;
        // simplex_subdivide() the simplices in all the active sublattices
        for (const NDSimplex &simp : search_region) {
            simplex_combinations.emplace_back(simp.simplex_subdivide(subdivisions_per_axis));
        }
        // lattice_complex() the result to generate all the combinations in the sublattices
        new_simplices = lattice_complex(simplex_combinations);
        // send each new SimplexCollection to the next depth
        for (const SimplexCollection &sc : new_simplices) {
            std::vector<std::vector<double>> recursive_minima = AdaptiveSearchND(phase, conditions, sc, depth+1);
            // Add the found minima to the list of known minima
            minima.reserve(minima.size()+recursive_minima.size());
            minima.insert ( minima.end(), std::make_move_iterator ( recursive_minima.begin() ),  std::make_move_iterator ( recursive_minima.end() ) );
        }
    }
    return minima;
    }
// kate: indent-mode cstyle; indent-width 4; replace-tabs on;
<|endoftext|>


<commit_before>// Include this #define to use SystemTraceControlGuid in Evntrace.h.
#define INITGUID

#include <windows.h>

#include <evntcons.h>
#include <evntrace.h>
#include <stdio.h>

static void err(char *s) {
  // Retrieve the system error message for the last-error code
  LPVOID lpMsgBuf;
  auto e = GetLastError();
  FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
                    FORMAT_MESSAGE_IGNORE_INSERTS,
                NULL, e, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                (LPTSTR)&lpMsgBuf, 0, NULL);

  // Display the error message and exit the process
  printf("%s failed with error %d: %s\n", s, e, lpMsgBuf);
  ExitProcess(e);
}

static void WINAPI EventRecordCallback(EVENT_RECORD *EventRecord) {
  EVENT_HEADER &Header = EventRecord->EventHeader;

  UCHAR ProcessorNumber = EventRecord->BufferContext.ProcessorNumber;
  ULONG ThreadID = Header.ThreadId;

  // Process event here.
}

static TRACEHANDLE ConsumerHandle;

static DWORD WINAPI processThread(LPVOID Parameter) {
  ProcessTrace(&ConsumerHandle, 1, 0, 0);
  return (0);
}

int main(int argc, char **argv) {
  TRACEHANDLE SessionHandle = 0;

  auto BufferSize = sizeof(EVENT_TRACE_PROPERTIES) + sizeof(KERNEL_LOGGER_NAME);
  EVENT_TRACE_PROPERTIES *properties =
      (EVENT_TRACE_PROPERTIES *)malloc(BufferSize);

  ZeroMemory(properties, BufferSize);
  properties->Wnode.BufferSize = BufferSize;
  properties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
  properties->Wnode.ClientContext = 3;
  properties->Wnode.Guid = SystemTraceControlGuid;
  properties->EnableFlags = EVENT_TRACE_FLAG_NETWORK_TCPIP;
  properties->LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
  properties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
  strcpy((char *)properties + properties->LoggerNameOffset, KERNEL_LOGGER_NAME);

  ControlTrace(0, KERNEL_LOGGER_NAME, properties, EVENT_TRACE_CONTROL_STOP);

  auto status =
      StartTrace((PTRACEHANDLE)&SessionHandle, KERNEL_LOGGER_NAME, properties);
  if (ERROR_SUCCESS != status)
    err("StartTrace");

  EVENT_TRACE_LOGFILE LogFile = {0};
  LogFile.LoggerName = KERNEL_LOGGER_NAME;
  LogFile.ProcessTraceMode =
      (PROCESS_TRACE_MODE_REAL_TIME | PROCESS_TRACE_MODE_EVENT_RECORD |
       PROCESS_TRACE_MODE_RAW_TIMESTAMP);
  LogFile.EventRecordCallback = EventRecordCallback;
  ConsumerHandle = OpenTrace(&LogFile);
  DWORD ThreadID;
  HANDLE ThreadHandle = CreateThread(0, 0, processThread, 0, 0, &ThreadID);
  CloseHandle(ThreadHandle);

  wprintf(L"Press any key to end trace session ");
  getchar();

  ControlTrace(0, KERNEL_LOGGER_NAME, properties, EVENT_TRACE_CONTROL_STOP);
  return 0;
}
<commit_msg>refactor<commit_after>// Include this #define to use SystemTraceControlGuid in Evntrace.h.
#define INITGUID

#include <windows.h>

#include <evntcons.h>
#include <evntrace.h>
#include <stdio.h>

static void err(char *s) {
  // Retrieve the system error message for the last-error code
  LPVOID msg;
  auto e = GetLastError();
  FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
                    FORMAT_MESSAGE_IGNORE_INSERTS,
                NULL, e, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                (LPTSTR)&msg, 0, NULL);

  // Display the error message and exit the process
  printf("%s failed with error %d: %s\n", s, e, msg);
  ExitProcess(e);
}

static void WINAPI EventRecordCallback(EVENT_RECORD *EventRecord) {
  EVENT_HEADER &Header = EventRecord->EventHeader;

  UCHAR ProcessorNumber = EventRecord->BufferContext.ProcessorNumber;
  ULONG ThreadID = Header.ThreadId;

  // Process event here.
}

static TRACEHANDLE trace;

static DWORD WINAPI processThread(LPVOID Parameter) {
  ProcessTrace(&trace, 1, 0, 0);
  return (0);
}

int main(int argc, char **argv) {
  auto BufferSize = sizeof(EVENT_TRACE_PROPERTIES) + sizeof(KERNEL_LOGGER_NAME);
  auto properties = (EVENT_TRACE_PROPERTIES *)malloc(BufferSize);

  ZeroMemory(properties, BufferSize);
  properties->Wnode.BufferSize = BufferSize;
  properties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
  properties->Wnode.ClientContext = 3;
  properties->Wnode.Guid = SystemTraceControlGuid;
  properties->EnableFlags = EVENT_TRACE_FLAG_NETWORK_TCPIP;
  properties->LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
  properties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
  strcpy((char *)properties + properties->LoggerNameOffset, KERNEL_LOGGER_NAME);

  ControlTrace(0, KERNEL_LOGGER_NAME, properties, EVENT_TRACE_CONTROL_STOP);

  auto status =
      StartTrace((PTRACEHANDLE)&trace, KERNEL_LOGGER_NAME, properties);
  if (ERROR_SUCCESS != status)
    err("StartTrace");

  EVENT_TRACE_LOGFILE LogFile = {0};
  LogFile.LoggerName = KERNEL_LOGGER_NAME;
  LogFile.ProcessTraceMode =
      (PROCESS_TRACE_MODE_REAL_TIME | PROCESS_TRACE_MODE_EVENT_RECORD |
       PROCESS_TRACE_MODE_RAW_TIMESTAMP);
  LogFile.EventRecordCallback = EventRecordCallback;
  trace = OpenTrace(&LogFile);
  CreateThread(0, 0, processThread, 0, 0, 0);

  wprintf(L"Press any key to end trace session ");
  getchar();

  ControlTrace(0, KERNEL_LOGGER_NAME, properties, EVENT_TRACE_CONTROL_STOP);
  return 0;
}
<|endoftext|>


<commit_before>/********************************************************************
 * AUTHORS: Vijay Ganesh, Trevor Hansen, Mate Soos
 *
 * BEGIN DATE: November, 2005
 *
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
********************************************************************/

#include "main_common.h"
#include "extlib-abc/cnf_short.h"

extern int smtparse(void*);
extern int smt2parse();
extern int cvcparse(void*);
extern int cvclex_destroy(void);
extern int smtlex_destroy(void);
extern int smt2lex_destroy(void);
extern void errorHandler(const char* error_msg);

// Amount of memory to ask for at beginning of main.
extern const intptr_t INITIAL_MEMORY_PREALLOCATION_SIZE;
extern FILE* cvcin;
extern FILE* smtin;
extern FILE* smt2in;

#ifdef EXT_HASH_MAP
using namespace __gnu_cxx;
#endif
using namespace BEEV;
using std::auto_ptr;
using std::cout;
using std::cerr;
using std::endl;

void errorHandler(const char* error_msg)
{
  cerr << prog << ": Error: " << error_msg << endl;
  exit(-1);
}

// Amount of memory to ask for at beginning of main.
const intptr_t INITIAL_MEMORY_PREALLOCATION_SIZE = 4000000;

Main::Main() : onePrintBack(false)
{
  bm = NULL;
  toClose = NULL;
  cvcin = NULL;
  smtin = NULL;
  smt2in = NULL;

  // Register the error handler
  vc_error_hdlr = errorHandler;

#if !defined(__MINGW32__) && !defined(__MINGW64__) && !defined(_MSC_VER)
  // Grab some memory from the OS upfront to reduce system time when
  // individual hash tables are being allocated
  if (sbrk(INITIAL_MEMORY_PREALLOCATION_SIZE) == ((void*)-1))
  {
    FatalError("Initial allocation of memory failed.");
  }
#endif

  bm = new STPMgr();
  ParserBM = bm;
}

Main::~Main()
{
  delete bm;
}

void Main::parse_file(ASTVec* AssertsQuery)
{
  TypeChecker nfTypeCheckSimp(*bm->defaultNodeFactory, *bm);
  TypeChecker nfTypeCheckDefault(*bm->hashingNodeFactory, *bm);

  Cpp_interface piTypeCheckSimp(*bm, &nfTypeCheckSimp);
  Cpp_interface piTypeCheckDefault(*bm, &nfTypeCheckDefault);

  // If you are converting formats, you probably don't want it simplifying (at
  // least I dont).
  if (onePrintBack)
  {
    parserInterface = &piTypeCheckDefault;
  }
  else
  {
    parserInterface = &piTypeCheckSimp;
  }

  parserInterface->startup();

  if (onePrintBack)
  {
    if (bm->UserFlags.smtlib2_parser_flag)
    {
      cerr << "Printback from SMTLIB2 inputs isn't currently working." << endl;
      cerr << "Please try again later" << endl;
      cerr << "It works prior to revision 1354" << endl;
      exit(1);
    }
  }

  if (bm->UserFlags.smtlib1_parser_flag)
  {
    smtparse((void*)AssertsQuery);
    smtlex_destroy();
  }
  else if (bm->UserFlags.smtlib2_parser_flag)
  {
    smt2parse();
    smt2lex_destroy();
  }
  else
  {
    cvcparse((void*)AssertsQuery);
    cvclex_destroy();
  }
  parserInterface = NULL;
  if (toClose != NULL)
  {
    fclose(toClose);
  }
}

void Main::print_back(ASTNode& query, ASTNode& asserts)
{
  ASTNode original_input =
      bm->CreateNode(AND, bm->CreateNode(NOT, query), asserts);

  if (bm->UserFlags.print_STPinput_back_flag)
  {
    if (bm->UserFlags.smtlib1_parser_flag)
    {
      bm->UserFlags.print_STPinput_back_SMTLIB2_flag = true;
    }
    else
    {
      bm->UserFlags.print_STPinput_back_CVC_flag = true;
    }
  }

  if (bm->UserFlags.print_STPinput_back_CVC_flag)
  {
    // needs just the query. Reads the asserts out of the data structure.
    print_STPInput_Back(original_input);
  }

  if (bm->UserFlags.print_STPinput_back_SMTLIB1_flag)
  {
    printer::SMTLIB1_PrintBack(cout, original_input);
  }

  if (bm->UserFlags.print_STPinput_back_SMTLIB2_flag)
  {
    printer::SMTLIB2_PrintBack(cout, original_input);
  }

  if (bm->UserFlags.print_STPinput_back_C_flag)
  {
    printer::C_Print(cout, original_input);
  }

  if (bm->UserFlags.print_STPinput_back_GDL_flag)
  {
    printer::GDL_Print(cout, original_input);
  }

  if (bm->UserFlags.print_STPinput_back_dot_flag)
  {
    printer::Dot_Print(cout, original_input);
  }
}

void Main::read_file()
{
  bool error = false;
  if (bm->UserFlags.smtlib1_parser_flag)
  {
    smtin = fopen(infile.c_str(), "r");
    toClose = smtin;
    if (smtin == NULL)
    {
      error = true;
    }
  }
  else if (bm->UserFlags.smtlib2_parser_flag)
  {
    smt2in = fopen(infile.c_str(), "r");
    toClose = smt2in;
    if (smt2in == NULL)
    {
      error = true;
    }
  }

  else
  {
    cvcin = fopen(infile.c_str(), "r");
    toClose = cvcin;
    if (cvcin == NULL)
    {
      error = true;
    }
  }

  if (error)
  {
    std::string errorMsg("Cannot open ");
    errorMsg += infile;
    FatalError(errorMsg.c_str());
  }
}

int Main::create_and_parse_options(int argc, char** argv)
{
  return 0;
}

void Main::check_infile_type()
{
  if (infile.size() >= 5)
  {
    if (!infile.compare(infile.length() - 4, 4, ".smt"))
    {
      bm->UserFlags.division_by_zero_returns_one_flag = true;
      bm->UserFlags.smtlib1_parser_flag = true;
    }
    if (!infile.compare(infile.length() - 5, 5, ".smt2"))
    {
      bm->UserFlags.division_by_zero_returns_one_flag = true;
      bm->UserFlags.smtlib2_parser_flag = true;
    }
  }
}

int Main::main(int argc, char** argv)
{
  auto_ptr<SimplifyingNodeFactory> simplifyingNF(
      new SimplifyingNodeFactory(*bm->hashingNodeFactory, *bm));
  bm->defaultNodeFactory = simplifyingNF.get();

  auto_ptr<Simplifier> simp(new Simplifier(bm));
  auto_ptr<ArrayTransformer> arrayTransformer(new ArrayTransformer(bm, simp.get()));
  auto_ptr<ToSAT> tosat(new ToSAT(bm));

  auto_ptr<AbsRefine_CounterExample> Ctr_Example(
      new AbsRefine_CounterExample(bm, simp.get(), arrayTransformer.get()));

  int ret = create_and_parse_options(argc, argv);
  if (ret != 0)
  {
    return ret;
  }

  GlobalSTP = new STP(bm, simp.get(), arrayTransformer.get(), tosat.get(),
                      Ctr_Example.get());

  // If we're not reading the file from stdin.
  if (!infile.empty())
    read_file();

  // want to print the output always from the commandline.
  bm->UserFlags.print_output_flag = true;
  ASTVec* AssertsQuery = new ASTVec;

  bm->GetRunTimes()->start(RunTimes::Parsing);
  parse_file(AssertsQuery);
  bm->GetRunTimes()->stop(RunTimes::Parsing);

  /*  The SMTLIB2 has a command language. The parser calls all the functions,
   *  so when we get to here the parser has already called "exit". i.e. if the
   *  language is smt2 then all the work has already been done, and all we need
   *  to do is cleanup...
   *    */
  if (!bm->UserFlags.smtlib2_parser_flag)
  {
    if (AssertsQuery->empty())
      FatalError("Input is Empty. Please enter some asserts and query\n");

    if (AssertsQuery->size() != 2)
      FatalError("Input must contain a query\n");

    ASTNode asserts = (*AssertsQuery)[0];
    ASTNode query = (*AssertsQuery)[1];

    if (onePrintBack)
    {
      print_back(query, asserts);
      return 0;
    }

    SOLVER_RETURN_TYPE ret = GlobalSTP->TopLevelSTP(asserts, query);
    if (bm->UserFlags.quick_statistics_flag)
    {
      bm->GetRunTimes()->print();
    }
    (GlobalSTP->tosat)->PrintOutput(ret);

    asserts = ASTNode();
    query = ASTNode();
  }

  // Without cleanup
  if (bm->UserFlags.isSet("fast-exit", "1"))
    exit(0);

  //Cleanup
  AssertsQuery->clear();
  delete AssertsQuery;
  _empty_ASTVec.clear();
  delete GlobalSTP;
  Cnf_ClearMemory();

  return 0;
}<commit_msg>Removing useless brackets<commit_after>/********************************************************************
 * AUTHORS: Vijay Ganesh, Trevor Hansen, Mate Soos
 *
 * BEGIN DATE: November, 2005
 *
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
********************************************************************/

#include "main_common.h"
#include "extlib-abc/cnf_short.h"

extern int smtparse(void*);
extern int smt2parse();
extern int cvcparse(void*);
extern int cvclex_destroy(void);
extern int smtlex_destroy(void);
extern int smt2lex_destroy(void);
extern void errorHandler(const char* error_msg);

// Amount of memory to ask for at beginning of main.
extern const intptr_t INITIAL_MEMORY_PREALLOCATION_SIZE;
extern FILE* cvcin;
extern FILE* smtin;
extern FILE* smt2in;

#ifdef EXT_HASH_MAP
using namespace __gnu_cxx;
#endif
using namespace BEEV;
using std::auto_ptr;
using std::cout;
using std::cerr;
using std::endl;

void errorHandler(const char* error_msg)
{
  cerr << prog << ": Error: " << error_msg << endl;
  exit(-1);
}

// Amount of memory to ask for at beginning of main.
const intptr_t INITIAL_MEMORY_PREALLOCATION_SIZE = 4000000;

Main::Main() : onePrintBack(false)
{
  bm = NULL;
  toClose = NULL;
  cvcin = NULL;
  smtin = NULL;
  smt2in = NULL;

  // Register the error handler
  vc_error_hdlr = errorHandler;

#if !defined(__MINGW32__) && !defined(__MINGW64__) && !defined(_MSC_VER)
  // Grab some memory from the OS upfront to reduce system time when
  // individual hash tables are being allocated
  if (sbrk(INITIAL_MEMORY_PREALLOCATION_SIZE) == ((void*)-1))
  {
    FatalError("Initial allocation of memory failed.");
  }
#endif

  bm = new STPMgr();
  ParserBM = bm;
}

Main::~Main()
{
  delete bm;
}

void Main::parse_file(ASTVec* AssertsQuery)
{
  TypeChecker nfTypeCheckSimp(*bm->defaultNodeFactory, *bm);
  TypeChecker nfTypeCheckDefault(*bm->hashingNodeFactory, *bm);

  Cpp_interface piTypeCheckSimp(*bm, &nfTypeCheckSimp);
  Cpp_interface piTypeCheckDefault(*bm, &nfTypeCheckDefault);

  // If you are converting formats, you probably don't want it simplifying (at
  // least I dont).
  if (onePrintBack)
  {
    parserInterface = &piTypeCheckDefault;
  }
  else
  {
    parserInterface = &piTypeCheckSimp;
  }

  parserInterface->startup();

  if (onePrintBack)
  {
    if (bm->UserFlags.smtlib2_parser_flag)
    {
      cerr << "Printback from SMTLIB2 inputs isn't currently working." << endl;
      cerr << "Please try again later" << endl;
      cerr << "It works prior to revision 1354" << endl;
      exit(1);
    }
  }

  if (bm->UserFlags.smtlib1_parser_flag)
  {
    smtparse((void*)AssertsQuery);
    smtlex_destroy();
  }
  else if (bm->UserFlags.smtlib2_parser_flag)
  {
    smt2parse();
    smt2lex_destroy();
  }
  else
  {
    cvcparse((void*)AssertsQuery);
    cvclex_destroy();
  }
  parserInterface = NULL;
  if (toClose != NULL)
  {
    fclose(toClose);
  }
}

void Main::print_back(ASTNode& query, ASTNode& asserts)
{
  ASTNode original_input =
      bm->CreateNode(AND, bm->CreateNode(NOT, query), asserts);

  if (bm->UserFlags.print_STPinput_back_flag)
  {
    if (bm->UserFlags.smtlib1_parser_flag)
    {
      bm->UserFlags.print_STPinput_back_SMTLIB2_flag = true;
    }
    else
    {
      bm->UserFlags.print_STPinput_back_CVC_flag = true;
    }
  }

  if (bm->UserFlags.print_STPinput_back_CVC_flag)
  {
    // needs just the query. Reads the asserts out of the data structure.
    print_STPInput_Back(original_input);
  }

  if (bm->UserFlags.print_STPinput_back_SMTLIB1_flag)
  {
    printer::SMTLIB1_PrintBack(cout, original_input);
  }

  if (bm->UserFlags.print_STPinput_back_SMTLIB2_flag)
  {
    printer::SMTLIB2_PrintBack(cout, original_input);
  }

  if (bm->UserFlags.print_STPinput_back_C_flag)
  {
    printer::C_Print(cout, original_input);
  }

  if (bm->UserFlags.print_STPinput_back_GDL_flag)
  {
    printer::GDL_Print(cout, original_input);
  }

  if (bm->UserFlags.print_STPinput_back_dot_flag)
  {
    printer::Dot_Print(cout, original_input);
  }
}

void Main::read_file()
{
  bool error = false;
  if (bm->UserFlags.smtlib1_parser_flag)
  {
    smtin = fopen(infile.c_str(), "r");
    toClose = smtin;
    if (smtin == NULL)
    {
      error = true;
    }
  }
  else if (bm->UserFlags.smtlib2_parser_flag)
  {
    smt2in = fopen(infile.c_str(), "r");
    toClose = smt2in;
    if (smt2in == NULL)
    {
      error = true;
    }
  }

  else
  {
    cvcin = fopen(infile.c_str(), "r");
    toClose = cvcin;
    if (cvcin == NULL)
    {
      error = true;
    }
  }

  if (error)
  {
    std::string errorMsg("Cannot open ");
    errorMsg += infile;
    FatalError(errorMsg.c_str());
  }
}

int Main::create_and_parse_options(int argc, char** argv)
{
  return 0;
}

void Main::check_infile_type()
{
  if (infile.size() >= 5)
  {
    if (!infile.compare(infile.length() - 4, 4, ".smt"))
    {
      bm->UserFlags.division_by_zero_returns_one_flag = true;
      bm->UserFlags.smtlib1_parser_flag = true;
    }
    if (!infile.compare(infile.length() - 5, 5, ".smt2"))
    {
      bm->UserFlags.division_by_zero_returns_one_flag = true;
      bm->UserFlags.smtlib2_parser_flag = true;
    }
  }
}

int Main::main(int argc, char** argv)
{
  auto_ptr<SimplifyingNodeFactory> simplifyingNF(
      new SimplifyingNodeFactory(*bm->hashingNodeFactory, *bm));
  bm->defaultNodeFactory = simplifyingNF.get();

  auto_ptr<Simplifier> simp(new Simplifier(bm));
  auto_ptr<ArrayTransformer> arrayTransformer(new ArrayTransformer(bm, simp.get()));
  auto_ptr<ToSAT> tosat(new ToSAT(bm));

  auto_ptr<AbsRefine_CounterExample> Ctr_Example(
      new AbsRefine_CounterExample(bm, simp.get(), arrayTransformer.get()));

  int ret = create_and_parse_options(argc, argv);
  if (ret != 0)
  {
    return ret;
  }

  GlobalSTP = new STP(bm, simp.get(), arrayTransformer.get(), tosat.get(),
                      Ctr_Example.get());

  // If we're not reading the file from stdin.
  if (!infile.empty())
    read_file();

  // want to print the output always from the commandline.
  bm->UserFlags.print_output_flag = true;
  ASTVec* AssertsQuery = new ASTVec;

  bm->GetRunTimes()->start(RunTimes::Parsing);
  parse_file(AssertsQuery);
  bm->GetRunTimes()->stop(RunTimes::Parsing);

  /*  The SMTLIB2 has a command language. The parser calls all the functions,
   *  so when we get to here the parser has already called "exit". i.e. if the
   *  language is smt2 then all the work has already been done, and all we need
   *  to do is cleanup...
   *    */
  if (!bm->UserFlags.smtlib2_parser_flag)
  {
    if (AssertsQuery->empty())
      FatalError("Input is Empty. Please enter some asserts and query\n");

    if (AssertsQuery->size() != 2)
      FatalError("Input must contain a query\n");

    ASTNode asserts = (*AssertsQuery)[0];
    ASTNode query = (*AssertsQuery)[1];

    if (onePrintBack)
    {
      print_back(query, asserts);
      return 0;
    }

    SOLVER_RETURN_TYPE ret = GlobalSTP->TopLevelSTP(asserts, query);
    if (bm->UserFlags.quick_statistics_flag)
    {
      bm->GetRunTimes()->print();
    }
    GlobalSTP->tosat->PrintOutput(ret);

    asserts = ASTNode();
    query = ASTNode();
  }

  // Without cleanup
  if (bm->UserFlags.isSet("fast-exit", "1"))
    exit(0);

  //Cleanup
  AssertsQuery->clear();
  delete AssertsQuery;
  _empty_ASTVec.clear();
  delete GlobalSTP;
  Cnf_ClearMemory();

  return 0;
}<|endoftext|>


<commit_before>// Copyright © 2016 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

#include <Arduino.h>
#include <TheThingsNetwork.h>

#define debugPrintLn(...) { if (debugStream) debugStream->println(__VA_ARGS__); }
#define debugPrint(...) { if (debugStream) debugStream->print(__VA_ARGS__); }

void TheThingsNetwork::init(Stream& modemStream, Stream& debugStream) {
  this->modemStream = &modemStream;
  this->debugStream = &debugStream;
}

String TheThingsNetwork::readLine(int waitTime) {
  unsigned long start = millis();
  while (millis() < start + waitTime) {
    String line = modemStream->readStringUntil('\n');
    if (line.length() > 0) {
      return line.substring(0, line.length() - 1);
    }
  }
  return "";
}

bool TheThingsNetwork::waitForOK(int waitTime, String okMessage) {
  String line = readLine(waitTime);
  if (line == "") {
    debugPrintLn(F("Wait for OK time-out expired"));
    return false;
  }

  if (line != okMessage) {
    debugPrint(F("Response is not OK: "));
    debugPrintLn(line);
    return false;
  }

  return true;
}

String TheThingsNetwork::readValue(String cmd) {
  modemStream->println(cmd);
  return readLine();
}

bool TheThingsNetwork::sendCommand(String cmd, int waitTime) {
  debugPrint(F("Sending: "));
  debugPrintLn(cmd);

  modemStream->println(cmd);

  return waitForOK(waitTime);
}

bool TheThingsNetwork::sendCommand(String cmd, String value, int waitTime) {
  int l = value.length();
  byte buf[l];
  value.getBytes(buf, l);

  return sendCommand(cmd, buf, l, waitTime);
}

char btohexa_high(unsigned char b) {
  b >>= 4;
  return (b > 0x9u) ? b + 'A' - 10 : b + '0';
}

char btohexa_low(unsigned char b) {
  b &= 0x0F;
  return (b > 0x9u) ? b + 'A' - 10 : b + '0';
}

bool TheThingsNetwork::sendCommand(String cmd, const byte *buf, int length, int waitTime) {
  debugPrint(F("Sending: "));
  debugPrint(cmd);
  debugPrint(F(" with "));
  debugPrint(length);
  debugPrintLn(F(" bytes"));

  modemStream->print(cmd + " ");

  for (int i = 0; i < length; i++) {
    modemStream->print(btohexa_high(buf[i]));
    modemStream->print(btohexa_low(buf[i]));
  }
  modemStream->println();

  return waitForOK(waitTime);
}

void TheThingsNetwork::reset(bool adr, int sf, int fsb) {
  #if !ADR_SUPPORTED
    adr = false;
  #endif

  modemStream->println(F("sys reset"));
  String version = readLine(3000);
  if (version == "") {
    debugPrintLn(F("Invalid version"));
    return;
  }

  model = version.substring(0, version.indexOf(' '));
  debugPrint(F("Version is "));
  debugPrint(version);
  debugPrint(F(", model is "));
  debugPrintLn(model);

  String str = "";
  str.concat(F("mac set adr "));
  if(adr){
    str.concat(F("on"));
  } else {
    str.concat(F("off"));
  }
  sendCommand(str);

  int dr = -1;
  if (model == F("RN2483")) {
    str = "";
    str.concat(F("mac set pwridx "));
    str.concat(PWRIDX_868);
    sendCommand(str);

    switch (sf) {
      case 7:
        dr = 5;
        break;
      case 8:
        dr = 4;
        break;
      case 9:
        dr = 3;
        break;
      case 10:
        dr = 2;
        break;
      case 11:
        dr = 1;
        break;
      case 12:
        dr = 0;
        break;
      default:
        debugPrintLn(F("Invalid SF"))
        break;
    }
  }
  else if (model == F("RN2903")) {
    str = "";
    str.concat(F("mac set pwridx "));
    str.concat(PWRIDX_915);
    sendCommand(str);
    enableFsbChannels(fsb);

    switch (sf) {
      case 7:
        dr = 3;
        break;
      case 8:
        dr = 2;
        break;
      case 9:
        dr = 1;
        break;
      case 10:
        dr = 0;
        break;
      default:
        debugPrintLn(F("Invalid SF"))
        break;
    }
  }

  if (dr > -1){
    str = "";
    str.concat(F("mac set dr "));
    str.concat(dr);
    sendCommand(str);
  }
}

bool TheThingsNetwork::enableFsbChannels(int fsb) {
  int chLow = fsb > 0 ? (fsb - 1) * 8 : 0;
  int chHigh = fsb > 0 ? chLow + 7 : 71;
  int ch500 = fsb + 63;

  for (int i = 0; i < 72; i++){
    String str = "";
    str.concat(F("mac set ch status "));
    str.concat(i);
    if (i == ch500 || chLow <= i && i <= chHigh){
      str.concat(F(" on"));
    }
    else{
      str.concat(F(" off"));
    }
    sendCommand(str);
  }
  return true;
}

bool TheThingsNetwork::personalize(const byte devAddr[4], const byte nwkSKey[16], const byte appSKey[16], bool reset) {

  if (reset == true)
    TheThingsNetwork::reset();
  sendCommand(F("mac set devaddr"), devAddr, 4);
  sendCommand(F("mac set nwkskey"), nwkSKey, 16);
  sendCommand(F("mac set appskey"), appSKey, 16);
  sendCommand(F("mac join abp"));

  String response = readLine();
  if (response != F("accepted")) {
    debugPrint(F("Personalize not accepted: "));
    debugPrintLn(response);
    return false;
  }

  debugPrint(F("Personalize accepted. Status: "));
  debugPrintLn(readValue(F("mac get status")));
  return true;
}

bool TheThingsNetwork::join(const byte appEui[8], const byte appKey[16]) {
  String devEui = readValue(F("sys get hweui"));
  sendCommand(F("mac set appeui"), appEui, 8);
  String str = "";
  str.concat(F("mac set deveui "));
  str.concat(devEui);
  sendCommand(str);
  sendCommand(F("mac set appkey"), appKey, 16);
  if (!sendCommand(F("mac join otaa"))) {
    debugPrintLn(F("Send join command failed"));
    return false;
  }

  String response = readLine(10000);
  if (response != F("accepted")) {
    debugPrint(F("Join not accepted: "));
    debugPrintLn(response);
    return false;
  }

  debugPrint(F("Join accepted. Status: "));
  debugPrintLn(readValue(F("mac get status")));
  return true;
}

int TheThingsNetwork::sendBytes(const byte* buffer, int length, int port, bool confirm) {
  String str = "";
  str.concat(F("mac tx "));
  str.concat(confirm ? F("cnf ") : F("uncnf "));
  str.concat(port);
  if (!sendCommand(str, buffer, length)) {
    debugPrintLn(F("Send command failed"));
    return 0;
  }

  String response = readLine(10000);
  if (response == "") {
    debugPrintLn(F("Time-out"));
    return 0;
  }
  if (response == F("mac_tx_ok")) {
    debugPrintLn(F("Successful transmission"));
    return 0;
  }
  if (response.startsWith(F("mac_rx"))) {
    int portEnds = response.indexOf(" ", 7);
    this->downlinkPort = response.substring(7, portEnds).toInt();
    String data = response.substring(portEnds + 1);
    int downlinkLength = data.length() / 2;
    for (int i = 0, d = 0; i < downlinkLength; i++, d += 2)
      this->downlink[i] = HEX_PAIR_TO_BYTE(data[d], data[d+1]);
    debugPrint(F("Successful transmission. Received "));
    debugPrint(downlinkLength);
    debugPrintLn(F(" bytes"));
    return downlinkLength;
  }

  debugPrint(F("Unexpected response: "));
  debugPrintLn(response);
}

int TheThingsNetwork::sendString(String message, int port, bool confirm) {
  int l = message.length();
  byte buf[l + 1];
  message.getBytes(buf, l + 1);

  return sendBytes(buf, l, port, confirm);
}

void TheThingsNetwork::showStatus() {
  debugPrint(F("EUI: "));
  debugPrintLn(readValue(F("sys get hweui")));
  debugPrint(F("Battery: "));
  debugPrint(readValue(F("sys get vdd")));
  debugPrint(F("AppEUI: "));
  debugPrintLn(readValue(F("mac get appeui")));
  debugPrint(F("DevEUI: "));
  debugPrintLn(readValue(F("mac get deveui")));
  debugPrint(F("DevAddr: "));
  debugPrintLn(readValue(F("mac get devaddr")));

  if (this->model == F("RN2483")) {
    debugPrint(F("Band: "));
    debugPrintLn(readValue(F("mac get band")));
  }

  debugPrint(F("Data Rate: "));
  debugPrintLn(readValue(F("mac get dr")));
  debugPrint(F("RX Delay 1: "));
  debugPrintLn(readValue(F("mac get rxdelay1")));
  debugPrint(F("RX Delay 2: "));
  debugPrintLn(readValue(F("mac get rxdelay2")));
}
<commit_msg>fixed reset = true<commit_after>// Copyright © 2016 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

#include <Arduino.h>
#include <TheThingsNetwork.h>

#define debugPrintLn(...) { if (debugStream) debugStream->println(__VA_ARGS__); }
#define debugPrint(...) { if (debugStream) debugStream->print(__VA_ARGS__); }

void TheThingsNetwork::init(Stream& modemStream, Stream& debugStream) {
  this->modemStream = &modemStream;
  this->debugStream = &debugStream;
}

String TheThingsNetwork::readLine(int waitTime) {
  unsigned long start = millis();
  while (millis() < start + waitTime) {
    String line = modemStream->readStringUntil('\n');
    if (line.length() > 0) {
      return line.substring(0, line.length() - 1);
    }
  }
  return "";
}

bool TheThingsNetwork::waitForOK(int waitTime, String okMessage) {
  String line = readLine(waitTime);
  if (line == "") {
    debugPrintLn(F("Wait for OK time-out expired"));
    return false;
  }

  if (line != okMessage) {
    debugPrint(F("Response is not OK: "));
    debugPrintLn(line);
    return false;
  }

  return true;
}

String TheThingsNetwork::readValue(String cmd) {
  modemStream->println(cmd);
  return readLine();
}

bool TheThingsNetwork::sendCommand(String cmd, int waitTime) {
  debugPrint(F("Sending: "));
  debugPrintLn(cmd);

  modemStream->println(cmd);

  return waitForOK(waitTime);
}

bool TheThingsNetwork::sendCommand(String cmd, String value, int waitTime) {
  int l = value.length();
  byte buf[l];
  value.getBytes(buf, l);

  return sendCommand(cmd, buf, l, waitTime);
}

char btohexa_high(unsigned char b) {
  b >>= 4;
  return (b > 0x9u) ? b + 'A' - 10 : b + '0';
}

char btohexa_low(unsigned char b) {
  b &= 0x0F;
  return (b > 0x9u) ? b + 'A' - 10 : b + '0';
}

bool TheThingsNetwork::sendCommand(String cmd, const byte *buf, int length, int waitTime) {
  debugPrint(F("Sending: "));
  debugPrint(cmd);
  debugPrint(F(" with "));
  debugPrint(length);
  debugPrintLn(F(" bytes"));

  modemStream->print(cmd + " ");

  for (int i = 0; i < length; i++) {
    modemStream->print(btohexa_high(buf[i]));
    modemStream->print(btohexa_low(buf[i]));
  }
  modemStream->println();

  return waitForOK(waitTime);
}

void TheThingsNetwork::reset(bool adr, int sf, int fsb) {
  #if !ADR_SUPPORTED
    adr = false;
  #endif

  modemStream->println(F("sys reset"));
  String version = readLine(3000);
  if (version == "") {
    debugPrintLn(F("Invalid version"));
    return;
  }

  model = version.substring(0, version.indexOf(' '));
  debugPrint(F("Version is "));
  debugPrint(version);
  debugPrint(F(", model is "));
  debugPrintLn(model);

  String str = "";
  str.concat(F("mac set adr "));
  if(adr){
    str.concat(F("on"));
  } else {
    str.concat(F("off"));
  }
  sendCommand(str);

  int dr = -1;
  if (model == F("RN2483")) {
    str = "";
    str.concat(F("mac set pwridx "));
    str.concat(PWRIDX_868);
    sendCommand(str);

    switch (sf) {
      case 7:
        dr = 5;
        break;
      case 8:
        dr = 4;
        break;
      case 9:
        dr = 3;
        break;
      case 10:
        dr = 2;
        break;
      case 11:
        dr = 1;
        break;
      case 12:
        dr = 0;
        break;
      default:
        debugPrintLn(F("Invalid SF"))
        break;
    }
  }
  else if (model == F("RN2903")) {
    str = "";
    str.concat(F("mac set pwridx "));
    str.concat(PWRIDX_915);
    sendCommand(str);
    enableFsbChannels(fsb);

    switch (sf) {
      case 7:
        dr = 3;
        break;
      case 8:
        dr = 2;
        break;
      case 9:
        dr = 1;
        break;
      case 10:
        dr = 0;
        break;
      default:
        debugPrintLn(F("Invalid SF"))
        break;
    }
  }

  if (dr > -1){
    str = "";
    str.concat(F("mac set dr "));
    str.concat(dr);
    sendCommand(str);
  }
}

bool TheThingsNetwork::enableFsbChannels(int fsb) {
  int chLow = fsb > 0 ? (fsb - 1) * 8 : 0;
  int chHigh = fsb > 0 ? chLow + 7 : 71;
  int ch500 = fsb + 63;

  for (int i = 0; i < 72; i++){
    String str = "";
    str.concat(F("mac set ch status "));
    str.concat(i);
    if (i == ch500 || chLow <= i && i <= chHigh){
      str.concat(F(" on"));
    }
    else{
      str.concat(F(" off"));
    }
    sendCommand(str);
  }
  return true;
}

bool TheThingsNetwork::personalize(const byte devAddr[4], const byte nwkSKey[16], const byte appSKey[16], bool reset) {

  if (reset) {
    TheThingsNetwork::reset();
  }
  sendCommand(F("mac set devaddr"), devAddr, 4);
  sendCommand(F("mac set nwkskey"), nwkSKey, 16);
  sendCommand(F("mac set appskey"), appSKey, 16);
  sendCommand(F("mac join abp"));

  String response = readLine();
  if (response != F("accepted")) {
    debugPrint(F("Personalize not accepted: "));
    debugPrintLn(response);
    return false;
  }

  debugPrint(F("Personalize accepted. Status: "));
  debugPrintLn(readValue(F("mac get status")));
  return true;
}

bool TheThingsNetwork::join(const byte appEui[8], const byte appKey[16]) {
  String devEui = readValue(F("sys get hweui"));
  sendCommand(F("mac set appeui"), appEui, 8);
  String str = "";
  str.concat(F("mac set deveui "));
  str.concat(devEui);
  sendCommand(str);
  sendCommand(F("mac set appkey"), appKey, 16);
  if (!sendCommand(F("mac join otaa"))) {
    debugPrintLn(F("Send join command failed"));
    return false;
  }

  String response = readLine(10000);
  if (response != F("accepted")) {
    debugPrint(F("Join not accepted: "));
    debugPrintLn(response);
    return false;
  }

  debugPrint(F("Join accepted. Status: "));
  debugPrintLn(readValue(F("mac get status")));
  return true;
}

int TheThingsNetwork::sendBytes(const byte* buffer, int length, int port, bool confirm) {
  String str = "";
  str.concat(F("mac tx "));
  str.concat(confirm ? F("cnf ") : F("uncnf "));
  str.concat(port);
  if (!sendCommand(str, buffer, length)) {
    debugPrintLn(F("Send command failed"));
    return 0;
  }

  String response = readLine(10000);
  if (response == "") {
    debugPrintLn(F("Time-out"));
    return 0;
  }
  if (response == F("mac_tx_ok")) {
    debugPrintLn(F("Successful transmission"));
    return 0;
  }
  if (response.startsWith(F("mac_rx"))) {
    int portEnds = response.indexOf(" ", 7);
    this->downlinkPort = response.substring(7, portEnds).toInt();
    String data = response.substring(portEnds + 1);
    int downlinkLength = data.length() / 2;
    for (int i = 0, d = 0; i < downlinkLength; i++, d += 2)
      this->downlink[i] = HEX_PAIR_TO_BYTE(data[d], data[d+1]);
    debugPrint(F("Successful transmission. Received "));
    debugPrint(downlinkLength);
    debugPrintLn(F(" bytes"));
    return downlinkLength;
  }

  debugPrint(F("Unexpected response: "));
  debugPrintLn(response);
}

int TheThingsNetwork::sendString(String message, int port, bool confirm) {
  int l = message.length();
  byte buf[l + 1];
  message.getBytes(buf, l + 1);

  return sendBytes(buf, l, port, confirm);
}

void TheThingsNetwork::showStatus() {
  debugPrint(F("EUI: "));
  debugPrintLn(readValue(F("sys get hweui")));
  debugPrint(F("Battery: "));
  debugPrint(readValue(F("sys get vdd")));
  debugPrint(F("AppEUI: "));
  debugPrintLn(readValue(F("mac get appeui")));
  debugPrint(F("DevEUI: "));
  debugPrintLn(readValue(F("mac get deveui")));
  debugPrint(F("DevAddr: "));
  debugPrintLn(readValue(F("mac get devaddr")));

  if (this->model == F("RN2483")) {
    debugPrint(F("Band: "));
    debugPrintLn(readValue(F("mac get band")));
  }

  debugPrint(F("Data Rate: "));
  debugPrintLn(readValue(F("mac get dr")));
  debugPrint(F("RX Delay 1: "));
  debugPrintLn(readValue(F("mac get rxdelay1")));
  debugPrint(F("RX Delay 2: "));
  debugPrintLn(readValue(F("mac get rxdelay2")));
}
<|endoftext|>