<commit_before>/*
 * Copyright © 2010 Intel Corporation
 *
 * 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 (including the next
 * paragraph) 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.
 */

/**
 * \file ir_dead_code.cpp
 *
 * Eliminates dead assignments and variable declarations from the code.
 */

#define NULL 0
#include "ir.h"
#include "ir_visitor.h"
#include "ir_expression_flattening.h"
#include "glsl_types.h"

class variable_entry : public exec_node
{
public:
   variable_entry(ir_variable *var)
   {
      this->var = var;
      assign = NULL;
      referenced = false;
      declaration = false;
   }

   ir_variable *var; /* The key: the variable's pointer. */
   ir_assignment *assign; /* An assignment to the variable, if any */
   bool referenced; /* If the variable has ever been referenced. */
   bool declaration; /* If the variable had a decl in the instruction stream */
};

class ir_dead_code_visitor : public ir_visitor {
public:

   /**
    * \name Visit methods
    *
    * As typical for the visitor pattern, there must be one \c visit method for
    * each concrete subclass of \c ir_instruction.  Virtual base classes within
    * the hierarchy should not have \c visit methods.
    */
   /*@{*/
   virtual void visit(ir_variable *);
   virtual void visit(ir_loop *);
   virtual void visit(ir_loop_jump *);
   virtual void visit(ir_function_signature *);
   virtual void visit(ir_function *);
   virtual void visit(ir_expression *);
   virtual void visit(ir_swizzle *);
   virtual void visit(ir_dereference *);
   virtual void visit(ir_assignment *);
   virtual void visit(ir_constant *);
   virtual void visit(ir_call *);
   virtual void visit(ir_return *);
   virtual void visit(ir_if *);
   /*@}*/

   variable_entry *get_variable_entry(ir_variable *var);

   bool (*predicate)(ir_instruction *ir);
   ir_instruction *base_ir;

   /* List of variable_entry */
   exec_list variable_list;
};

variable_entry *
ir_dead_code_visitor::get_variable_entry(ir_variable *var)
{
   assert(var);
   foreach_iter(exec_list_iterator, iter, this->variable_list) {
      variable_entry *entry = (variable_entry *)iter.get();
      if (entry->var == var)
	 return entry;
   }

   variable_entry *entry = new variable_entry(var);
   this->variable_list.push_tail(entry);
   return entry;
}

void
find_dead_code(exec_list *instructions, ir_dead_code_visitor *v)
{
   foreach_iter(exec_list_iterator, iter, *instructions) {
      ir_instruction *ir = (ir_instruction *)iter.get();

      ir->accept(v);
   }
}

void
ir_dead_code_visitor::visit(ir_variable *ir)
{
   variable_entry *entry = this->get_variable_entry(ir);
   if (entry) {
      entry->declaration = true;
   }
}

void
ir_dead_code_visitor::visit(ir_loop *ir)
{
   find_dead_code(&ir->body_instructions, this);
   if (ir->from)
      ir->from->accept(this);
   if (ir->to)
      ir->to->accept(this);
   if (ir->increment)
      ir->increment->accept(this);
}

void
ir_dead_code_visitor::visit(ir_loop_jump *ir)
{
   (void) ir;
}

void
ir_dead_code_visitor::visit(ir_function_signature *ir)
{
   find_dead_code(&ir->body, this);
}

void
ir_dead_code_visitor::visit(ir_function *ir)
{
   (void) ir;
}

void
ir_dead_code_visitor::visit(ir_expression *ir)
{
   unsigned int operand;

   for (operand = 0; operand < ir->get_num_operands(); operand++) {
      ir->operands[operand]->accept(this);
   }
}

void
ir_dead_code_visitor::visit(ir_swizzle *ir)
{
   ir->val->accept(this);
}

void
ir_dead_code_visitor::visit(ir_dereference *ir)
{
   ir_variable *var;

   if (ir->mode == ir_dereference::ir_reference_array) {
      ir->selector.array_index->accept(this);
   }

   var = ir->var->as_variable();
   if (var) {
      variable_entry *entry = this->get_variable_entry(var);
      entry->referenced = true;
   } else {
      ir->var->accept(this);
   }
}

void
ir_dead_code_visitor::visit(ir_assignment *ir)
{
   ir_instruction *lhs = ir->lhs;

   /* Walk through the LHS and mark references for variables used in
    * array indices but not for the assignment dereference.
    */
   while (lhs) {
      if (lhs->as_variable())
	 break;

      ir_dereference *deref = lhs->as_dereference();
      if (deref) {
	 if (deref->mode == ir_dereference::ir_reference_array)
	    deref->selector.array_index->accept(this);
	 lhs = deref->var;
      } else {
	 ir_swizzle *swiz = lhs->as_swizzle();

	 lhs = swiz->val;
      }
   }

   ir->rhs->accept(this);
   if (ir->condition)
      ir->condition->accept(this);

   variable_entry *entry;
   entry = this->get_variable_entry(lhs->as_variable());
   if (entry) {
      if (entry->assign == NULL)
	 entry->assign = ir;
   }
}

void
ir_dead_code_visitor::visit(ir_constant *ir)
{
   (void) ir;
}

void
ir_dead_code_visitor::visit(ir_call *ir)
{
   foreach_iter(exec_list_iterator, iter, *ir) {
      ir_rvalue *param = (ir_rvalue *)iter.get();

      /* FINISHME: handle out values. */
      param->accept(this);
   }

   /* Ignore the callee.  Function bodies will get handled when they're
    * encountered at the top level instruction stream and spawn their
    * own dead code visitor.
    */
}

void
ir_dead_code_visitor::visit(ir_return *ir)
{
   ir_rvalue *val = ir->get_value();

   if (val)
      val->accept(this);
}

void
ir_dead_code_visitor::visit(ir_if *ir)
{
   ir->condition->accept(this);

   find_dead_code(&ir->then_instructions, this);
   find_dead_code(&ir->else_instructions, this);
}

/**
 * Do a dead code pass over instructions and everything that instructions
 * references.
 *
 * Note that this will remove assignments to globals, so it is not suitable
 * for usage on an unlinked instruction stream.
 */
bool
do_dead_code(exec_list *instructions)
{
   ir_dead_code_visitor v;
   bool progress = false;

   find_dead_code(instructions, &v);

   foreach_iter(exec_list_iterator, iter, v.variable_list) {
      variable_entry *entry = (variable_entry *)iter.get();

      if (entry->referenced || !entry->declaration)
	 continue;

      if (entry->assign) {
	 /* Remove a single dead assignment to the variable we found.
	  * Don't do so if it's a shader output, though.
	  */
	 if (!entry->var->shader_out) {
	    entry->assign->remove();
	    progress = true;
	 }
      } else {
	 /* If there are no assignments or references to the variable left,
	  * then we can remove its declaration.
	  */
	 entry->var->remove();
	 progress = true;
      }
   }
   return progress;
}

/**
 * Does a dead code pass on the functions present in the instruction stream.
 *
 * This is suitable for use while the program is not linked, as it will
 * ignore variable declarations (and the assignments to them) for variables
 * with global scope.
 */
bool
do_dead_code_unlinked(exec_list *instructions)
{
   bool progress = false;

   foreach_iter(exec_list_iterator, iter, *instructions) {
      ir_instruction *ir = (ir_instruction *)iter.get();
      ir_function *f = ir->as_function();
      if (f) {
	 foreach_iter(exec_list_iterator, sigiter, *f) {
	    ir_function_signature *sig =
	       (ir_function_signature *) sigiter.get();
	    if (do_dead_code(&sig->body))
	       progress = true;
	 }
      }
   }

   return progress;
}
<commit_msg>Replace find_dead_code with visit_exec_list<commit_after>/*
 * Copyright © 2010 Intel Corporation
 *
 * 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 (including the next
 * paragraph) 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.
 */

/**
 * \file ir_dead_code.cpp
 *
 * Eliminates dead assignments and variable declarations from the code.
 */

#define NULL 0
#include "ir.h"
#include "ir_visitor.h"
#include "ir_expression_flattening.h"
#include "glsl_types.h"

class variable_entry : public exec_node
{
public:
   variable_entry(ir_variable *var)
   {
      this->var = var;
      assign = NULL;
      referenced = false;
      declaration = false;
   }

   ir_variable *var; /* The key: the variable's pointer. */
   ir_assignment *assign; /* An assignment to the variable, if any */
   bool referenced; /* If the variable has ever been referenced. */
   bool declaration; /* If the variable had a decl in the instruction stream */
};

class ir_dead_code_visitor : public ir_visitor {
public:

   /**
    * \name Visit methods
    *
    * As typical for the visitor pattern, there must be one \c visit method for
    * each concrete subclass of \c ir_instruction.  Virtual base classes within
    * the hierarchy should not have \c visit methods.
    */
   /*@{*/
   virtual void visit(ir_variable *);
   virtual void visit(ir_loop *);
   virtual void visit(ir_loop_jump *);
   virtual void visit(ir_function_signature *);
   virtual void visit(ir_function *);
   virtual void visit(ir_expression *);
   virtual void visit(ir_swizzle *);
   virtual void visit(ir_dereference *);
   virtual void visit(ir_assignment *);
   virtual void visit(ir_constant *);
   virtual void visit(ir_call *);
   virtual void visit(ir_return *);
   virtual void visit(ir_if *);
   /*@}*/

   variable_entry *get_variable_entry(ir_variable *var);

   bool (*predicate)(ir_instruction *ir);
   ir_instruction *base_ir;

   /* List of variable_entry */
   exec_list variable_list;
};

variable_entry *
ir_dead_code_visitor::get_variable_entry(ir_variable *var)
{
   assert(var);
   foreach_iter(exec_list_iterator, iter, this->variable_list) {
      variable_entry *entry = (variable_entry *)iter.get();
      if (entry->var == var)
	 return entry;
   }

   variable_entry *entry = new variable_entry(var);
   this->variable_list.push_tail(entry);
   return entry;
}

void
ir_dead_code_visitor::visit(ir_variable *ir)
{
   variable_entry *entry = this->get_variable_entry(ir);
   if (entry) {
      entry->declaration = true;
   }
}

void
ir_dead_code_visitor::visit(ir_loop *ir)
{
   visit_exec_list(&ir->body_instructions, this);
   if (ir->from)
      ir->from->accept(this);
   if (ir->to)
      ir->to->accept(this);
   if (ir->increment)
      ir->increment->accept(this);
}

void
ir_dead_code_visitor::visit(ir_loop_jump *ir)
{
   (void) ir;
}

void
ir_dead_code_visitor::visit(ir_function_signature *ir)
{
   visit_exec_list(&ir->body, this);
}

void
ir_dead_code_visitor::visit(ir_function *ir)
{
   (void) ir;
}

void
ir_dead_code_visitor::visit(ir_expression *ir)
{
   unsigned int operand;

   for (operand = 0; operand < ir->get_num_operands(); operand++) {
      ir->operands[operand]->accept(this);
   }
}

void
ir_dead_code_visitor::visit(ir_swizzle *ir)
{
   ir->val->accept(this);
}

void
ir_dead_code_visitor::visit(ir_dereference *ir)
{
   ir_variable *var;

   if (ir->mode == ir_dereference::ir_reference_array) {
      ir->selector.array_index->accept(this);
   }

   var = ir->var->as_variable();
   if (var) {
      variable_entry *entry = this->get_variable_entry(var);
      entry->referenced = true;
   } else {
      ir->var->accept(this);
   }
}

void
ir_dead_code_visitor::visit(ir_assignment *ir)
{
   ir_instruction *lhs = ir->lhs;

   /* Walk through the LHS and mark references for variables used in
    * array indices but not for the assignment dereference.
    */
   while (lhs) {
      if (lhs->as_variable())
	 break;

      ir_dereference *deref = lhs->as_dereference();
      if (deref) {
	 if (deref->mode == ir_dereference::ir_reference_array)
	    deref->selector.array_index->accept(this);
	 lhs = deref->var;
      } else {
	 ir_swizzle *swiz = lhs->as_swizzle();

	 lhs = swiz->val;
      }
   }

   ir->rhs->accept(this);
   if (ir->condition)
      ir->condition->accept(this);

   variable_entry *entry;
   entry = this->get_variable_entry(lhs->as_variable());
   if (entry) {
      if (entry->assign == NULL)
	 entry->assign = ir;
   }
}

void
ir_dead_code_visitor::visit(ir_constant *ir)
{
   (void) ir;
}

void
ir_dead_code_visitor::visit(ir_call *ir)
{
   foreach_iter(exec_list_iterator, iter, *ir) {
      ir_rvalue *param = (ir_rvalue *)iter.get();

      /* FINISHME: handle out values. */
      param->accept(this);
   }

   /* Ignore the callee.  Function bodies will get handled when they're
    * encountered at the top level instruction stream and spawn their
    * own dead code visitor.
    */
}

void
ir_dead_code_visitor::visit(ir_return *ir)
{
   ir_rvalue *val = ir->get_value();

   if (val)
      val->accept(this);
}

void
ir_dead_code_visitor::visit(ir_if *ir)
{
   ir->condition->accept(this);

   visit_exec_list(&ir->then_instructions, this);
   visit_exec_list(&ir->else_instructions, this);
}

/**
 * Do a dead code pass over instructions and everything that instructions
 * references.
 *
 * Note that this will remove assignments to globals, so it is not suitable
 * for usage on an unlinked instruction stream.
 */
bool
do_dead_code(exec_list *instructions)
{
   ir_dead_code_visitor v;
   bool progress = false;

   visit_exec_list(instructions, &v);

   foreach_iter(exec_list_iterator, iter, v.variable_list) {
      variable_entry *entry = (variable_entry *)iter.get();

      if (entry->referenced || !entry->declaration)
	 continue;

      if (entry->assign) {
	 /* Remove a single dead assignment to the variable we found.
	  * Don't do so if it's a shader output, though.
	  */
	 if (!entry->var->shader_out) {
	    entry->assign->remove();
	    progress = true;
	 }
      } else {
	 /* If there are no assignments or references to the variable left,
	  * then we can remove its declaration.
	  */
	 entry->var->remove();
	 progress = true;
      }
   }
   return progress;
}

/**
 * Does a dead code pass on the functions present in the instruction stream.
 *
 * This is suitable for use while the program is not linked, as it will
 * ignore variable declarations (and the assignments to them) for variables
 * with global scope.
 */
bool
do_dead_code_unlinked(exec_list *instructions)
{
   bool progress = false;

   foreach_iter(exec_list_iterator, iter, *instructions) {
      ir_instruction *ir = (ir_instruction *)iter.get();
      ir_function *f = ir->as_function();
      if (f) {
	 foreach_iter(exec_list_iterator, sigiter, *f) {
	    ir_function_signature *sig =
	       (ir_function_signature *) sigiter.get();
	    if (do_dead_code(&sig->body))
	       progress = true;
	 }
      }
   }

   return progress;
}
<|endoftext|>


<commit_before>/*
 *   Copyright (C) 2014 Pelagicore AB
 *   All rights reserved.
 */
#include <sys/wait.h>
#include <unistd.h>
#include <glibmm.h>

#include "gateway.h"
#include "container.h"
#include "pelagicontain.h"

Pelagicontain::Pelagicontain()
{
    m_containerState = ContainerState::CREATED;
}

Pelagicontain::~Pelagicontain()
{
}

void Pelagicontain::addGateway(Gateway &gateway)
{
    gateway.setContainer(*m_container);
    m_gateways.push_back(&gateway);
}

// Preload the container. This is a non-blocking operation
pid_t Pelagicontain::preload(Container &container)
{
    m_container = &container;
    if (isError(m_container->create()))
    	return INVALID_PID;

    pid_t pid = m_container->start();
    m_containerState.setValueNotify(ContainerState::PRELOADED);
    return pid;
}

void Pelagicontain::shutdownContainer()
{
    shutdownGateways();
    m_container->destroy();

    m_containerState.setValueNotify(ContainerState::TERMINATED);
}

void Pelagicontain::shutdownContainer(unsigned int timeout)
{
    shutdownGateways();
    m_container->destroy(timeout);

    m_containerState.setValueNotify(ContainerState::TERMINATED);
}

pid_t Pelagicontain::launchCommand(const std::string &commandLine)
{
    log_debug() << "launchCommand called with commandLine: " << commandLine;
    pid_t pid = m_container->attach(commandLine);

    assert(m_mainLoopContext != nullptr);
    addProcessListener(m_connections, pid, [&](pid_t pid, int returnCode) {
                shutdown();
            }, *m_mainLoopContext);

    return pid;
}

void Pelagicontain::updateGatewayConfiguration(const GatewayConfiguration &configs)
{
    log_debug() << "updateGatewayConfiguration called" << configs;
    setGatewayConfigs(configs);
}

void Pelagicontain::setGatewayConfigs(const GatewayConfiguration &configs)
{
    // Go through the received configs and see if they match any of
    // the running gateways, if so: set their respective config

    for (auto &gateway : m_gateways) {
        std::string gatewayId = gateway->id();

        if (configs.count(gatewayId) != 0) {
            std::string config = configs.at(gatewayId);
            gateway->setConfig(config);
        }
    }

    for (auto &gateway : m_gateways) {
        gateway->activate();
    }

    m_containerState.setValueNotify(ContainerState::READY);

}

void Pelagicontain::shutdown()
{
    log_debug() << "shutdown called"; // << logging::getStackTrace();
    shutdownContainer();
}

void Pelagicontain::shutdown(unsigned int timeout)
{
    log_debug() << "shutdown called"; // << logging::getStackTrace();
    shutdownContainer(timeout);
}

void Pelagicontain::shutdownGateways()
{
    for (auto &gateway : m_gateways) {
        if (!gateway->teardown()) {
            log_warning() << "Could not tear down gateway cleanly";
        }
    }

    m_gateways.clear();
}
<commit_msg>pelagicontain.cpp: add if/else instead of if/fallthrough for clarity.<commit_after>/*
 *   Copyright (C) 2014 Pelagicore AB
 *   All rights reserved.
 */
#include <sys/wait.h>
#include <unistd.h>
#include <glibmm.h>

#include "gateway.h"
#include "container.h"
#include "pelagicontain.h"

Pelagicontain::Pelagicontain()
{
    m_containerState = ContainerState::CREATED;
}

Pelagicontain::~Pelagicontain()
{
}

void Pelagicontain::addGateway(Gateway &gateway)
{
    gateway.setContainer(*m_container);
    m_gateways.push_back(&gateway);
}

// Preload the container. This is a non-blocking operation
pid_t Pelagicontain::preload(Container &container)
{
    m_container = &container;
    if (isError(m_container->create())) {
    	return INVALID_PID;
    } else {
        pid_t pid = m_container->start();
        m_containerState.setValueNotify(ContainerState::PRELOADED);
        return pid;
    }
}

void Pelagicontain::shutdownContainer()
{
    shutdownGateways();
    m_container->destroy();

    m_containerState.setValueNotify(ContainerState::TERMINATED);
}

void Pelagicontain::shutdownContainer(unsigned int timeout)
{
    shutdownGateways();
    m_container->destroy(timeout);

    m_containerState.setValueNotify(ContainerState::TERMINATED);
}

pid_t Pelagicontain::launchCommand(const std::string &commandLine)
{
    log_debug() << "launchCommand called with commandLine: " << commandLine;
    pid_t pid = m_container->attach(commandLine);

    assert(m_mainLoopContext != nullptr);
    addProcessListener(m_connections, pid, [&](pid_t pid, int returnCode) {
                shutdown();
            }, *m_mainLoopContext);

    return pid;
}

void Pelagicontain::updateGatewayConfiguration(const GatewayConfiguration &configs)
{
    log_debug() << "updateGatewayConfiguration called" << configs;
    setGatewayConfigs(configs);
}

void Pelagicontain::setGatewayConfigs(const GatewayConfiguration &configs)
{
    // Go through the received configs and see if they match any of
    // the running gateways, if so: set their respective config

    for (auto &gateway : m_gateways) {
        std::string gatewayId = gateway->id();

        if (configs.count(gatewayId) != 0) {
            std::string config = configs.at(gatewayId);
            gateway->setConfig(config);
        }
    }

    for (auto &gateway : m_gateways) {
        gateway->activate();
    }

    m_containerState.setValueNotify(ContainerState::READY);

}

void Pelagicontain::shutdown()
{
    log_debug() << "shutdown called"; // << logging::getStackTrace();
    shutdownContainer();
}

void Pelagicontain::shutdown(unsigned int timeout)
{
    log_debug() << "shutdown called"; // << logging::getStackTrace();
    shutdownContainer(timeout);
}

void Pelagicontain::shutdownGateways()
{
    for (auto &gateway : m_gateways) {
        if (!gateway->teardown()) {
            log_warning() << "Could not tear down gateway cleanly";
        }
    }

    m_gateways.clear();
}
<|endoftext|>


<commit_before>//***************************************************************
//
// Copyright (c) 2015 Intel Corporation.  All rights reserved.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
//***************************************************************

//***************************************************************
//
// Module: CurieTimer
//
//
// Notes:
//
//   - Arc has two timers, Timer-0 is used.  Please check the file
//     arcv2_timer0.cpp.
//
// Cautions:
//   - The module, Tone.cpp, also makes use of Arc Timer-1 which
//     is used here.
//
//***************************************************************

#include "CurieTimer.h"
#include <conf.h>

CurieTimer  CurieTimerOne;

static void timerOneIsrWrapper(void)
{
  CurieTimerOne.timerIsr();
}
static void timerOnePwmCbWrapper(void)
{
  CurieTimerOne.pwmCallBack();
}

CurieTimer::CurieTimer(const unsigned int timerNum) :
  tickCnt(0), currState(IDLE), userCB(NULL)
{
  if(timerNum == 0) {
    timerCountAddr = ARC_V2_TMR0_COUNT;
    timerControlAddr = ARC_V2_TMR0_CONTROL;
    timerLimitAddr = ARC_V2_TMR0_LIMIT;
    timerIrqNum = ARCV2_IRQ_TIMER0;
    isrFuncPtr = NULL;
    pwmCB = NULL;
  }
  else {
    timerCountAddr = ARC_V2_TMR1_COUNT;
    timerControlAddr = ARC_V2_TMR1_CONTROL;
    timerLimitAddr = ARC_V2_TMR1_LIMIT;
    timerIrqNum = ARCV2_IRQ_TIMER1;
    isrFuncPtr = &timerOneIsrWrapper;
    pwmCB = &timerOnePwmCbWrapper;
  }
}

// Method:  kill
// Description:
//   Set the timer back to power up default condition.

void CurieTimer::kill()
{
  interrupt_disable(timerIrqNum);  // Disable Timer at controller
  aux_reg_write(timerControlAddr, 0);  // Disable Timer itself
  aux_reg_write(timerLimitAddr, 0);
  aux_reg_write(timerCountAddr, 0);

  tickCnt = 0;
  userCB = NULL;
  currState = IDLE;
}

void CurieTimer::attachInterrupt(void (*userCallBack)())
{
  unsigned int reg;

  // Disable timer interrupt first.
  reg = aux_reg_read(timerControlAddr) & ~ARC_TIMER_EN_INTR_BIT_FLAG;
  aux_reg_write(timerControlAddr, reg);

  // Record the user call back routine.
  userCB = userCallBack;

  // Let timer interrupt go again.
  reg |= ARC_TIMER_EN_INTR_BIT_FLAG;
  aux_reg_write(timerControlAddr, reg);
}

unsigned int CurieTimer::rdRstTickCount(void)
{
  unsigned int tmp;

  tmp = tickCnt;
  tickCnt = 0;
  return tmp;
}

void CurieTimer::pause(void)
{
  if(currState != RUNNING)
    return;

  pauseCntrl = aux_reg_read(timerControlAddr);
  pauseCount = aux_reg_read(timerCountAddr);

  interrupt_disable(timerIrqNum);  // Disable Timer at controller
  aux_reg_write(timerControlAddr, 0);  // Disable Timer itself

  currState = PAUSED;
}

void CurieTimer::resume(void)
{
  if(currState != PAUSED)
    return;

  aux_reg_write(timerCountAddr, pauseCount);
  aux_reg_write(timerControlAddr, pauseCntrl);
  currState = RUNNING;
}

// Method: pwmStart
//   Kick off a timer as the mean to time a pwm.  Calculate the durations of the duty cycle
// and they are loaded into the timer in the pwm call back.

int CurieTimer::pwmStart(unsigned int outputPin, double dutyPercentage, unsigned int periodUsec)
{
  unsigned int pwmPeriod;

  if(periodUsec == 0)
    return -(INVALID_PERIOD);

  if((dutyPercentage < 0.0) || (dutyPercentage > 100.0))
    return -(INVALID_DUTY_CYCLE);

  pwmPin = outputPin;
  pinMode(pwmPin, OUTPUT);

  if(dutyPercentage == 0.0) {
    digitalWrite(pwmPin, LOW);
    return SUCCESS;
  }

  if(dutyPercentage == 100.0) {
    digitalWrite(pwmPin, HIGH);
    return SUCCESS;
  }

  pwmPeriod = periodUsec * HZ_USEC;

  dutyCycle = (unsigned int)(((double)pwmPeriod / 100.0) * dutyPercentage);
  nonDutyCycle = pwmPeriod - dutyCycle;

  dutyToggle = true;
  digitalWrite(pwmPin, HIGH);
  init(dutyCycle, pwmCB);

  return SUCCESS;
}

int CurieTimer::pwmStart(unsigned int outputPin, int dutyRange, unsigned int periodUsec)
{
  if((dutyRange < 0) || (dutyRange > MAX_DUTY_RANGE))
    return -(INVALID_DUTY_CYCLE);

  return pwmStart(outputPin, ((double)dutyRange * 100.0)/(double)MAX_DUTY_RANGE, periodUsec);
}

// Method:  pwmCallBack
//   Software PWM ISR.  Timer generates interrupt and calls this method in
// its ISR.  This routine is responsible to toggle the PWM signal according
// to duty cycle duration.

inline void CurieTimer::pwmCallBack(void)
{
  dutyToggle = !dutyToggle;

  digitalWrite(pwmPin, dutyToggle ? HIGH : LOW);

  aux_reg_write(timerLimitAddr, dutyToggle ? dutyCycle : nonDutyCycle);
  aux_reg_write(timerCountAddr, 0);
}

// Method:  init
//   Kick off the timer with a period, in Hz, provided.  Initialize
// timer to run in non-halt mode, enable timer interrupt.  Always install
// the generic ISR and initialize the user call back if provided.

int CurieTimer::init(const unsigned int periodHz,
  void (*userCallBack)())
{
  if((periodHz == 0) || (periodHz > MAX_PERIOD))
    return -(INVALID_PERIOD);

  interrupt_disable(timerIrqNum);  // Disable Timer at controller
  aux_reg_write(timerControlAddr, 0);  // Disable Timer itself

  if(userCallBack != NULL)
    userCB = userCallBack;
  aux_reg_write(timerLimitAddr, periodHz);  // Load Timer period

  aux_reg_write(timerCountAddr, 0);  // Reset variables
  tickCnt = 0;

  if(isrFuncPtr != NULL) {  // Enable timer running with interrupt
    interrupt_connect(timerIrqNum, isrFuncPtr);
    aux_reg_write(timerControlAddr, ARC_TIMER_EN_INTR_BIT_FLAG |
		  ARC_TIMER_NON_HALT_ONLY_BIT_FLAG);
    interrupt_enable(timerIrqNum);
  }
  else {  // Timer runs without interrupt
    aux_reg_write(timerControlAddr, ARC_TIMER_NON_HALT_ONLY_BIT_FLAG);
  }

  currState = RUNNING;
  return SUCCESS;
}

// Method:  timerIsr
//   It's the generic timer ISR.  Will call user call back here.

inline void CurieTimer::timerIsr(void)
{
  unsigned int reg;

  // Clear the interrupt pending bit.
  reg = aux_reg_read(timerControlAddr) & ~ARC_TIMER_INTR_PENDING_BIT_FLAG;
  aux_reg_write(timerControlAddr, reg);

  tickCnt++;  // Account for the interrupt

  if(userCB != NULL)  // Call user ISR if available
    userCB();
}

<commit_msg>Jira-501: CurieTimer.resume() did not re-enable interrupt at the controller.<commit_after>//***************************************************************
//
// Copyright (c) 2015 Intel Corporation.  All rights reserved.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
//***************************************************************

//***************************************************************
//
// Module: CurieTimer
//
//
// Notes:
//
//   - Arc has two timers, Timer-0 is used.  Please check the file
//     arcv2_timer0.cpp.
//
// Cautions:
//   - The module, Tone.cpp, also makes use of Arc Timer-1 which
//     is used here.
//
//***************************************************************

#include "CurieTimer.h"
#include <conf.h>

CurieTimer  CurieTimerOne;

static void timerOneIsrWrapper(void)
{
  CurieTimerOne.timerIsr();
}
static void timerOnePwmCbWrapper(void)
{
  CurieTimerOne.pwmCallBack();
}

CurieTimer::CurieTimer(const unsigned int timerNum) :
  tickCnt(0), currState(IDLE), userCB(NULL)
{
  if(timerNum == 0) {
    timerCountAddr = ARC_V2_TMR0_COUNT;
    timerControlAddr = ARC_V2_TMR0_CONTROL;
    timerLimitAddr = ARC_V2_TMR0_LIMIT;
    timerIrqNum = ARCV2_IRQ_TIMER0;
    isrFuncPtr = NULL;
    pwmCB = NULL;
  }
  else {
    timerCountAddr = ARC_V2_TMR1_COUNT;
    timerControlAddr = ARC_V2_TMR1_CONTROL;
    timerLimitAddr = ARC_V2_TMR1_LIMIT;
    timerIrqNum = ARCV2_IRQ_TIMER1;
    isrFuncPtr = &timerOneIsrWrapper;
    pwmCB = &timerOnePwmCbWrapper;
  }
}

// Method:  kill
// Description:
//   Set the timer back to power up default condition.

void CurieTimer::kill()
{
  interrupt_disable(timerIrqNum);  // Disable Timer at controller
  aux_reg_write(timerControlAddr, 0);  // Disable Timer itself
  aux_reg_write(timerLimitAddr, 0);
  aux_reg_write(timerCountAddr, 0);

  tickCnt = 0;
  userCB = NULL;
  currState = IDLE;
}

void CurieTimer::attachInterrupt(void (*userCallBack)())
{
  unsigned int reg;

  // Disable timer interrupt first.
  reg = aux_reg_read(timerControlAddr) & ~ARC_TIMER_EN_INTR_BIT_FLAG;
  aux_reg_write(timerControlAddr, reg);

  // Record the user call back routine.
  userCB = userCallBack;

  // Let timer interrupt go again.
  reg |= ARC_TIMER_EN_INTR_BIT_FLAG;
  aux_reg_write(timerControlAddr, reg);
}

unsigned int CurieTimer::rdRstTickCount(void)
{
  unsigned int tmp;

  tmp = tickCnt;
  tickCnt = 0;
  return tmp;
}

void CurieTimer::pause(void)
{
  if(currState != RUNNING)
    return;

  pauseCntrl = aux_reg_read(timerControlAddr);
  pauseCount = aux_reg_read(timerCountAddr);

  interrupt_disable(timerIrqNum);  // Disable Timer at controller
  aux_reg_write(timerControlAddr, 0);  // Disable Timer itself

  currState = PAUSED;
}

void CurieTimer::resume(void)
{
  if(currState != PAUSED)
    return;

  aux_reg_write(timerCountAddr, pauseCount);
  aux_reg_write(timerControlAddr, pauseCntrl);
  currState = RUNNING;

  // Re-enable timer interrupt once timer is reloaded with previous stop values.
  interrupt_enable(timerIrqNum);
}

// Method: pwmStart
//   Kick off a timer as the mean to time a pwm.  Calculate the durations of the duty cycle
// and they are loaded into the timer in the pwm call back.

int CurieTimer::pwmStart(unsigned int outputPin, double dutyPercentage, unsigned int periodUsec)
{
  unsigned int pwmPeriod;

  if(periodUsec == 0)
    return -(INVALID_PERIOD);

  if((dutyPercentage < 0.0) || (dutyPercentage > 100.0))
    return -(INVALID_DUTY_CYCLE);

  pwmPin = outputPin;
  pinMode(pwmPin, OUTPUT);

  if(dutyPercentage == 0.0) {
    digitalWrite(pwmPin, LOW);
    return SUCCESS;
  }

  if(dutyPercentage == 100.0) {
    digitalWrite(pwmPin, HIGH);
    return SUCCESS;
  }

  pwmPeriod = periodUsec * HZ_USEC;

  dutyCycle = (unsigned int)(((double)pwmPeriod / 100.0) * dutyPercentage);
  nonDutyCycle = pwmPeriod - dutyCycle;

  dutyToggle = true;
  digitalWrite(pwmPin, HIGH);
  init(dutyCycle, pwmCB);

  return SUCCESS;
}

int CurieTimer::pwmStart(unsigned int outputPin, int dutyRange, unsigned int periodUsec)
{
  if((dutyRange < 0) || (dutyRange > MAX_DUTY_RANGE))
    return -(INVALID_DUTY_CYCLE);

  return pwmStart(outputPin, ((double)dutyRange * 100.0)/(double)MAX_DUTY_RANGE, periodUsec);
}

// Method:  pwmCallBack
//   Software PWM ISR.  Timer generates interrupt and calls this method in
// its ISR.  This routine is responsible to toggle the PWM signal according
// to duty cycle duration.

inline void CurieTimer::pwmCallBack(void)
{
  dutyToggle = !dutyToggle;

  digitalWrite(pwmPin, dutyToggle ? HIGH : LOW);

  aux_reg_write(timerLimitAddr, dutyToggle ? dutyCycle : nonDutyCycle);
  aux_reg_write(timerCountAddr, 0);
}

// Method:  init
//   Kick off the timer with a period, in Hz, provided.  Initialize
// timer to run in non-halt mode, enable timer interrupt.  Always install
// the generic ISR and initialize the user call back if provided.

int CurieTimer::init(const unsigned int periodHz,
  void (*userCallBack)())
{
  if((periodHz == 0) || (periodHz > MAX_PERIOD))
    return -(INVALID_PERIOD);

  interrupt_disable(timerIrqNum);  // Disable Timer at controller
  aux_reg_write(timerControlAddr, 0);  // Disable Timer itself

  if(userCallBack != NULL)
    userCB = userCallBack;
  aux_reg_write(timerLimitAddr, periodHz);  // Load Timer period

  aux_reg_write(timerCountAddr, 0);  // Reset variables
  tickCnt = 0;

  if(isrFuncPtr != NULL) {  // Enable timer running with interrupt
    interrupt_connect(timerIrqNum, isrFuncPtr);
    aux_reg_write(timerControlAddr, ARC_TIMER_EN_INTR_BIT_FLAG |
		  ARC_TIMER_NON_HALT_ONLY_BIT_FLAG);
    interrupt_enable(timerIrqNum);
  }
  else {  // Timer runs without interrupt
    aux_reg_write(timerControlAddr, ARC_TIMER_NON_HALT_ONLY_BIT_FLAG);
  }

  currState = RUNNING;
  return SUCCESS;
}

// Method:  timerIsr
//   It's the generic timer ISR.  Will call user call back here.

inline void CurieTimer::timerIsr(void)
{
  unsigned int reg;

  // Clear the interrupt pending bit.
  reg = aux_reg_read(timerControlAddr) & ~ARC_TIMER_INTR_PENDING_BIT_FLAG;
  aux_reg_write(timerControlAddr, reg);

  tickCnt++;  // Account for the interrupt

  if(userCB != NULL)  // Call user ISR if available
    userCB();
}

<|endoftext|>


<commit_before>#include "blockbrowser.h"
#include "ui_blockbrowser.h"
#include "main.h"
#include "walletmodel.h"
#include "base58.h"
#include "clientmodel.h"
//#include "bitcoinrpc.h"

#include "rpcclient.h"
#include "transactionrecord.h"

#include <sstream>
#include <string>
#include <boost/exception/to_string.hpp>

#include <QDir>
#include <QFile>
#include <QProcess>
#include <QTime>
#include <QTimer>
#include <QStringList>
#include <QMap>
#include <QSettings>
#include <QSlider>

double BlockBrowser::getBlockHardness(int height)
{
    const CBlockIndex* blockindex = getBlockIndex(height);

    int nShift = (blockindex->nBits >> 24) & 0xff;

    double dDiff =
        (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);

    while (nShift < 29)
    {
        dDiff *= 256.0;
        nShift++;
    }
    while (nShift > 29)
    {
        dDiff /= 256.0;
        nShift--;
    }

    return dDiff;
}

int BlockBrowser::getBlockHashrate(int height)
{
    int lookup = height;

    double timeDiff = getBlockTime(height) - getBlockTime(1);
    double timePerBlock = timeDiff / lookup;

    return (boost::int64_t)(((double)getBlockHardness(height) * pow(2.0, 32)) / timePerBlock);
}

const CBlockIndex* BlockBrowser::getBlockIndex(int height)
{
    std::string hex = getBlockHash(height);
    uint256 hash(hex);
    return mapBlockIndex[hash];
}

std::string BlockBrowser::getBlockHash(int Height)
{
    CBlockIndex* pblockindex = chainActive[Height];
    if(Height > pblockindex->nHeight) { return "73dc70a1698579360b62e724ecfeacfd938f45283162f3cf18f1b9eb3fc9fcd7"; }
    if(Height < 0) { return "73dc70a1698579360b62e724ecfeacfd938f45283162f3cf18f1b9eb3fc9fcd7"; }
    int desiredheight;
    desiredheight = Height;
    if (desiredheight < 0 || desiredheight > chainActive.Height())
        return 0;

    CBlock block;
    //pblockindex = mapBlockIndex[hashBestChain];
    while (pblockindex->nHeight > desiredheight)
        pblockindex = pblockindex->pprev;
    return pblockindex->phashBlock->GetHex();
}

int BlockBrowser::getBlockTime(int Height)
{
    std::string strHash = getBlockHash(Height);
    uint256 hash(strHash);

    if (mapBlockIndex.count(hash) == 0)
        return 0;

    CBlock block;
    CBlockIndex* pblockindex = mapBlockIndex[hash];
    return pblockindex->nTime;
}

std::string BlockBrowser::getBlockMerkle(int Height)
{
    std::string strHash = getBlockHash(Height);
    uint256 hash(strHash);

    if (mapBlockIndex.count(hash) == 0)
        return 0;

    CBlock block;
    CBlockIndex* pblockindex = mapBlockIndex[hash];
    return pblockindex->hashMerkleRoot.ToString().substr(0,10).c_str();
}

int BlockBrowser::getBlocknBits(int Height)
{
    std::string strHash = getBlockHash(Height);
    uint256 hash(strHash);

    if (mapBlockIndex.count(hash) == 0)
        return 0;

    CBlock block;
    CBlockIndex* pblockindex = mapBlockIndex[hash];
    return pblockindex->nBits;
}

int BlockBrowser::getBlockNonce(int Height)
{
    std::string strHash = getBlockHash(Height);
    uint256 hash(strHash);

    if (mapBlockIndex.count(hash) == 0)
        return 0;

    CBlock block;
    CBlockIndex* pblockindex = mapBlockIndex[hash];
    return pblockindex->nNonce;
}

std::string BlockBrowser::getBlockDebug(int Height)
{
    std::string strHash = getBlockHash(Height);
    uint256 hash(strHash);

    if (mapBlockIndex.count(hash) == 0)
        return 0;

    CBlock block;
    CBlockIndex* pblockindex = mapBlockIndex[hash];
    return pblockindex->ToString();
}

int BlockBrowser::blocksInPastHours(int hours)
{
    CBlockIndex* pindexBest = pindexBestHeader;
    int wayback = hours * 3600;
    bool check = true;
    int height = pindexBest->nHeight;
    int heightHour = pindexBest->nHeight;
    int utime = (int)time(NULL);
    int target = utime - wayback;

    while(check)
    {
        if(getBlockTime(heightHour) < target)
        {
            check = false;
            return height - heightHour;
        } else {
            heightHour = heightHour - 1;
        }
    }

    return 0;
}

double BlockBrowser::getTxTotalValue(std::string txid)
{
    uint256 hash;
    hash.SetHex(txid);

    CTransaction tx;
    uint256 hashBlock = 0;
    if (!GetTransaction(hash, tx, hashBlock,true))
        return 11;

    return convertCoins(tx.GetValueOut());

}

double BlockBrowser::convertCoins(int64_t amount)
{
    return (double)amount / ((double)COIN);
}

std::string BlockBrowser::getOutputs(std::string txid)
{
    uint256 hash;
    hash.SetHex(txid);

    CTransaction tx;
    uint256 hashBlock = 0;
    if (!GetTransaction(hash, tx, hashBlock,true))
        return "fail";

    CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
    ssTx << tx;

    std::string str = "";
    for (unsigned int i = 0; i < tx.vout.size(); i++)
    {
        const CTxOut& txout = tx.vout[i];
        CTxDestination source;
        ExtractDestination(txout.scriptPubKey, source);
        CBitcoinAddress addressSource(source);
        std::string lol7 = addressSource.ToString();
        double buffer = convertCoins(txout.nValue);
        std::string amount = boost::to_string(buffer);
        str.append(lol7);
        str.append(": ");
        str.append(amount);
        str.append(" SXC");
        str.append("\n");
    }

    return str;
}

std::string BlockBrowser::getInputs(std::string txid)
{
    uint256 hash;
    hash.SetHex(txid);

    CTransaction tx;

    uint256 hashBlock = 0;

    //does the transaction exist
    if (!GetTransaction(hash, tx, hashBlock, true))
        return "fail";

    // is it a coinbase transaction
    if(tx.IsCoinBase())
        return( "Coinbase / Mined");

    // Ok, lets get a list of inputs and their amounts
    std::string str = "";
    for (unsigned int i = 0; i < tx.vin.size(); i++)
    {
        uint256 hash;
        const CTxIn& vin = tx.vin[i];
        hash.SetHex(vin.prevout.hash.ToString());

        CTransaction wtxPrev;
        uint256 hashBlock = 0;
        if (!GetTransaction(hash, wtxPrev, hashBlock, true))
             return "fail (you probably need to enable transaction indexing)";

        CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
        ssTx << wtxPrev;

        CTxDestination source;
        ExtractDestination(wtxPrev.vout[vin.prevout.n].scriptPubKey, source);
        CBitcoinAddress addressSource(source);
        std::string lol6 = addressSource.ToString();
        const CScript target = wtxPrev.vout[vin.prevout.n].scriptPubKey;
        double buffer = convertCoins(getInputValue(wtxPrev, target));
        std::string amount = boost::to_string(buffer);
        str.append(lol6);
        str.append(": ");
        str.append(amount);
        str.append("SXC");
        str.append("\n");
    }

    return str;
}

// Send this the previous transaction and read the outs, to get the value in
// for the entry you are looking at
int64_t BlockBrowser::getInputValue(CTransaction prevTx, CScript target)
{

    double valueIn = 0;
    for (unsigned int i = 0; i < prevTx.vout.size(); i++)
    {
        const CTxOut& txout = prevTx.vout[i];
        if(txout.scriptPubKey == target)
        {
            valueIn += txout.nValue;
        }
    }
    return valueIn;
}

double BlockBrowser::getTxFees(std::string txid)
{
    uint256 hash;
    hash.SetHex(txid);

    CTransaction tx;
    uint256 hashBlock = 0;
    if (!GetTransaction(hash, tx, hashBlock, true))
        return 1;

    double valueOut = convertCoins(tx.GetValueOut());

    double valueIn = 0;
    double buffer0 = 0;
    for (unsigned int i = 0; i < tx.vin.size(); i++)
    {
        uint256 hash0;
        const CTxIn& vin = tx.vin[i];
        hash0.SetHex(vin.prevout.hash.ToString());
        CTransaction wtxPrev;
        uint256 hashBlock0 = 0;

        if (!GetTransaction(hash0, wtxPrev, hashBlock0, true)){
            buffer0 = valueIn;
        }else{
            CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
            ssTx << wtxPrev;
            const CScript target = wtxPrev.vout[vin.prevout.n].scriptPubKey;
            buffer0 = valueIn + convertCoins(getInputValue(wtxPrev, target));
        }
        valueIn = buffer0;
    }

    return valueIn - valueOut;
}

BlockBrowser::BlockBrowser(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::BlockBrowser)
{
    ui->setupUi(this);

    setFixedSize(400, 420);

    connect(ui->blockButton, SIGNAL(pressed()), this, SLOT(blockClicked()));
    connect(ui->txButton, SIGNAL(pressed()), this, SLOT(txClicked()));
}

void BlockBrowser::updateExplorer(bool block)
{
    CBlockIndex* pindexBest = pindexBestHeader;
    if(block)
    {
        ui->heightLabel->show();
        ui->heightLabel_2->show();
        ui->hashLabel->show();
        ui->hashBox->show();
        ui->merkleLabel->show();
        ui->merkleBox->show();
        ui->nonceLabel->show();
        ui->nonceBox->show();
        ui->bitsLabel->show();
        ui->bitsBox->show();
        ui->timeLabel->show();
        ui->timeBox->show();
        ui->hardLabel->show();
        ui->hardBox->show();;
        ui->pawLabel->show();
        ui->pawBox->show();
        int height = ui->heightBox->value();
        if (height > pindexBest->nHeight)
        {
            ui->heightBox->setValue(pindexBest->nHeight);
            height = pindexBest->nHeight;
        }
        int Pawrate = getBlockHashrate(height);
        double Pawrate2 = 0.000;
        Pawrate2 = ((double)Pawrate / 1000);
        std::string hash = getBlockHash(height);
        std::string merkle = getBlockMerkle(height);
        int nBits = getBlocknBits(height);
        int nNonce = getBlockNonce(height);
        int atime = getBlockTime(height);
        double hardness = getBlockHardness(height);
        QString QHeight = QString::number(height);
        QString QHash = QString::fromUtf8(hash.c_str());
        QString QMerkle = QString::fromUtf8(merkle.c_str());
        QString QBits = QString::number(nBits);
        QString QNonce = QString::number(nNonce);
        QString QTime = QString::number(atime);
        QString QHardness = QString::number(hardness, 'f', 6);
        QString QPawrate = QString::number(Pawrate2, 'f', 3);
        ui->heightLabel->setText(QHeight);
        ui->hashBox->setText(QHash);
        ui->merkleBox->setText(QMerkle);
        ui->bitsBox->setText(QBits);
        ui->nonceBox->setText(QNonce);
        ui->timeBox->setText(QTime);
        ui->hardBox->setText(QHardness);
        ui->pawBox->setText(QPawrate + " KH/s");
    }

    if(block == false) {
        ui->txID->show();
        ui->txLabel->show();
        ui->valueLabel->show();
        ui->valueBox->show();
        ui->inputLabel->show();
        ui->inputBox->show();
        ui->outputLabel->show();
        ui->outputBox->show();
        ui->feesLabel->show();
        ui->feesBox->show();
        std::string txid = ui->txBox->text().toUtf8().constData();
        double value = getTxTotalValue(txid);
        double fees = getTxFees(txid);
        std::string outputs = getOutputs(txid);
        std::string inputs = getInputs(txid);
        QString QValue = QString::number(value, 'f', 6);
        QString QID = QString::fromUtf8(txid.c_str());
        QString QOutputs = QString::fromUtf8(outputs.c_str());
        QString QInputs = QString::fromUtf8(inputs.c_str());
        QString QFees = QString::number(fees, 'f', 6);
        ui->valueBox->setText(QValue + " SXC");
        ui->txID->setText(QID);
        ui->outputBox->setText(QOutputs);
        ui->inputBox->setText(QInputs);
        ui->feesBox->setText(QFees + " SXC");
    }
}

void BlockBrowser::txClicked()
{
    updateExplorer(false);
}

void BlockBrowser::blockClicked()
{
    updateExplorer(true);
}

void BlockBrowser::setModel(WalletModel *walletModel)
{
    this->walletModel = walletModel;
}

void BlockBrowser::setClientModel(ClientModel *clientModel)
{
    this->clientModel = clientModel;
}

BlockBrowser::~BlockBrowser()
{
    delete ui;
}
<commit_msg>Fix coinbase fee misreported<commit_after>#include "blockbrowser.h"
#include "ui_blockbrowser.h"
#include "main.h"
#include "walletmodel.h"
#include "base58.h"
#include "clientmodel.h"
//#include "bitcoinrpc.h"

#include "rpcclient.h"
#include "transactionrecord.h"

#include <sstream>
#include <string>
#include <boost/exception/to_string.hpp>

#include <QDir>
#include <QFile>
#include <QProcess>
#include <QTime>
#include <QTimer>
#include <QStringList>
#include <QMap>
#include <QSettings>
#include <QSlider>

double BlockBrowser::getBlockHardness(int height)
{
    const CBlockIndex* blockindex = getBlockIndex(height);

    int nShift = (blockindex->nBits >> 24) & 0xff;

    double dDiff =
        (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);

    while (nShift < 29)
    {
        dDiff *= 256.0;
        nShift++;
    }
    while (nShift > 29)
    {
        dDiff /= 256.0;
        nShift--;
    }

    return dDiff;
}

int BlockBrowser::getBlockHashrate(int height)
{
    int lookup = height;

    double timeDiff = getBlockTime(height) - getBlockTime(1);
    double timePerBlock = timeDiff / lookup;

    return (boost::int64_t)(((double)getBlockHardness(height) * pow(2.0, 32)) / timePerBlock);
}

const CBlockIndex* BlockBrowser::getBlockIndex(int height)
{
    std::string hex = getBlockHash(height);
    uint256 hash(hex);
    return mapBlockIndex[hash];
}

std::string BlockBrowser::getBlockHash(int Height)
{
    CBlockIndex* pblockindex = chainActive[Height];
    if(Height > pblockindex->nHeight) { return "73dc70a1698579360b62e724ecfeacfd938f45283162f3cf18f1b9eb3fc9fcd7"; }
    if(Height < 0) { return "73dc70a1698579360b62e724ecfeacfd938f45283162f3cf18f1b9eb3fc9fcd7"; }
    int desiredheight;
    desiredheight = Height;
    if (desiredheight < 0 || desiredheight > chainActive.Height())
        return 0;

    CBlock block;
    //pblockindex = mapBlockIndex[hashBestChain];
    while (pblockindex->nHeight > desiredheight)
        pblockindex = pblockindex->pprev;
    return pblockindex->phashBlock->GetHex();
}

int BlockBrowser::getBlockTime(int Height)
{
    std::string strHash = getBlockHash(Height);
    uint256 hash(strHash);

    if (mapBlockIndex.count(hash) == 0)
        return 0;

    CBlock block;
    CBlockIndex* pblockindex = mapBlockIndex[hash];
    return pblockindex->nTime;
}

std::string BlockBrowser::getBlockMerkle(int Height)
{
    std::string strHash = getBlockHash(Height);
    uint256 hash(strHash);

    if (mapBlockIndex.count(hash) == 0)
        return 0;

    CBlock block;
    CBlockIndex* pblockindex = mapBlockIndex[hash];
    return pblockindex->hashMerkleRoot.ToString().substr(0,10).c_str();
}

int BlockBrowser::getBlocknBits(int Height)
{
    std::string strHash = getBlockHash(Height);
    uint256 hash(strHash);

    if (mapBlockIndex.count(hash) == 0)
        return 0;

    CBlock block;
    CBlockIndex* pblockindex = mapBlockIndex[hash];
    return pblockindex->nBits;
}

int BlockBrowser::getBlockNonce(int Height)
{
    std::string strHash = getBlockHash(Height);
    uint256 hash(strHash);

    if (mapBlockIndex.count(hash) == 0)
        return 0;

    CBlock block;
    CBlockIndex* pblockindex = mapBlockIndex[hash];
    return pblockindex->nNonce;
}

std::string BlockBrowser::getBlockDebug(int Height)
{
    std::string strHash = getBlockHash(Height);
    uint256 hash(strHash);

    if (mapBlockIndex.count(hash) == 0)
        return 0;

    CBlock block;
    CBlockIndex* pblockindex = mapBlockIndex[hash];
    return pblockindex->ToString();
}

int BlockBrowser::blocksInPastHours(int hours)
{
    CBlockIndex* pindexBest = pindexBestHeader;
    int wayback = hours * 3600;
    bool check = true;
    int height = pindexBest->nHeight;
    int heightHour = pindexBest->nHeight;
    int utime = (int)time(NULL);
    int target = utime - wayback;

    while(check)
    {
        if(getBlockTime(heightHour) < target)
        {
            check = false;
            return height - heightHour;
        } else {
            heightHour = heightHour - 1;
        }
    }

    return 0;
}

double BlockBrowser::getTxTotalValue(std::string txid)
{
    uint256 hash;
    hash.SetHex(txid);

    CTransaction tx;
    uint256 hashBlock = 0;
    if (!GetTransaction(hash, tx, hashBlock,true))
        return 11;

    return convertCoins(tx.GetValueOut());

}

double BlockBrowser::convertCoins(int64_t amount)
{
    return (double)amount / ((double)COIN);
}

std::string BlockBrowser::getOutputs(std::string txid)
{
    uint256 hash;
    hash.SetHex(txid);

    CTransaction tx;
    uint256 hashBlock = 0;
    if (!GetTransaction(hash, tx, hashBlock,true))
        return "fail";

    CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
    ssTx << tx;

    std::string str = "";
    for (unsigned int i = 0; i < tx.vout.size(); i++)
    {
        const CTxOut& txout = tx.vout[i];
        CTxDestination source;
        ExtractDestination(txout.scriptPubKey, source);
        CBitcoinAddress addressSource(source);
        std::string lol7 = addressSource.ToString();
        double buffer = convertCoins(txout.nValue);
        std::string amount = boost::to_string(buffer);
        str.append(lol7);
        str.append(": ");
        str.append(amount);
        str.append(" SXC");
        str.append("\n");
    }

    return str;
}

std::string BlockBrowser::getInputs(std::string txid)
{
    uint256 hash;
    hash.SetHex(txid);

    CTransaction tx;

    uint256 hashBlock = 0;

    //does the transaction exist
    if (!GetTransaction(hash, tx, hashBlock, true))
        return "fail";

    // is it a coinbase transaction
    if(tx.IsCoinBase())
        return( "Coinbase / Mined");

    // Ok, lets get a list of inputs and their amounts
    std::string str = "";
    for (unsigned int i = 0; i < tx.vin.size(); i++)
    {
        uint256 hash;
        const CTxIn& vin = tx.vin[i];
        hash.SetHex(vin.prevout.hash.ToString());

        CTransaction wtxPrev;
        uint256 hashBlock = 0;
        if (!GetTransaction(hash, wtxPrev, hashBlock, true))
             return "fail (you probably need to enable transaction indexing)";

        CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
        ssTx << wtxPrev;

        CTxDestination source;
        ExtractDestination(wtxPrev.vout[vin.prevout.n].scriptPubKey, source);
        CBitcoinAddress addressSource(source);
        std::string lol6 = addressSource.ToString();
        const CScript target = wtxPrev.vout[vin.prevout.n].scriptPubKey;
        double buffer = convertCoins(getInputValue(wtxPrev, target));
        std::string amount = boost::to_string(buffer);
        str.append(lol6);
        str.append(": ");
        str.append(amount);
        str.append("SXC");
        str.append("\n");
    }

    return str;
}

// Send this the previous transaction and read the outs, to get the value in
// for the entry you are looking at
int64_t BlockBrowser::getInputValue(CTransaction prevTx, CScript target)
{

    double valueIn = 0;
    for (unsigned int i = 0; i < prevTx.vout.size(); i++)
    {
        const CTxOut& txout = prevTx.vout[i];
        if(txout.scriptPubKey == target)
        {
            valueIn += txout.nValue;
        }
    }
    return valueIn;
}

double BlockBrowser::getTxFees(std::string txid)
{
    uint256 hash;
    hash.SetHex(txid);

    CTransaction tx;
    uint256 hashBlock = 0;
    if (!GetTransaction(hash, tx, hashBlock, true))
        return 1;

    if(tx.IsCoinBase()
        return 0;

    double valueOut = convertCoins(tx.GetValueOut());

    double valueIn = 0;
    double buffer0 = 0;
    for (unsigned int i = 0; i < tx.vin.size(); i++)
    {
        uint256 hash0;
        const CTxIn& vin = tx.vin[i];
        hash0.SetHex(vin.prevout.hash.ToString());
        CTransaction wtxPrev;
        uint256 hashBlock0 = 0;

        if (!GetTransaction(hash0, wtxPrev, hashBlock0, true)){
            buffer0 = valueIn;
        }else{
            CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
            ssTx << wtxPrev;
            const CScript target = wtxPrev.vout[vin.prevout.n].scriptPubKey;
            buffer0 = valueIn + convertCoins(getInputValue(wtxPrev, target));
        }
        valueIn = buffer0;
    }

    return valueIn - valueOut;
}

BlockBrowser::BlockBrowser(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::BlockBrowser)
{
    ui->setupUi(this);

    setFixedSize(400, 420);

    connect(ui->blockButton, SIGNAL(pressed()), this, SLOT(blockClicked()));
    connect(ui->txButton, SIGNAL(pressed()), this, SLOT(txClicked()));
}

void BlockBrowser::updateExplorer(bool block)
{
    CBlockIndex* pindexBest = pindexBestHeader;
    if(block)
    {
        ui->heightLabel->show();
        ui->heightLabel_2->show();
        ui->hashLabel->show();
        ui->hashBox->show();
        ui->merkleLabel->show();
        ui->merkleBox->show();
        ui->nonceLabel->show();
        ui->nonceBox->show();
        ui->bitsLabel->show();
        ui->bitsBox->show();
        ui->timeLabel->show();
        ui->timeBox->show();
        ui->hardLabel->show();
        ui->hardBox->show();;
        ui->pawLabel->show();
        ui->pawBox->show();
        int height = ui->heightBox->value();
        if (height > pindexBest->nHeight)
        {
            ui->heightBox->setValue(pindexBest->nHeight);
            height = pindexBest->nHeight;
        }
        int Pawrate = getBlockHashrate(height);
        double Pawrate2 = 0.000;
        Pawrate2 = ((double)Pawrate / 1000);
        std::string hash = getBlockHash(height);
        std::string merkle = getBlockMerkle(height);
        int nBits = getBlocknBits(height);
        int nNonce = getBlockNonce(height);
        int atime = getBlockTime(height);
        double hardness = getBlockHardness(height);
        QString QHeight = QString::number(height);
        QString QHash = QString::fromUtf8(hash.c_str());
        QString QMerkle = QString::fromUtf8(merkle.c_str());
        QString QBits = QString::number(nBits);
        QString QNonce = QString::number(nNonce);
        QString QTime = QString::number(atime);
        QString QHardness = QString::number(hardness, 'f', 6);
        QString QPawrate = QString::number(Pawrate2, 'f', 3);
        ui->heightLabel->setText(QHeight);
        ui->hashBox->setText(QHash);
        ui->merkleBox->setText(QMerkle);
        ui->bitsBox->setText(QBits);
        ui->nonceBox->setText(QNonce);
        ui->timeBox->setText(QTime);
        ui->hardBox->setText(QHardness);
        ui->pawBox->setText(QPawrate + " KH/s");
    }

    if(block == false) {
        ui->txID->show();
        ui->txLabel->show();
        ui->valueLabel->show();
        ui->valueBox->show();
        ui->inputLabel->show();
        ui->inputBox->show();
        ui->outputLabel->show();
        ui->outputBox->show();
        ui->feesLabel->show();
        ui->feesBox->show();
        std::string txid = ui->txBox->text().toUtf8().constData();
        double value = getTxTotalValue(txid);
        double fees = getTxFees(txid);
        std::string outputs = getOutputs(txid);
        std::string inputs = getInputs(txid);
        QString QValue = QString::number(value, 'f', 6);
        QString QID = QString::fromUtf8(txid.c_str());
        QString QOutputs = QString::fromUtf8(outputs.c_str());
        QString QInputs = QString::fromUtf8(inputs.c_str());
        QString QFees = QString::number(fees, 'f', 6);
        ui->valueBox->setText(QValue + " SXC");
        ui->txID->setText(QID);
        ui->outputBox->setText(QOutputs);
        ui->inputBox->setText(QInputs);
        ui->feesBox->setText(QFees + " SXC");
    }
}

void BlockBrowser::txClicked()
{
    updateExplorer(false);
}

void BlockBrowser::blockClicked()
{
    updateExplorer(true);
}

void BlockBrowser::setModel(WalletModel *walletModel)
{
    this->walletModel = walletModel;
}

void BlockBrowser::setClientModel(ClientModel *clientModel)
{
    this->clientModel = clientModel;
}

BlockBrowser::~BlockBrowser()
{
    delete ui;
}
<|endoftext|>


<commit_before>/***************************************************************************
* Copyright (c) 2016, Johan Mabille and Sylvain Corlay                     *
*                                                                          *
* Distributed under the terms of the BSD 3-Clause License.                 *
*                                                                          *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

#ifndef PY_CONTAINER_HPP
#define PY_CONTAINER_HPP

#include <cmath>
#include <functional>
#include <numeric>

#include "pybind11/complex.h"
#include "pybind11/pybind11.h"
#include "pybind11/numpy.h"

#ifndef FORCE_IMPORT_ARRAY
#define NO_IMPORT_ARRAY
#endif
#ifndef PY_ARRAY_UNIQUE_SYMBOL
#define PY_ARRAY_UNIQUE_SYMBOL xtensor_python_ARRAY_API
#endif
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION

#include "numpy/arrayobject.h"
// Required because pyconfig.hpp defines copysign to _copysign
#undef copysign

#include <cmath>
#include "xtensor/xcontainer.hpp"

#include "xtl/xsequence.hpp"

namespace xt
{

    inline void import_numpy();

    /**
     * @class pycontainer
     * @brief Base class for xtensor containers wrapping numpy arryays.
     *
     * The pycontainer class should not be instantiated directly. Instead, used should
     * use pytensor and pyarray instancs.
     *
     * @tparam D The derived type, i.e. the inheriting class for which pycontainer
     *           provides the interface.
     */
    template <class D>
    class pycontainer : public pybind11::object,
                        public xcontainer<D>
    {
    public:

        using derived_type = D;

        using base_type = xcontainer<D>;
        using inner_types = xcontainer_inner_types<D>;
        using storage_type = typename inner_types::storage_type;
        using value_type = typename storage_type::value_type;
        using reference = typename storage_type::reference;
        using const_reference = typename storage_type::const_reference;
        using pointer = typename storage_type::pointer;
        using const_pointer = typename storage_type::const_pointer;
        using size_type = typename storage_type::size_type;
        using difference_type = typename storage_type::difference_type;

        using shape_type = typename inner_types::shape_type;
        using strides_type = typename inner_types::strides_type;
        using backstrides_type = typename inner_types::backstrides_type;
        using inner_shape_type = typename inner_types::inner_shape_type;
        using inner_strides_type = typename inner_types::inner_strides_type;

        using iterable_base = xcontainer<D>;

        using iterator = typename iterable_base::iterator;
        using const_iterator = typename iterable_base::const_iterator;

        using stepper = typename iterable_base::stepper;
        using const_stepper = typename iterable_base::const_stepper;

        template <class S = shape_type>
        void resize(const S& shape);
        template <class S = shape_type>
        void resize(const S& shape, layout_type l);
        template <class S = shape_type>
        void resize(const S& shape, const strides_type& strides);

        template <class S = shape_type>
        void reshape(S&& shape, layout_type layout = base_type::static_layout);

        layout_type layout() const;

        using base_type::operator();
        using base_type::operator[];
        using base_type::begin;
        using base_type::end;

    protected:

        pycontainer();
        ~pycontainer() = default;

        pycontainer(pybind11::handle h, borrowed_t);
        pycontainer(pybind11::handle h, stolen_t);
        pycontainer(const pybind11::object& o);

        pycontainer(const pycontainer&) = default;
        pycontainer& operator=(const pycontainer&) = default;

        pycontainer(pycontainer&&) = default;
        pycontainer& operator=(pycontainer&&) = default;

        static derived_type ensure(pybind11::handle h);
        static bool check_(pybind11::handle h);
        static PyObject* raw_array_t(PyObject* ptr);

        derived_type& derived_cast();
        const derived_type& derived_cast() const;

        PyArrayObject* python_array() const;
        size_type get_buffer_size() const;
    };

    namespace detail
    {
        template <class T, class E = void>
        struct numpy_traits;

        template <class T>
        struct numpy_traits<T, std::enable_if_t<pybind11::detail::satisfies_any_of<T, std::is_arithmetic, xtl::is_complex>::value>>
        {
        private:

            // On Windows 64 bits, NPY_INT != NPY_INT32 and NPY_UINT != NPY_UINT32
            // We use the NPY_INT32 and NPY_UINT32 which are consistent with the values
            // of NPY_LONG and NPY_ULONG
            // On Linux x64, NPY_INT64 != NPY_LONGLONG and NPY_UINT64 != NPY_ULONGLONG,
            // we use the values of NPY_INT64 and NPY_UINT64 which are consistent with the
            // values of NPY_LONG and NPY_ULONG.
            constexpr static const int value_list[15] = {
                NPY_BOOL,
                NPY_BYTE, NPY_UBYTE, NPY_SHORT, NPY_USHORT,
                NPY_INT32, NPY_UINT32, NPY_INT64, NPY_UINT64,
                NPY_FLOAT, NPY_DOUBLE, NPY_LONGDOUBLE,
                NPY_CFLOAT, NPY_CDOUBLE, NPY_CLONGDOUBLE};

        public:

            using value_type = std::remove_const_t<T>;

            static constexpr int type_num = value_list[pybind11::detail::is_fmt_numeric<value_type>::index];
        };

        // On Linux x64, NPY_INT64 != NPY_LONGLONG and NPY_UINT64 != NPY_ULONGLONG
        // NPY_LONGLONG and NPY_ULONGLONG must be adjusted so the right type is
        // selected
        template <bool>
        struct numpy_enum_adjuster
        {
            static inline int pyarray_type(PyArrayObject* obj)
            {
                return PyArray_TYPE(obj);
            }
        };

        template <>
        struct numpy_enum_adjuster<true>
        {
            static inline int pyarray_type(PyArrayObject* obj)
            {
                int res = PyArray_TYPE(obj);
                if(res == NPY_LONGLONG || res == NPY_ULONGLONG)
                {
                    res -= 2;
                }
                return res;
            }
        };

        inline int pyarray_type(PyArrayObject* obj)
        {
            return numpy_enum_adjuster<NPY_LONGLONG != NPY_INT64>::pyarray_type(obj);
        }

        template <class T>
        void default_initialize_impl(T& storage, std::false_type)
        {
        }

        template <class T>
        void default_initialize_impl(T& storage, std::true_type)
        {
            using value_type = typename T::value_type;
            storage[0] = value_type{};
        }

        template <class T>
        void default_initialize(T& storage)
        {
            using value_type = typename T::value_type;
            default_initialize_impl(storage, std::is_copy_assignable<value_type>());
        }

        template <class T>
        bool check_array_type(const pybind11::handle& src, std::true_type)
        {
            int type_num = xt::detail::numpy_traits<T>::type_num;
            return xt::detail::pyarray_type(reinterpret_cast<PyArrayObject*>(src.ptr())) == type_num;
        }

        template <class T>
        bool check_array_type(const pybind11::handle& src, std::false_type)
        {
            return PyArray_EquivTypes((PyArray_Descr*) pybind11::detail::array_proxy(src.ptr())->descr,
                                      (PyArray_Descr*) pybind11::dtype::of<T>().ptr());
        }

        template <class T>
        bool check_array(const pybind11::handle& src)
        {
            using is_arithmetic_type = std::integral_constant<bool, bool(pybind11::detail::satisfies_any_of<T, std::is_arithmetic, xtl::is_complex>::value)>;
            return PyArray_Check(src.ptr()) && check_array_type<T>(src, is_arithmetic_type{});
        }
    }

    /******************************
     * pycontainer implementation *
     ******************************/

    template <class D>
    inline pycontainer<D>::pycontainer()
        : pybind11::object()
    {
    }

    template <class D>
    inline pycontainer<D>::pycontainer(pybind11::handle h, borrowed_t b)
        : pybind11::object(h, b)
    {
    }

    template <class D>
    inline pycontainer<D>::pycontainer(pybind11::handle h, stolen_t s)
        : pybind11::object(h, s)
    {
    }

    template <class D>
    inline pycontainer<D>::pycontainer(const pybind11::object& o)
        : pybind11::object(raw_array_t(o.ptr()), pybind11::object::stolen_t{})
    {
        if (!this->m_ptr)
        {
            throw pybind11::error_already_set();
        }
    }

    template <class D>
    inline auto pycontainer<D>::ensure(pybind11::handle h) -> derived_type
    {
        auto result = pybind11::reinterpret_steal<derived_type>(raw_array_t(h.ptr()));
        if (result.ptr() == nullptr)
        {
            PyErr_Clear();
        }
        return result;
    }

    template <class D>
    inline bool pycontainer<D>::check_(pybind11::handle h)
    {
        return detail::check_array<typename D::value_type>(h);
    }

    template <class D>
    inline PyObject* pycontainer<D>::raw_array_t(PyObject* ptr)
    {
        if (ptr == nullptr)
        {
            return nullptr;
        }

        auto dtype = pybind11::detail::npy_format_descriptor<value_type>::dtype();
        auto res = PyArray_FromAny(ptr, (PyArray_Descr *) dtype.release().ptr(), 0, 0,
                                   NPY_ARRAY_ENSUREARRAY | NPY_ARRAY_FORCECAST, nullptr);
        return res;
    }

    template <class D>
    inline PyArrayObject* pycontainer<D>::python_array() const
    {
        return reinterpret_cast<PyArrayObject*>(this->m_ptr);
    }

    template <class D>
    inline auto pycontainer<D>::get_buffer_size() const -> size_type
    {
        const size_type& (*min)(const size_type&, const size_type&) = std::min<size_type>;
        size_type min_stride = this->strides().empty() ? size_type(1) :
            std::max(size_type(1), std::accumulate(this->strides().cbegin(),
                                                   this->strides().cend(),
                                                   std::numeric_limits<size_type>::max(),
                                                   min));
        return min_stride * static_cast<size_type>(PyArray_SIZE(this->python_array()));
    }

    template <class D>
    inline auto pycontainer<D>::derived_cast() -> derived_type&
    {
        return *static_cast<derived_type*>(this);
    }

    template <class D>
    inline auto pycontainer<D>::derived_cast() const -> const derived_type&
    {
        return *static_cast<const derived_type*>(this);
    }

    namespace detail
    {
        template <class S>
        struct check_dims
        {
            static bool run(std::size_t)
            {
                return true;
            }
        };

        template <class T, std::size_t N>
        struct check_dims<std::array<T, N>>
        {
            static bool run(std::size_t new_dim)
            {
                if(new_dim != N)
                {
                    throw std::runtime_error("Dims not matching.");
                }
                return new_dim == N;
            }
        };
    }

    /**
     * resizes the container.
     * @param shape the new shape
     */
    template <class D>
    template <class S>
    inline void pycontainer<D>::resize(const S& shape)
    {
        if (shape.size() != this->dimension() || !std::equal(std::begin(shape), std::end(shape), std::begin(this->shape())))
        {
            resize(shape, layout_type::row_major);
        }
    }

    /**
     * resizes the container.
     * @param shape the new shape
     * @param l the new layout
     */
    template <class D>
    template <class S>
    inline void pycontainer<D>::resize(const S& shape, layout_type l)
    {
        strides_type strides = xtl::make_sequence<strides_type>(shape.size(), size_type(1));
        compute_strides(shape, l, strides);
        resize(shape, strides);
    }

    /**
     * resizes the container.
     * @param shape the new shape
     * @param strides the new strides
     */
    template <class D>
    template <class S>
    inline void pycontainer<D>::resize(const S& shape, const strides_type& strides)
    {
        detail::check_dims<shape_type>::run(shape.size());
        derived_type tmp(xtl::forward_sequence<shape_type, decltype(shape)>(shape), strides);
        *static_cast<derived_type*>(this) = std::move(tmp);
    }

    template <class D>
    template <class S>
    inline void pycontainer<D>::reshape(S&& shape, layout_type layout)
    {
        if (compute_size(shape) != this->size())
        {
            throw std::runtime_error("Cannot reshape with incorrect number of elements (" + std::to_string(this->size()) + " vs " + std::to_string(compute_size(shape)) + ")");
        }
        detail::check_dims<shape_type>::run(shape.size());
        layout = default_assignable_layout(layout);

        NPY_ORDER npy_layout;
        if (layout == layout_type::row_major)
        {
            npy_layout = NPY_CORDER;
        }
        else if (layout == layout_type::column_major)
        {
            npy_layout = NPY_FORTRANORDER;
        }
        else
        {
            throw std::runtime_error("Cannot reshape with unknown layout_type.");
        }

        using shape_ptr = typename std::decay_t<S>::pointer;
        PyArray_Dims dims = {reinterpret_cast<npy_intp*>(const_cast<shape_ptr>(shape.data())), static_cast<int>(shape.size())};
        auto new_ptr = PyArray_Newshape((PyArrayObject*) this->ptr(), &dims, npy_layout);
        auto old_ptr = this->ptr();
        this->ptr() = new_ptr;
        Py_XDECREF(old_ptr);
        this->derived_cast().init_from_python();
    }

    /**
     * Return the layout_type of the container
     * @return layout_type of the container
     */
    template <class D>
    inline layout_type pycontainer<D>::layout() const
    {
        if (PyArray_CHKFLAGS(python_array(), NPY_ARRAY_C_CONTIGUOUS))
        {
            return layout_type::row_major;
        }
        else if (PyArray_CHKFLAGS(python_array(), NPY_ARRAY_F_CONTIGUOUS))
        {
            return layout_type::column_major;
        }
        else
        {
            return layout_type::dynamic;
        }
    }

    /**
     * Import the numpy Python module.
     */
    inline void import_numpy()
    {
#ifdef FORCE_IMPORT_ARRAY
        if (_import_array() < 0)
        {
            PyErr_Print();
            PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import");
        }
#endif
    }
}

#endif
<commit_msg>Explicit long long allocator instantiation<commit_after>/***************************************************************************
* Copyright (c) 2016, Johan Mabille and Sylvain Corlay                     *
*                                                                          *
* Distributed under the terms of the BSD 3-Clause License.                 *
*                                                                          *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/

#ifndef PY_CONTAINER_HPP
#define PY_CONTAINER_HPP

#include <cmath>
#include <functional>
#include <numeric>

#include "pybind11/complex.h"
#include "pybind11/pybind11.h"
#include "pybind11/numpy.h"

#ifndef FORCE_IMPORT_ARRAY
#define NO_IMPORT_ARRAY
#endif
#ifndef PY_ARRAY_UNIQUE_SYMBOL
#define PY_ARRAY_UNIQUE_SYMBOL xtensor_python_ARRAY_API
#endif
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION

#include "numpy/arrayobject.h"
// Required because pyconfig.hpp defines copysign to _copysign
#undef copysign

#include <cmath>
#include "xtensor/xcontainer.hpp"

#include "xtl/xsequence.hpp"

namespace xt
{

    inline void import_numpy();

    /**
     * @class pycontainer
     * @brief Base class for xtensor containers wrapping numpy arryays.
     *
     * The pycontainer class should not be instantiated directly. Instead, used should
     * use pytensor and pyarray instancs.
     *
     * @tparam D The derived type, i.e. the inheriting class for which pycontainer
     *           provides the interface.
     */
    template <class D>
    class pycontainer : public pybind11::object,
                        public xcontainer<D>
    {
    public:

        using derived_type = D;

        using base_type = xcontainer<D>;
        using inner_types = xcontainer_inner_types<D>;
        using storage_type = typename inner_types::storage_type;
        using value_type = typename storage_type::value_type;
        using reference = typename storage_type::reference;
        using const_reference = typename storage_type::const_reference;
        using pointer = typename storage_type::pointer;
        using const_pointer = typename storage_type::const_pointer;
        using size_type = typename storage_type::size_type;
        using difference_type = typename storage_type::difference_type;

        using shape_type = typename inner_types::shape_type;
        using strides_type = typename inner_types::strides_type;
        using backstrides_type = typename inner_types::backstrides_type;
        using inner_shape_type = typename inner_types::inner_shape_type;
        using inner_strides_type = typename inner_types::inner_strides_type;

        using iterable_base = xcontainer<D>;

        using iterator = typename iterable_base::iterator;
        using const_iterator = typename iterable_base::const_iterator;

        using stepper = typename iterable_base::stepper;
        using const_stepper = typename iterable_base::const_stepper;

        template <class S = shape_type>
        void resize(const S& shape);
        template <class S = shape_type>
        void resize(const S& shape, layout_type l);
        template <class S = shape_type>
        void resize(const S& shape, const strides_type& strides);

        template <class S = shape_type>
        void reshape(S&& shape, layout_type layout = base_type::static_layout);

        layout_type layout() const;

        using base_type::operator();
        using base_type::operator[];
        using base_type::begin;
        using base_type::end;

    protected:

        pycontainer();
        ~pycontainer() = default;

        pycontainer(pybind11::handle h, borrowed_t);
        pycontainer(pybind11::handle h, stolen_t);
        pycontainer(const pybind11::object& o);

        pycontainer(const pycontainer&) = default;
        pycontainer& operator=(const pycontainer&) = default;

        pycontainer(pycontainer&&) = default;
        pycontainer& operator=(pycontainer&&) = default;

        static derived_type ensure(pybind11::handle h);
        static bool check_(pybind11::handle h);
        static PyObject* raw_array_t(PyObject* ptr);

        derived_type& derived_cast();
        const derived_type& derived_cast() const;

        PyArrayObject* python_array() const;
        size_type get_buffer_size() const;
    };

    namespace detail
    {
        template <class T, class E = void>
        struct numpy_traits;

        template <class T>
        struct numpy_traits<T, std::enable_if_t<pybind11::detail::satisfies_any_of<T, std::is_arithmetic, xtl::is_complex>::value>>
        {
        private:

            // On Windows 64 bits, NPY_INT != NPY_INT32 and NPY_UINT != NPY_UINT32
            // We use the NPY_INT32 and NPY_UINT32 which are consistent with the values
            // of NPY_LONG and NPY_ULONG
            // On Linux x64, NPY_INT64 != NPY_LONGLONG and NPY_UINT64 != NPY_ULONGLONG,
            // we use the values of NPY_INT64 and NPY_UINT64 which are consistent with the
            // values of NPY_LONG and NPY_ULONG.
            constexpr static const int value_list[15] = {
                NPY_BOOL,
                NPY_BYTE, NPY_UBYTE, NPY_SHORT, NPY_USHORT,
                NPY_INT32, NPY_UINT32, NPY_INT64, NPY_UINT64,
                NPY_FLOAT, NPY_DOUBLE, NPY_LONGDOUBLE,
                NPY_CFLOAT, NPY_CDOUBLE, NPY_CLONGDOUBLE};

        public:

            using value_type = std::remove_const_t<T>;

            static constexpr int type_num = value_list[pybind11::detail::is_fmt_numeric<value_type>::index];
        };

        // On Linux x64, NPY_INT64 != NPY_LONGLONG and NPY_UINT64 != NPY_ULONGLONG
        // NPY_LONGLONG and NPY_ULONGLONG must be adjusted so the right type is
        // selected
        template <bool>
        struct numpy_enum_adjuster
        {
            static inline int pyarray_type(PyArrayObject* obj)
            {
                return PyArray_TYPE(obj);
            }
        };

        template <>
        struct numpy_enum_adjuster<true>
        {
            static inline int pyarray_type(PyArrayObject* obj)
            {
                int res = PyArray_TYPE(obj);
                if(res == NPY_LONGLONG || res == NPY_ULONGLONG)
                {
                    res -= 2;
                }
                return res;
            }
        };

        inline int pyarray_type(PyArrayObject* obj)
        {
            return numpy_enum_adjuster<NPY_LONGLONG != NPY_INT64>::pyarray_type(obj);
        }

        template <class T>
        void default_initialize_impl(T& storage, std::false_type)
        {
        }

        template <class T>
        void default_initialize_impl(T& storage, std::true_type)
        {
            using value_type = typename T::value_type;
            storage[0] = value_type{};
        }

        template <class T>
        void default_initialize(T& storage)
        {
            using value_type = typename T::value_type;
            default_initialize_impl(storage, std::is_copy_assignable<value_type>());
        }

        template <class T>
        bool check_array_type(const pybind11::handle& src, std::true_type)
        {
            int type_num = xt::detail::numpy_traits<T>::type_num;
            return xt::detail::pyarray_type(reinterpret_cast<PyArrayObject*>(src.ptr())) == type_num;
        }

        template <class T>
        bool check_array_type(const pybind11::handle& src, std::false_type)
        {
            return PyArray_EquivTypes((PyArray_Descr*) pybind11::detail::array_proxy(src.ptr())->descr,
                                      (PyArray_Descr*) pybind11::dtype::of<T>().ptr());
        }

        template <class T>
        bool check_array(const pybind11::handle& src)
        {
            using is_arithmetic_type = std::integral_constant<bool, bool(pybind11::detail::satisfies_any_of<T, std::is_arithmetic, xtl::is_complex>::value)>;
            return PyArray_Check(src.ptr()) && check_array_type<T>(src, is_arithmetic_type{});
        }
    }

    /******************************
     * pycontainer implementation *
     ******************************/

    template <class D>
    inline pycontainer<D>::pycontainer()
        : pybind11::object()
    {
    }

    template <class D>
    inline pycontainer<D>::pycontainer(pybind11::handle h, borrowed_t b)
        : pybind11::object(h, b)
    {
    }

    template <class D>
    inline pycontainer<D>::pycontainer(pybind11::handle h, stolen_t s)
        : pybind11::object(h, s)
    {
    }

    template <class D>
    inline pycontainer<D>::pycontainer(const pybind11::object& o)
        : pybind11::object(raw_array_t(o.ptr()), pybind11::object::stolen_t{})
    {
        if (!this->m_ptr)
        {
            throw pybind11::error_already_set();
        }
    }

    template <class D>
    inline auto pycontainer<D>::ensure(pybind11::handle h) -> derived_type
    {
        auto result = pybind11::reinterpret_steal<derived_type>(raw_array_t(h.ptr()));
        if (result.ptr() == nullptr)
        {
            PyErr_Clear();
        }
        return result;
    }

    template <class D>
    inline bool pycontainer<D>::check_(pybind11::handle h)
    {
        return detail::check_array<typename D::value_type>(h);
    }

    template <class D>
    inline PyObject* pycontainer<D>::raw_array_t(PyObject* ptr)
    {
        if (ptr == nullptr)
        {
            return nullptr;
        }

        auto dtype = pybind11::detail::npy_format_descriptor<value_type>::dtype();
        auto res = PyArray_FromAny(ptr, (PyArray_Descr *) dtype.release().ptr(), 0, 0,
                                   NPY_ARRAY_ENSUREARRAY | NPY_ARRAY_FORCECAST, nullptr);
        return res;
    }

    template <class D>
    inline PyArrayObject* pycontainer<D>::python_array() const
    {
        return reinterpret_cast<PyArrayObject*>(this->m_ptr);
    }

    template <class D>
    inline auto pycontainer<D>::get_buffer_size() const -> size_type
    {
        const size_type& (*min)(const size_type&, const size_type&) = std::min<size_type>;
        size_type min_stride = this->strides().empty() ? size_type(1) :
            std::max(size_type(1), std::accumulate(this->strides().cbegin(),
                                                   this->strides().cend(),
                                                   std::numeric_limits<size_type>::max(),
                                                   min));
        return min_stride * static_cast<size_type>(PyArray_SIZE(this->python_array()));
    }

    template <class D>
    inline auto pycontainer<D>::derived_cast() -> derived_type&
    {
        return *static_cast<derived_type*>(this);
    }

    template <class D>
    inline auto pycontainer<D>::derived_cast() const -> const derived_type&
    {
        return *static_cast<const derived_type*>(this);
    }

    namespace detail
    {
        template <class S>
        struct check_dims
        {
            static bool run(std::size_t)
            {
                return true;
            }
        };

        template <class T, std::size_t N>
        struct check_dims<std::array<T, N>>
        {
            static bool run(std::size_t new_dim)
            {
                if(new_dim != N)
                {
                    throw std::runtime_error("Dims not matching.");
                }
                return new_dim == N;
            }
        };
    }

    /**
     * resizes the container.
     * @param shape the new shape
     */
    template <class D>
    template <class S>
    inline void pycontainer<D>::resize(const S& shape)
    {
        if (shape.size() != this->dimension() || !std::equal(std::begin(shape), std::end(shape), std::begin(this->shape())))
        {
            resize(shape, layout_type::row_major);
        }
    }

    /**
     * resizes the container.
     * @param shape the new shape
     * @param l the new layout
     */
    template <class D>
    template <class S>
    inline void pycontainer<D>::resize(const S& shape, layout_type l)
    {
        strides_type strides = xtl::make_sequence<strides_type>(shape.size(), size_type(1));
        compute_strides(shape, l, strides);
        resize(shape, strides);
    }

    /**
     * resizes the container.
     * @param shape the new shape
     * @param strides the new strides
     */
    template <class D>
    template <class S>
    inline void pycontainer<D>::resize(const S& shape, const strides_type& strides)
    {
        detail::check_dims<shape_type>::run(shape.size());
        derived_type tmp(xtl::forward_sequence<shape_type, decltype(shape)>(shape), strides);
        *static_cast<derived_type*>(this) = std::move(tmp);
    }

    template <class D>
    template <class S>
    inline void pycontainer<D>::reshape(S&& shape, layout_type layout)
    {
        if (compute_size(shape) != this->size())
        {
            throw std::runtime_error("Cannot reshape with incorrect number of elements (" + std::to_string(this->size()) + " vs " + std::to_string(compute_size(shape)) + ")");
        }
        detail::check_dims<shape_type>::run(shape.size());
        layout = default_assignable_layout(layout);

        NPY_ORDER npy_layout;
        if (layout == layout_type::row_major)
        {
            npy_layout = NPY_CORDER;
        }
        else if (layout == layout_type::column_major)
        {
            npy_layout = NPY_FORTRANORDER;
        }
        else
        {
            throw std::runtime_error("Cannot reshape with unknown layout_type.");
        }

        using shape_ptr = typename std::decay_t<S>::pointer;
        PyArray_Dims dims = {reinterpret_cast<npy_intp*>(const_cast<shape_ptr>(shape.data())), static_cast<int>(shape.size())};
        auto new_ptr = PyArray_Newshape((PyArrayObject*) this->ptr(), &dims, npy_layout);
        auto old_ptr = this->ptr();
        this->ptr() = new_ptr;
        Py_XDECREF(old_ptr);
        this->derived_cast().init_from_python();
    }

    /**
     * Return the layout_type of the container
     * @return layout_type of the container
     */
    template <class D>
    inline layout_type pycontainer<D>::layout() const
    {
        if (PyArray_CHKFLAGS(python_array(), NPY_ARRAY_C_CONTIGUOUS))
        {
            return layout_type::row_major;
        }
        else if (PyArray_CHKFLAGS(python_array(), NPY_ARRAY_F_CONTIGUOUS))
        {
            return layout_type::column_major;
        }
        else
        {
            return layout_type::dynamic;
        }
    }

    /**
     * Import the numpy Python module.
     */
    inline void import_numpy()
    {
#ifdef FORCE_IMPORT_ARRAY
        if (_import_array() < 0)
        {
            PyErr_Print();
            PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import");
        }
#endif
    }

#if defined(__GNUC__) && !defined(__clang__)
    namespace workaround
    {
        // Fixes "undefined symbol" issues
        inline void long_long_allocator()
        {
            std::allocator<long long> a;
            std::allocator<unsigned long long> b;
        }
    }
#endif
}

#endif
<|endoftext|>