<commit_before>//===-- AsmPrinter.cpp - Common AsmPrinter code ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the AsmPrinter class.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/Constants.h"
#include "llvm/Instruction.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;

bool AsmPrinter::doInitialization(Module &M) {
  Mang = new Mangler(M, GlobalPrefix);
  return false;
}

bool AsmPrinter::doFinalization(Module &M) {
  delete Mang; Mang = 0;
  return false;
}

void AsmPrinter::setupMachineFunction(MachineFunction &MF) {
  // What's my mangled name?
  CurrentFnName = Mang->getValueName((Value*)MF.getFunction());

}

// Print out the specified constant, without a storage class.  Only the
// constants valid in constant expressions can occur here.
void AsmPrinter::emitConstantValueOnly(const Constant *CV) {
  if (CV->isNullValue())
    O << "0";
  else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) {
    assert(CB == ConstantBool::True);
    O << "1";
  } else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV))
    if (((CI->getValue() << 32) >> 32) == CI->getValue())
      O << CI->getValue();
    else
      O << (unsigned long long)CI->getValue();
  else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV))
    O << CI->getValue();
  else if (isa<GlobalValue>((Value*)CV))
    // This is a constant address for a global variable or function.  Use the
    // name of the variable or function as the address value.
    O << Mang->getValueName(CV);
  else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
    const TargetData &TD = TM.getTargetData();
    switch(CE->getOpcode()) {
    case Instruction::GetElementPtr: {
      // generate a symbolic expression for the byte address
      const Constant *ptrVal = CE->getOperand(0);
      std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
      if (unsigned Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec)) {
        O << "(";
        emitConstantValueOnly(ptrVal);
        O << ") + " << Offset;
      } else {
        emitConstantValueOnly(ptrVal);
      }
      break;
    }
    case Instruction::Cast: {
      // Support only non-converting or widening casts for now, that is, ones
      // that do not involve a change in value.  This assertion is really gross,
      // and may not even be a complete check.
      Constant *Op = CE->getOperand(0);
      const Type *OpTy = Op->getType(), *Ty = CE->getType();

      // Remember, kids, pointers can be losslessly converted back and forth
      // into 32-bit or wider integers, regardless of signedness. :-P
      assert(((isa<PointerType>(OpTy)
               && (Ty == Type::LongTy || Ty == Type::ULongTy
                   || Ty == Type::IntTy || Ty == Type::UIntTy))
              || (isa<PointerType>(Ty)
                  && (OpTy == Type::LongTy || OpTy == Type::ULongTy
                      || OpTy == Type::IntTy || OpTy == Type::UIntTy))
              || (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy))
                   && OpTy->isLosslesslyConvertibleTo(Ty))))
             && "FIXME: Don't yet support this kind of constant cast expr");
      O << "(";
      emitConstantValueOnly(Op);
      O << ")";
      break;
    }
    case Instruction::Add:
      O << "(";
      emitConstantValueOnly(CE->getOperand(0));
      O << ") + (";
      emitConstantValueOnly(CE->getOperand(1));
      O << ")";
      break;
    default:
      assert(0 && "Unsupported operator!");
    }
  } else {
    assert(0 && "Unknown constant value!");
  }
}

/// toOctal - Convert the low order bits of X into an octal digit.
///
static inline char toOctal(int X) {
  return (X&7)+'0';
}

/// getAsCString - Return the specified array as a C compatible string, only if
/// the predicate isString is true.
///
static void printAsCString(std::ostream &O, const ConstantArray *CVA) {
  assert(CVA->isString() && "Array is not string compatible!");

  O << "\"";
  for (unsigned i = 0; i != CVA->getNumOperands(); ++i) {
    unsigned char C = cast<ConstantInt>(CVA->getOperand(i))->getRawValue();

    if (C == '"') {
      O << "\\\"";
    } else if (C == '\\') {
      O << "\\\\";
    } else if (isprint(C)) {
      O << C;
    } else {
      switch(C) {
      case '\b': O << "\\b"; break;
      case '\f': O << "\\f"; break;
      case '\n': O << "\\n"; break;
      case '\r': O << "\\r"; break;
      case '\t': O << "\\t"; break;
      default:
        O << '\\';
        O << toOctal(C >> 6);
        O << toOctal(C >> 3);
        O << toOctal(C >> 0);
        break;
      }
    }
  }
  O << "\"";
}

/// emitGlobalConstant - Print a general LLVM constant to the .s file.
///
void AsmPrinter::emitGlobalConstant(const Constant *CV) {
  const TargetData &TD = TM.getTargetData();

  if (CV->isNullValue()) {
    O << ZeroDirective << TD.getTypeSize(CV->getType()) << "\n";
    return;
  } else if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
    if (CVA->isString()) {
      O << AsciiDirective;
      printAsCString(O, CVA);
      O << "\n";
    } else { // Not a string.  Print the values in successive locations
      for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i)
        emitGlobalConstant(CVA->getOperand(i));
    }
    return;
  } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
    // Print the fields in successive locations. Pad to align if needed!
    const StructLayout *cvsLayout = TD.getStructLayout(CVS->getType());
    unsigned sizeSoFar = 0;
    for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) {
      const Constant* field = CVS->getOperand(i);

      // Check if padding is needed and insert one or more 0s.
      unsigned fieldSize = TD.getTypeSize(field->getType());
      unsigned padSize = ((i == e-1? cvsLayout->StructSize
                           : cvsLayout->MemberOffsets[i+1])
                          - cvsLayout->MemberOffsets[i]) - fieldSize;
      sizeSoFar += fieldSize + padSize;

      // Now print the actual field value
      emitGlobalConstant(field);

      // Insert the field padding unless it's zero bytes...
      if (padSize)
        O << ZeroDirective << padSize << "\n";
    }
    assert(sizeSoFar == cvsLayout->StructSize &&
           "Layout of constant struct may be incorrect!");
    return;
  } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
    // FP Constants are printed as integer constants to avoid losing
    // precision...
    double Val = CFP->getValue();
    if (CFP->getType() == Type::DoubleTy) {
      union DU {                            // Abide by C TBAA rules
        double FVal;
        uint64_t UVal;
      } U;
      U.FVal = Val;

      if (TD.isBigEndian()) {
        O << Data32bitsDirective << unsigned(U.UVal >> 32)
          << "\t; double most significant word " << Val << "\n";
        O << Data32bitsDirective << unsigned(U.UVal)
          << "\t; double least significant word " << Val << "\n";
      } else {
        O << Data32bitsDirective << unsigned(U.UVal)
          << "\t; double least significant word " << Val << "\n";
        O << Data32bitsDirective << unsigned(U.UVal >> 32)
          << "\t; double most significant word " << Val << "\n";
      }
      return;
    } else {
      union FU {                            // Abide by C TBAA rules
        float FVal;
        int32_t UVal;
      } U;
      U.FVal = Val;

      O << Data32bitsDirective << U.UVal << "\t; float " << Val << "\n";
      return;
    }
  } else if (CV->getType() == Type::ULongTy || CV->getType() == Type::LongTy) {
    if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
      uint64_t Val = CI->getRawValue();

      if (TD.isBigEndian()) {
        O << Data32bitsDirective << unsigned(Val >> 32)
          << "\t; Double-word most significant word " << Val << "\n";
        O << Data32bitsDirective << unsigned(Val)
          << "\t; Double-word least significant word " << Val << "\n";
      } else {
        O << Data32bitsDirective << unsigned(Val)
          << "\t; Double-word least significant word " << Val << "\n";
        O << Data32bitsDirective << unsigned(Val >> 32)
          << "\t; Double-word most significant word " << Val << "\n";
      }
      return;
    }
  }

  const Type *type = CV->getType();
  O << "\t";
  switch (type->getTypeID()) {
  case Type::UByteTyID: case Type::SByteTyID:
    O << Data8bitsDirective;
    break;
  case Type::UShortTyID: case Type::ShortTyID:
    O << Data16bitsDirective;
    break;
  case Type::BoolTyID:
  case Type::PointerTyID:
  case Type::UIntTyID: case Type::IntTyID:
    O << Data32bitsDirective;
    break;
  case Type::ULongTyID: case Type::LongTyID:
    assert (0 && "Should have already output double-word constant.");
  case Type::FloatTyID: case Type::DoubleTyID:
    assert (0 && "Should have already output floating point constant.");
  default:
    assert (0 && "Can't handle printing this type of thing");
    break;
  }
  emitConstantValueOnly(CV);
  O << "\n";
}
<commit_msg>Add support for targets that have .quad, drop extra tab inserted<commit_after>//===-- AsmPrinter.cpp - Common AsmPrinter code ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the AsmPrinter class.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/Constants.h"
#include "llvm/Instruction.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;

bool AsmPrinter::doInitialization(Module &M) {
  Mang = new Mangler(M, GlobalPrefix);
  return false;
}

bool AsmPrinter::doFinalization(Module &M) {
  delete Mang; Mang = 0;
  return false;
}

void AsmPrinter::setupMachineFunction(MachineFunction &MF) {
  // What's my mangled name?
  CurrentFnName = Mang->getValueName((Value*)MF.getFunction());
}

// Print out the specified constant, without a storage class.  Only the
// constants valid in constant expressions can occur here.
void AsmPrinter::emitConstantValueOnly(const Constant *CV) {
  if (CV->isNullValue())
    O << "0";
  else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) {
    assert(CB == ConstantBool::True);
    O << "1";
  } else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV))
    if (((CI->getValue() << 32) >> 32) == CI->getValue())
      O << CI->getValue();
    else
      O << (unsigned long long)CI->getValue();
  else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV))
    O << CI->getValue();
  else if (isa<GlobalValue>((Value*)CV))
    // This is a constant address for a global variable or function.  Use the
    // name of the variable or function as the address value.
    O << Mang->getValueName(CV);
  else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
    const TargetData &TD = TM.getTargetData();
    switch(CE->getOpcode()) {
    case Instruction::GetElementPtr: {
      // generate a symbolic expression for the byte address
      const Constant *ptrVal = CE->getOperand(0);
      std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
      if (unsigned Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec)) {
        O << "(";
        emitConstantValueOnly(ptrVal);
        O << ") + " << Offset;
      } else {
        emitConstantValueOnly(ptrVal);
      }
      break;
    }
    case Instruction::Cast: {
      // Support only non-converting or widening casts for now, that is, ones
      // that do not involve a change in value.  This assertion is really gross,
      // and may not even be a complete check.
      Constant *Op = CE->getOperand(0);
      const Type *OpTy = Op->getType(), *Ty = CE->getType();

      // Remember, kids, pointers can be losslessly converted back and forth
      // into 32-bit or wider integers, regardless of signedness. :-P
      assert(((isa<PointerType>(OpTy)
               && (Ty == Type::LongTy || Ty == Type::ULongTy
                   || Ty == Type::IntTy || Ty == Type::UIntTy))
              || (isa<PointerType>(Ty)
                  && (OpTy == Type::LongTy || OpTy == Type::ULongTy
                      || OpTy == Type::IntTy || OpTy == Type::UIntTy))
              || (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy))
                   && OpTy->isLosslesslyConvertibleTo(Ty))))
             && "FIXME: Don't yet support this kind of constant cast expr");
      O << "(";
      emitConstantValueOnly(Op);
      O << ")";
      break;
    }
    case Instruction::Add:
      O << "(";
      emitConstantValueOnly(CE->getOperand(0));
      O << ") + (";
      emitConstantValueOnly(CE->getOperand(1));
      O << ")";
      break;
    default:
      assert(0 && "Unsupported operator!");
    }
  } else {
    assert(0 && "Unknown constant value!");
  }
}

/// toOctal - Convert the low order bits of X into an octal digit.
///
static inline char toOctal(int X) {
  return (X&7)+'0';
}

/// getAsCString - Return the specified array as a C compatible string, only if
/// the predicate isString is true.
///
static void printAsCString(std::ostream &O, const ConstantArray *CVA) {
  assert(CVA->isString() && "Array is not string compatible!");

  O << "\"";
  for (unsigned i = 0; i != CVA->getNumOperands(); ++i) {
    unsigned char C = cast<ConstantInt>(CVA->getOperand(i))->getRawValue();

    if (C == '"') {
      O << "\\\"";
    } else if (C == '\\') {
      O << "\\\\";
    } else if (isprint(C)) {
      O << C;
    } else {
      switch(C) {
      case '\b': O << "\\b"; break;
      case '\f': O << "\\f"; break;
      case '\n': O << "\\n"; break;
      case '\r': O << "\\r"; break;
      case '\t': O << "\\t"; break;
      default:
        O << '\\';
        O << toOctal(C >> 6);
        O << toOctal(C >> 3);
        O << toOctal(C >> 0);
        break;
      }
    }
  }
  O << "\"";
}

/// emitGlobalConstant - Print a general LLVM constant to the .s file.
///
void AsmPrinter::emitGlobalConstant(const Constant *CV) {
  const TargetData &TD = TM.getTargetData();

  if (CV->isNullValue()) {
    O << ZeroDirective << TD.getTypeSize(CV->getType()) << "\n";
    return;
  } else if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
    if (CVA->isString()) {
      O << AsciiDirective;
      printAsCString(O, CVA);
      O << "\n";
    } else { // Not a string.  Print the values in successive locations
      for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i)
        emitGlobalConstant(CVA->getOperand(i));
    }
    return;
  } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
    // Print the fields in successive locations. Pad to align if needed!
    const StructLayout *cvsLayout = TD.getStructLayout(CVS->getType());
    unsigned sizeSoFar = 0;
    for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) {
      const Constant* field = CVS->getOperand(i);

      // Check if padding is needed and insert one or more 0s.
      unsigned fieldSize = TD.getTypeSize(field->getType());
      unsigned padSize = ((i == e-1? cvsLayout->StructSize
                           : cvsLayout->MemberOffsets[i+1])
                          - cvsLayout->MemberOffsets[i]) - fieldSize;
      sizeSoFar += fieldSize + padSize;

      // Now print the actual field value
      emitGlobalConstant(field);

      // Insert the field padding unless it's zero bytes...
      if (padSize)
        O << ZeroDirective << padSize << "\n";
    }
    assert(sizeSoFar == cvsLayout->StructSize &&
           "Layout of constant struct may be incorrect!");
    return;
  } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
    // FP Constants are printed as integer constants to avoid losing
    // precision...
    double Val = CFP->getValue();
    if (CFP->getType() == Type::DoubleTy) {
      union DU {                            // Abide by C TBAA rules
        double FVal;
        uint64_t UVal;
      } U;
      U.FVal = Val;

      if (Data64bitsDirective)
        O << Data64bitsDirective << U.UVal << "\n";
      else if (TD.isBigEndian()) {
        O << Data32bitsDirective << unsigned(U.UVal >> 32)
          << "\t; double most significant word " << Val << "\n";
        O << Data32bitsDirective << unsigned(U.UVal)
          << "\t; double least significant word " << Val << "\n";
      } else {
        O << Data32bitsDirective << unsigned(U.UVal)
          << "\t; double least significant word " << Val << "\n";
        O << Data32bitsDirective << unsigned(U.UVal >> 32)
          << "\t; double most significant word " << Val << "\n";
      }
      return;
    } else {
      union FU {                            // Abide by C TBAA rules
        float FVal;
        int32_t UVal;
      } U;
      U.FVal = Val;

      O << Data32bitsDirective << U.UVal << "\t; float " << Val << "\n";
      return;
    }
  } else if (CV->getType() == Type::ULongTy || CV->getType() == Type::LongTy) {
    if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
      uint64_t Val = CI->getRawValue();

      if (Data64bitsDirective)
        O << Data64bitsDirective << Val << "\n";
      else if (TD.isBigEndian()) {
        O << Data32bitsDirective << unsigned(Val >> 32)
          << "\t; Double-word most significant word " << Val << "\n";
        O << Data32bitsDirective << unsigned(Val)
          << "\t; Double-word least significant word " << Val << "\n";
      } else {
        O << Data32bitsDirective << unsigned(Val)
          << "\t; Double-word least significant word " << Val << "\n";
        O << Data32bitsDirective << unsigned(Val >> 32)
          << "\t; Double-word most significant word " << Val << "\n";
      }
      return;
    }
  }

  const Type *type = CV->getType();
  switch (type->getTypeID()) {
  case Type::UByteTyID: case Type::SByteTyID:
    O << Data8bitsDirective;
    break;
  case Type::UShortTyID: case Type::ShortTyID:
    O << Data16bitsDirective;
    break;
  case Type::BoolTyID:
  case Type::PointerTyID:
  case Type::UIntTyID: case Type::IntTyID:
    O << Data32bitsDirective;
    break;
  case Type::ULongTyID: case Type::LongTyID:
    assert (0 && "Should have already output double-word constant.");
  case Type::FloatTyID: case Type::DoubleTyID:
    assert (0 && "Should have already output floating point constant.");
  default:
    assert (0 && "Can't handle printing this type of thing");
    break;
  }
  emitConstantValueOnly(CV);
  O << "\n";
}
<|endoftext|>


<commit_before>#include "notewidgetdelegate.h"
#include "noteview.h"
#include <QPainter>
#include <QEvent>
#include <QDebug>
#include "notemodel.h"

NoteWidgetDelegate::NoteWidgetDelegate(QObject *parent)
    : QStyledItemDelegate(parent),
      m_titleFont(QFont(QStringLiteral("Liberation Sans"), 10,QFont::Bold)),
      m_dateFont(QFont(QStringLiteral("Liberation Sans"), 8)),
      m_titleColor(0, 0, 0),
      m_dateColor(132, 132, 132),
      m_focusColor(254, 206, 9),
      m_noFocusColor(255, 235, 80),
      m_hoverColor(207, 207, 207),
      m_separatorColor(221, 221, 221),
      m_defaultColor(255,255,255),
      m_rowHeight(38),
      m_maxFrame(200),
      m_state(Normal)
{
    m_timeLine = new QTimeLine(300, this);
    m_timeLine->setFrameRange(0,m_maxFrame);
    m_timeLine->setUpdateInterval(10);
    m_timeLine->setCurveShape(QTimeLine::EaseInOutCurve);

    connect( m_timeLine, &QTimeLine::frameChanged, [this](){
        emit sizeHintChanged(m_animatedIndex);
    });

    connect(m_timeLine, &QTimeLine::finished, [this](){
        m_animatedIndex = QModelIndex();
        m_state = Normal;
    });
}

void NoteWidgetDelegate::setState(States NewState, QModelIndex index)
{
    m_animatedIndex = index;

    auto startAnimation = [this](QTimeLine::Direction diretion, int duration){
        m_timeLine->setDirection(diretion);
        m_timeLine->setDuration(duration);
        m_timeLine->start();
    };

    switch ( NewState ){
    case Insert:
        startAnimation(QTimeLine::Forward, m_maxFrame);
        break;
    case Remove:
        startAnimation(QTimeLine::Backward, m_maxFrame);
        break;
    case MoveOut:
        startAnimation(QTimeLine::Backward, m_maxFrame);
        break;
    case MoveIn:
        startAnimation(QTimeLine::Backward, m_maxFrame);
        break;
    case Normal:
        m_animatedIndex = QModelIndex();
        break;
    }

    m_state = NewState;
}

void NoteWidgetDelegate::setAnimationDuration(const int duration)
{
    m_timeLine->setDuration(duration);
}

void NoteWidgetDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    painter->save();
    QStyleOptionViewItem opt = option;
    opt.rect.setWidth(option.rect.width()-2);

    int currentFrame = m_timeLine->currentFrame();
    double rate = (currentFrame/(double)m_maxFrame);
    double height = m_rowHeight * rate;

    switch(m_state){
    case Insert:
    case Remove:
    case MoveOut:
        if(index == m_animatedIndex){
            opt.rect.setHeight(height);
            opt.backgroundBrush.setColor(m_noFocusColor);
        }
        break;
    case MoveIn:
        if(index == m_animatedIndex){
            opt.rect.setY(height);
        }
        break;
    case Normal:
        break;
    }

    paintBackground(painter, opt, index);
    paintTitle(painter, option, index);
    paintDateTime(painter, option, index);

    painter->restore();
}

QSize NoteWidgetDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QSize result = QStyledItemDelegate::sizeHint(option, index);
    if(index == m_animatedIndex){
        if(m_state == MoveIn){
            result.setHeight(m_rowHeight);
        }else{
            double rate = m_timeLine->currentFrame()/(double)m_maxFrame;
            double height = m_rowHeight * rate;
            result.setHeight(height);
        }
    }else{
        result.setHeight(m_rowHeight);
    }

    return result;
}

QTimeLine::State NoteWidgetDelegate::animationState()
{
    return m_timeLine->state();
}

void NoteWidgetDelegate::paintBackground(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    painter->save();
    if((option.state & QStyle::State_Selected) == QStyle::State_Selected){
        if((option.state & QStyle::State_HasFocus)== QStyle::State_HasFocus){
            painter->fillRect(option.rect, QBrush(m_focusColor));
        }else{
            painter->fillRect(option.rect, QBrush(m_noFocusColor));
        }
    }else if((option.state & QStyle::State_MouseOver) == QStyle::State_MouseOver){
        painter->fillRect(option.rect, QBrush(m_hoverColor));
    }else if((index.row() !=  m_currentSelectedIndex.row() -1)
             && (index.row() !=  m_hoveredIndex.row() -1)){

        painter->fillRect(option.rect, QBrush(m_defaultColor));
        paintSeparator(painter, option, index);
    }
    painter->restore();
}

void NoteWidgetDelegate::paintTitle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    painter->save();
    QString title{index.data(NoteModel::NoteFullTitle).toString()};
    QFontMetrics fontMetrics(m_titleFont);
    title = fontMetrics.elidedText(title,Qt::ElideRight, option.rect.width() - 20);

    painter->setPen(m_titleColor);
    painter->setFont(m_titleFont);

    double rate = m_timeLine->currentFrame()/(double)m_maxFrame;
    int posX = option.rect.x() + 10;
    int posY = option.rect.y() + 15;

    if(index.row() == m_animatedIndex.row()){
        if(m_state == MoveIn){
            int posYAnim = posY + m_rowHeight * rate;
            painter->drawText(QPoint(posX, posYAnim), title);
        }else{
            int posYAnim = posY + m_rowHeight * (rate - 1);
            painter->drawText(QPoint(posX, posYAnim), title);
        }
    }else{
        painter->drawText(QPoint(posX, posY), title);
    }
    painter->restore();
}

void NoteWidgetDelegate::paintDateTime(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    painter->save();
    QString date = parseDateTime(index.data(NoteModel::NoteLastModificationDateTime).toDateTime());
    painter->setPen(m_dateColor);
    painter->setFont(m_dateFont);

    double rate = m_timeLine->currentFrame()/(double)m_maxFrame;
    int posX = option.rect.x() + 10;
    int posY = option.rect.y() + 31;

    if(index.row() == m_animatedIndex.row()){
        if(m_state == MoveIn){
            int posYAnim = posY + m_rowHeight * rate;
            painter->drawText(QPoint(posX, posYAnim), date);
        }else{
            int posYAnim = posY + m_rowHeight * (rate - 1);
            painter->drawText(QPoint(posX, posYAnim), date);
        }
    }else{
        painter->drawText(QPoint(posX, posY), date);
    }
    painter->restore();
}

void NoteWidgetDelegate::paintSeparator(QPainter*painter, const QStyleOptionViewItem&option, const QModelIndex&index) const
{
    Q_UNUSED(index)

    painter->setPen(QPen(m_separatorColor));

    int posX1 = option.rect.x() + 10;
    int posX2 = option.rect.x() + option.rect.width()-11;
    int posY = option.rect.y() + option.rect.height()-1;

    painter->drawLine(QPoint(posX1, posY),
                      QPoint(posX2, posY));
}

QString NoteWidgetDelegate::parseDateTime(const QDateTime &dateTime) const
{
    QLocale usLocale(QLocale("en_US"));

    auto currDateTime = QDateTime::currentDateTime();

    if(dateTime.date() == currDateTime.date()){
        return usLocale.toString(dateTime.time(),"h:mm A");
    }else if(dateTime.daysTo(currDateTime) == 1){
        return "Yesterday";
    }else if(dateTime.daysTo(currDateTime) >= 2 &&
             dateTime.daysTo(currDateTime) <= 7){
        return usLocale.toString(dateTime.date(), "dddd");
    }

    return dateTime.date().toString("M/d/yy");
}

void NoteWidgetDelegate::setHoveredIndex(const QModelIndex &hoveredIndex)
{
    m_hoveredIndex = hoveredIndex;
}

void NoteWidgetDelegate::setCurrentSelectedIndex(const QModelIndex &currentSelectedIndex)
{
    m_currentSelectedIndex = currentSelectedIndex;
}
<commit_msg>Fixing animation<commit_after>#include "notewidgetdelegate.h"
#include "noteview.h"
#include <QPainter>
#include <QEvent>
#include <QDebug>
#include "notemodel.h"

NoteWidgetDelegate::NoteWidgetDelegate(QObject *parent)
    : QStyledItemDelegate(parent),
      m_titleFont(QFont(QStringLiteral("Liberation Sans"), 10,QFont::Bold)),
      m_dateFont(QFont(QStringLiteral("Liberation Sans"), 8)),
      m_titleColor(0, 0, 0),
      m_dateColor(132, 132, 132),
      m_focusColor(254, 206, 9),
      m_noFocusColor(255, 235, 80),
      m_hoverColor(207, 207, 207),
      m_separatorColor(221, 221, 221),
      m_defaultColor(255,255,255),
      m_rowHeight(38),
      m_maxFrame(200),
      m_state(Normal)
{
    m_timeLine = new QTimeLine(300, this);
    m_timeLine->setFrameRange(0,m_maxFrame);
    m_timeLine->setUpdateInterval(10);
    m_timeLine->setCurveShape(QTimeLine::EaseInCurve);

    connect( m_timeLine, &QTimeLine::frameChanged, [this](){
        emit sizeHintChanged(m_animatedIndex);
    });

    connect(m_timeLine, &QTimeLine::finished, [this](){
        m_animatedIndex = QModelIndex();
        m_state = Normal;
    });
}

void NoteWidgetDelegate::setState(States NewState, QModelIndex index)
{
    m_animatedIndex = index;

    auto startAnimation = [this](QTimeLine::Direction diretion, int duration){
        m_timeLine->setDirection(diretion);
        m_timeLine->setDuration(duration);
        m_timeLine->start();
    };

    switch ( NewState ){
    case Insert:
        startAnimation(QTimeLine::Forward, m_maxFrame);
        break;
    case Remove:
        startAnimation(QTimeLine::Backward, m_maxFrame);
        break;
    case MoveOut:
        startAnimation(QTimeLine::Backward, m_maxFrame);
        break;
    case MoveIn:
        startAnimation(QTimeLine::Backward, m_maxFrame);
        break;
    case Normal:
        m_animatedIndex = QModelIndex();
        break;
    }

    m_state = NewState;
}

void NoteWidgetDelegate::setAnimationDuration(const int duration)
{
    m_timeLine->setDuration(duration);
}

void NoteWidgetDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    painter->save();
    QStyleOptionViewItem opt = option;
    opt.rect.setWidth(option.rect.width()-2);

    int currentFrame = m_timeLine->currentFrame();
    double rate = (currentFrame/(double)m_maxFrame);
    double height = m_rowHeight * rate;

    switch(m_state){
    case Insert:
    case Remove:
    case MoveOut:
        if(index == m_animatedIndex){
            opt.rect.setHeight(height);
            opt.backgroundBrush.setColor(m_noFocusColor);
        }
        break;
    case MoveIn:
        if(index == m_animatedIndex){
            opt.rect.setY(height);
        }
        break;
    case Normal:
        break;
    }

    paintBackground(painter, opt, index);
    paintTitle(painter, option, index);
    paintDateTime(painter, option, index);

    painter->restore();
}

QSize NoteWidgetDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QSize result = QStyledItemDelegate::sizeHint(option, index);
    if(index == m_animatedIndex){
        if(m_state == MoveIn){
            result.setHeight(m_rowHeight);
        }else{
            double rate = m_timeLine->currentFrame()/(double)m_maxFrame;
            double height = m_rowHeight * rate;
            result.setHeight(height);
        }
    }else{
        result.setHeight(m_rowHeight);
    }

    return result;
}

QTimeLine::State NoteWidgetDelegate::animationState()
{
    return m_timeLine->state();
}

void NoteWidgetDelegate::paintBackground(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    painter->save();
    if((option.state & QStyle::State_Selected) == QStyle::State_Selected){
        if((option.state & QStyle::State_HasFocus)== QStyle::State_HasFocus){
            painter->fillRect(option.rect, QBrush(m_focusColor));
        }else{
            painter->fillRect(option.rect, QBrush(m_noFocusColor));
        }
    }else if((option.state & QStyle::State_MouseOver) == QStyle::State_MouseOver){
        painter->fillRect(option.rect, QBrush(m_hoverColor));
    }else if((index.row() !=  m_currentSelectedIndex.row() -1)
             && (index.row() !=  m_hoveredIndex.row() -1)){

        painter->fillRect(option.rect, QBrush(m_defaultColor));
        paintSeparator(painter, option, index);
    }
    painter->restore();
}

void NoteWidgetDelegate::paintTitle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    painter->save();
    QString title{index.data(NoteModel::NoteFullTitle).toString()};
    QFontMetrics fm(m_titleFont);
    QRect fmRect = fm.boundingRect(title);
    title = fm.elidedText(title,Qt::ElideRight, option.rect.width() - 20);
    painter->setPen(m_titleColor);
    painter->setFont(m_titleFont);

    double rowRate = m_timeLine->currentFrame()/(double)m_maxFrame;
    int rowPosX = option.rect.x();
    int rowPosY = option.rect.y();
    int rowWidth = option.rect.width();
    int textRectPosX = rowPosX + 10;
    int textRectPosY = rowPosY;
    double textRectWidth = rowWidth - textRectPosX - 10;
    double textRectHeight = fmRect.height() + 4.0;

    auto textRect = [&](double heightRate){
        return QRectF(textRectPosX, textRectPosY, textRectWidth, textRectHeight*heightRate);
    };

    if(index.row() == m_animatedIndex.row()){
        if(m_state == MoveIn){
            int posX = option.rect.x() + 10;
            int posY = option.rect.y() + 16;
            int posYAnim = posY + m_rowHeight * rowRate;
            painter->drawText(QPoint(posX, posYAnim), title);
        }else{
            double currRowHeight = m_rowHeight * rowRate;
            if(currRowHeight >= textRectHeight){
                double rateTitle = (currRowHeight - textRectHeight)/(m_rowHeight - textRectHeight);
                painter->drawText(textRect(rateTitle), Qt::AlignBottom, title);
            }
        }
    }else{
        painter->drawText(textRect(1), Qt::AlignBottom, title);
    }
    painter->restore();
}

void NoteWidgetDelegate::paintDateTime(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    painter->save();
    QString date = parseDateTime(index.data(NoteModel::NoteLastModificationDateTime).toDateTime());
    painter->setPen(m_dateColor);
    painter->setFont(m_dateFont);
    QFontMetrics fm(m_dateFont);

    int rowPosX = option.rect.x();
    int rowPosY = option.rect.y();
    int rowWidth = option.rect.width();
    double rowHeightRate = m_timeLine->currentFrame()/(double)m_maxFrame;
    double currRowHeight = m_rowHeight * rowHeightRate;
    double textRectPosX = rowPosX + 10;
    double textRectWidth = rowWidth - textRectPosX - 10;

    if(index.row() == m_animatedIndex.row()){
        if(m_state == MoveIn){
            int textPosX = rowPosX + 10;
            int textPosY = rowPosY + 32;
            int posYAnim = textPosY + currRowHeight;
            painter->drawText(QPoint(textPosX, posYAnim), date);
        }else{

            double textRectHeight = fm.height() + 2;
            double textRectPosY = rowPosY + currRowHeight - (textRectHeight + 3);

            if(currRowHeight <= (textRectHeight + 3)){
                textRectPosY = rowPosY;
                textRectHeight = currRowHeight - 3;
            }

            QRectF rect(textRectPosX, textRectPosY, textRectWidth, textRectHeight);
            painter->drawText(rect, Qt::AlignBottom, date);
        }
    }else{
        double textRectHeight = fm.height() + 2;
        double textRectPosY = rowPosY + m_rowHeight - (textRectHeight+3);
        QRectF rect(QPoint(textRectPosX, textRectPosY), QSize(textRectWidth, textRectHeight));
        painter->drawText(rect, Qt::AlignBottom, date);
    }
    painter->restore();
}

void NoteWidgetDelegate::paintSeparator(QPainter*painter, const QStyleOptionViewItem&option, const QModelIndex&index) const
{
    Q_UNUSED(index)

    painter->setPen(QPen(m_separatorColor));

    int posX1 = option.rect.x() + 10;
    int posX2 = option.rect.x() + option.rect.width()-11;
    int posY = option.rect.y() + option.rect.height()-1;

    painter->drawLine(QPoint(posX1, posY),
                      QPoint(posX2, posY));
}

QString NoteWidgetDelegate::parseDateTime(const QDateTime &dateTime) const
{
    QLocale usLocale(QLocale("en_US"));

    auto currDateTime = QDateTime::currentDateTime();

    if(dateTime.date() == currDateTime.date()){
        return usLocale.toString(dateTime.time(),"h:mm A");
    }else if(dateTime.daysTo(currDateTime) == 1){
        return "Yesterday";
    }else if(dateTime.daysTo(currDateTime) >= 2 &&
             dateTime.daysTo(currDateTime) <= 7){
        return usLocale.toString(dateTime.date(), "dddd");
    }

    return dateTime.date().toString("M/d/yy");
}

void NoteWidgetDelegate::setHoveredIndex(const QModelIndex &hoveredIndex)
{
    m_hoveredIndex = hoveredIndex;
}

void NoteWidgetDelegate::setCurrentSelectedIndex(const QModelIndex &currentSelectedIndex)
{
    m_currentSelectedIndex = currentSelectedIndex;
}
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
//  AY38910Window.cc
//------------------------------------------------------------------------------
#include "AY38910Window.h"
#include "IMUI/IMUI.h"

using namespace Oryol;

namespace YAKC {

//------------------------------------------------------------------------------
void
AY38910Window::Setup(yakc& emu) {
    this->setName("AY-3-8910 State");
}

//------------------------------------------------------------------------------
bool
AY38910Window::Draw(yakc& emu) {
    ImGui::SetNextWindowSize(ImVec2(220, 270), ImGuiSetCond_Once);
    if (ImGui::Begin(this->title.AsCStr(), &this->Visible)) {
        const ay38910_t& ay = board.ay38910;
        const char* type = "unknown";
        switch (ay.type) {
            case AY38910_TYPE_8910: type="AY-3-8910"; break;
            case AY38910_TYPE_8912: type="AY-3-8912"; break;
            case AY38910_TYPE_8913: type="AY-3-8913"; break;
        }
        const uint16_t period_a = (ay.period_a_coarse<<8)|ay.period_a_fine;
        const uint16_t period_b = (ay.period_b_coarse<<8)|ay.period_b_fine;
        const uint16_t period_c = (ay.period_c_coarse<<8)|ay.period_c_fine;
        const uint16_t period_env = (ay.period_env_coarse<<8)|ay.period_env_fine;
        ImGui::Text("Type:         %s", type);
        ImGui::Separator();
        ImGui::Text("              A    B    C");
        ImGui::Text("Tone Periods: %04X %04X %04X", period_a, period_b, period_c);
        ImGui::Text("Tone Amps:    %02X   %02X   %02X", ay.amp_a, ay.amp_b, ay.amp_c);
        ImGui::Text("Noise Period: %02X", ay.period_noise);
        ImGui::Text("Env Period:   %04X", period_env);
        ImGui::Text("Env Cycle:    %02X", ay.env_shape_cycle);
        ImGui::Text("Enable:       %02X", ay.enable);
        ImGui::Text("IO Ports:     %02X   %02X", ay.port_a, ay.port_b);
        ImGui::Separator();
        ImGui::Text("Tone Counter: %04X %04X %04X", ay.tone[0].counter, ay.tone[1].counter, ay.tone[2].counter);
        ImGui::Text("Tone Bit:     %s %s %s",
            ay.tone[0].bit ? "ON  ":"OFF ",
            ay.tone[1].bit ? "ON  ":"OFF ",
            ay.tone[2].bit ? "ON  ":"OFF ");
        ImGui::Text("Tone Enable:  %s %s %s",
            !ay.tone[0].tone_disable ? "ON  ":"OFF ",
            !ay.tone[1].tone_disable ? "ON  ":"OFF ",
            !ay.tone[2].tone_disable ? "ON  ":"OFF ");
        ImGui::Text("Noise Enable: %s %s %s",
            !ay.tone[0].noise_disable ? "ON  ":"OFF ",
            !ay.tone[1].noise_disable ? "ON  ":"OFF ",
            !ay.tone[2].noise_disable ? "ON  ":"OFF ");
        ImGui::Text("Env Counter:  %04X", ay.env.counter);
    }
    ImGui::End();
    return this->Visible;
}

} // namespace YAKC
<commit_msg>Add envelope generator info to AY-3-8910 window<commit_after>//------------------------------------------------------------------------------
//  AY38910Window.cc
//------------------------------------------------------------------------------
#include "AY38910Window.h"
#include "IMUI/IMUI.h"

using namespace Oryol;

namespace YAKC {

//------------------------------------------------------------------------------
void
AY38910Window::Setup(yakc& emu) {
    this->setName("AY-3-8910 State");
}

//------------------------------------------------------------------------------
bool
AY38910Window::Draw(yakc& emu) {
    ImGui::SetNextWindowSize(ImVec2(240, 352), ImGuiSetCond_Once);
    if (ImGui::Begin(this->title.AsCStr(), &this->Visible)) {
        const ay38910_t& ay = board.ay38910;
        const char* type = "unknown";
        switch (ay.type) {
            case AY38910_TYPE_8910: type="AY-3-8910"; break;
            case AY38910_TYPE_8912: type="AY-3-8912"; break;
            case AY38910_TYPE_8913: type="AY-3-8913"; break;
        }
        const uint16_t period_a = (ay.period_a_coarse<<8)|ay.period_a_fine;
        const uint16_t period_b = (ay.period_b_coarse<<8)|ay.period_b_fine;
        const uint16_t period_c = (ay.period_c_coarse<<8)|ay.period_c_fine;
        const uint16_t period_env = (ay.period_env_coarse<<8)|ay.period_env_fine;
        ImGui::Text("Type:         %s", type);
        ImGui::Separator();
        ImGui::Text("              A    B    C");
        ImGui::Text("Tone Periods: %04X %04X %04X", period_a, period_b, period_c);
        ImGui::Text("Tone Amps:    %02X   %02X   %02X", ay.amp_a, ay.amp_b, ay.amp_c);
        ImGui::Text("Noise Period: %02X", ay.period_noise);
        ImGui::Text("Env Period:   %04X", period_env);
        ImGui::Text("Env Cycle:    %02X", ay.env_shape_cycle);
        ImGui::Text("Enable:       %02X", ay.enable);
        ImGui::Text("IO Ports:     %02X   %02X", ay.port_a, ay.port_b);
        ImGui::Separator();
        ImGui::Text("Tone Counter: %04X %04X %04X", ay.tone[0].counter, ay.tone[1].counter, ay.tone[2].counter);
        ImGui::Text("Tone Bit:     %s %s %s",
            ay.tone[0].bit ? "ON  ":"OFF ",
            ay.tone[1].bit ? "ON  ":"OFF ",
            ay.tone[2].bit ? "ON  ":"OFF ");
        ImGui::Text("Tone Enable:  %s %s %s",
            !ay.tone[0].tone_disable ? "ON  ":"OFF ",
            !ay.tone[1].tone_disable ? "ON  ":"OFF ",
            !ay.tone[2].tone_disable ? "ON  ":"OFF ");
        ImGui::Text("Noise Enable: %s %s %s",
            !ay.tone[0].noise_disable ? "ON  ":"OFF ",
            !ay.tone[1].noise_disable ? "ON  ":"OFF ",
            !ay.tone[2].noise_disable ? "ON  ":"OFF ");
        ImGui::Text("Env Enable:   %s %s %s",
            (ay.amp_a & (1<<4)) ? "ON  ":"OFF ",
            (ay.amp_b & (1<<4)) ? "ON  ":"OFF ",
            (ay.amp_c & (1<<4)) ? "ON  ":"OFF ");
        ImGui::Text("Env Counter:   %04X", ay.env.counter);
        ImGui::Text("Env Shape Ctr: %02X", ay.env.shape_counter);
        ImGui::Text("Env Volume:    %02X", ay.env.shape_state);
        ImGui::Text("Env Hold/Holding: %s/%s", ay.env.shape_hold?"ON ":"OFF", ay.env.shape_holding?"ON ":"OFF");
    }
    ImGui::End();
    return this->Visible;
}

} // namespace YAKC
<|endoftext|>


<commit_before>#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
#include <sensor_msgs/PointCloud.h>
#include <math.h>

static const float tol = 0.000000000000001f;

double magnitude(double vec[3]){
    return sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]);
}

void normalize(double vec[3]){
    float m = magnitude(vec);
    if(tol >= m) m = 1;
    vec[0] /= m;
    vec[1] /= m;
    vec[2] /= m;

    if(fabs(vec[0]) < tol) vec[0] = 0.0f;
    if(fabs(vec[1]) < tol) vec[1] = 0.0f;
    if(fabs(vec[2]) < tol) vec[2] = 0.0f;
}

class ArtificialPotentialField{
public:
    ArtificialPotentialField(ros::NodeHandle &node) :
        cmd_pub_(node.advertise<geometry_msgs::Twist>("cmd_vel", 10)),
        obs_sub_(node.subscribe("slam_cloud", 10, &ArtificialPotentialField::obstacleCallback, this))

    {
        for(int i=0; i < 3; i++) obs_[i] = 0;
    }

    void spin(){
        ros::Rate r(10);

        ros::Duration(1).sleep();
        geometry_msgs::Twist cmd;
        cmd.linear.z = 0.15;
        cmd_pub_.publish(cmd);
        ros::Duration(3).sleep();

        cmd.linear.z = 0;
        cmd_pub_.publish(cmd);
        ros::Duration(3).sleep();

        const double A = 0;
        const double B = 3;
        const double n = 1;
        const double m = 1.5;
        const double force = 0.025;

        while(ros::ok()){
            double Fs[3];
            Fs[0] = Fs[1] = Fs[2] = 0;

            double f_in[3];
            get_potential_force(obs_, f_in, 0, 3, 1, 1.5);

            Fs[0] += f_in[0];
            Fs[1] += f_in[1];
            Fs[2] += f_in[2];

            cmd.linear.x = -Fs[0] * force;
            cmd.linear.y = Fs[1] * force;

            ROS_INFO("obs = (%f, %f)", obs_[0], obs_[1]);
            ROS_INFO_STREAM("cmd = " << cmd);
            cmd_pub_.publish(cmd);
            r.sleep();
            ros::spinOnce();
        }
    }

private:
    void get_potential_force(double dest_lc[3], double f_out[3], double A = 1, double B = 3, double n = 1, double m = 1.5){
        double u[3];
        u[0] = dest_lc[0];
        u[1] = dest_lc[1];
        u[2] = dest_lc[2];
        normalize(u);

        const double d = magnitude(dest_lc);
        double U = 0;
        if(fabs(d) > tol){
            U = -A/pow(d, n) + B/pow(d, m);
        }

        f_out[0] = U * u[0];
        f_out[1] = U * u[1];
        f_out[2] = U * u[2];
    }

    void obstacleCallback(const sensor_msgs::PointCloudPtr &obs_msg){

        if(obs_msg->points.size() == 0){
            obs_[0] = 0;
            obs_[1] = 0;
            obs_[2] = 0;
            return;
        }

        double min_obs[3];
        min_obs[0] = obs_msg->points[0].x;
        min_obs[1] = obs_msg->points[0].y;
        min_obs[2] = obs_msg->points[0].z;

        float min_dist = magnitude(min_obs);

        for(int i=1; i < obs_msg->points.size(); i++){
            double obs[3];
            obs[0] = obs_msg->points[i].x;
            obs[1] = obs_msg->points[i].y;
            obs[2] = obs_msg->points[i].z;

            //ROS_INFO("(%f, %f)", obs[0], obs[1]);

            double dist = magnitude(obs);
            if(dist < min_dist){
                min_obs[0] = obs[0];
                min_obs[1] = obs[1];
                min_obs[2] = obs[2];
                min_dist = dist;
            }
        }

        obs_[0] = min_obs[0];
        obs_[1] = min_obs[1];
        obs_[2] = min_obs[2];
    }

    double obs_[3];
    ros::Publisher cmd_pub_;
    ros::Subscriber obs_sub_;
};

int main(int argc, char *argv[]){
    ros::init(argc, argv, "obstacle_avoidance");

    ros::NodeHandle node;
    ArtificialPotentialField apf = ArtificialPotentialField(node);
    apf.spin();

    return 0;
}

<commit_msg>add attraction force<commit_after>#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
#include <sensor_msgs/PointCloud.h>
#include <math.h>

static const float tol = 0.000000000000001f;

double magnitude(double vec[3]){
    return sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]);
}

void normalize(double vec[3]){
    float m = magnitude(vec);
    if(tol >= m) m = 1;
    vec[0] /= m;
    vec[1] /= m;
    vec[2] /= m;

    if(fabs(vec[0]) < tol) vec[0] = 0.0f;
    if(fabs(vec[1]) < tol) vec[1] = 0.0f;
    if(fabs(vec[2]) < tol) vec[2] = 0.0f;
}

class ArtificialPotentialField{
public:
    ArtificialPotentialField(ros::NodeHandle &node) :
        cmd_pub_(node.advertise<geometry_msgs::Twist>("cmd_vel", 10)),
        obs_sub_(node.subscribe("slam_cloud", 10, &ArtificialPotentialField::obstacleCallback, this))

    {
        for(int i=0; i < 3; i++) obs_[i] = 0;
    }

    void spin(){
        ros::Rate r(10);

        ros::Duration(1).sleep();
        geometry_msgs::Twist cmd;
        cmd.linear.z = 0.15;
        cmd_pub_.publish(cmd);
        ros::Duration(3).sleep();

        cmd.linear.z = 0;
        cmd_pub_.publish(cmd);
        ros::Duration(3).sleep();

        const double A = 0;
        const double B = 3;
        const double n = 1;
        const double m = 1.5;
        const double force = 0.025;

        while(ros::ok()){
            double Fs[3];
            Fs[0] = Fs[1] = Fs[2] = 0;

            double f_in[3];
            get_potential_force(obs_, f_in, 0, 3, 1, 1.5);

            Fs[0] += f_in[0];
            Fs[1] += f_in[1];
            Fs[2] += f_in[2];

            double g[3];
            g[0] = 0.5;
            g[1] = 0;
            g[2] = 0;

            get_potential_force(g, f_in, 3, 0, 1.5, 1);

            Fs[0] += f_in[0];
            Fs[1] += f_in[1];
            Fs[2] += f_in[2];

            cmd.linear.x = -Fs[0] * force;
            cmd.linear.y = Fs[1] * force;

            ROS_INFO("obs = (%f, %f)", obs_[0], obs_[1]);
            ROS_INFO_STREAM("cmd = " << cmd);
            cmd_pub_.publish(cmd);
            r.sleep();
            ros::spinOnce();
        }
    }

private:
    void get_potential_force(double dest_lc[3], double f_out[3], double A = 1, double B = 3, double n = 1, double m = 1.5){
        double u[3];
        u[0] = dest_lc[0];
        u[1] = dest_lc[1];
        u[2] = dest_lc[2];
        normalize(u);

        const double d = magnitude(dest_lc);
        double U = 0;
        if(fabs(d) > tol){
            U = -A/pow(d, n) + B/pow(d, m);
        }

        f_out[0] = U * u[0];
        f_out[1] = U * u[1];
        f_out[2] = U * u[2];
    }

    void obstacleCallback(const sensor_msgs::PointCloudPtr &obs_msg){

        if(obs_msg->points.size() == 0){
            obs_[0] = 0;
            obs_[1] = 0;
            obs_[2] = 0;
            return;
        }

        double min_obs[3];
        min_obs[0] = obs_msg->points[0].x;
        min_obs[1] = obs_msg->points[0].y;
        min_obs[2] = obs_msg->points[0].z;

        float min_dist = magnitude(min_obs);

        for(int i=1; i < obs_msg->points.size(); i++){
            double obs[3];
            obs[0] = obs_msg->points[i].x;
            obs[1] = obs_msg->points[i].y;
            obs[2] = obs_msg->points[i].z;

            //ROS_INFO("(%f, %f)", obs[0], obs[1]);

            double dist = magnitude(obs);
            if(dist < min_dist){
                min_obs[0] = obs[0];
                min_obs[1] = obs[1];
                min_obs[2] = obs[2];
                min_dist = dist;
            }
        }

        obs_[0] = min_obs[0];
        obs_[1] = min_obs[1];
        obs_[2] = min_obs[2];
    }

    double obs_[3];
    ros::Publisher cmd_pub_;
    ros::Subscriber obs_sub_;
};

int main(int argc, char *argv[]){
    ros::init(argc, argv, "obstacle_avoidance");

    ros::NodeHandle node;
    ArtificialPotentialField apf = ArtificialPotentialField(node);
    apf.spin();

    return 0;
}

<|endoftext|>


<commit_before>#include <main.h>
#include <pidData.h>

// Imu code includes a lot of buffers moving around
// Currently not circular
// Very bug prone; needs more testing
// Maybe add timestamps?

// Imu samples go here
// These are processed on the same main thread so hopefully no race conditions
// Indexes into imuSamples; Marks index of next data point to transmit to audacy
// If sentDataPointer == dataPointer, buffer is empty
// If dataPointer == sentDataPointer - IMU_SAMPLE_SIZE, buffer is full
volatile unsigned int imuSentDataPointer = 0;
volatile unsigned int imuDataPointer = 0; // Marks index of next place to read into
volatile unsigned int imuSamplesSent = 0;
volatile pidSample imuSamples[IMU_BUFFER_SIZE + 10]; // Add some extra space on the end in case we overflow
volatile bool sampling = false;
elapsedMicros timeSinceLastRead;

// This packet ships out directly to audacy
// This is more than we need; OUT_PACKET_OVERHEAD is measured in units of uint16_t, not pidSample
volatile expandedPidSample imuDumpPacketMemory[IMU_DATA_DUMP_SIZE + OUT_PACKET_OVERHEAD + 10];
// We skip the first few uint16 because we want the packet body to begin at imuDumpPacketMemory[1], which has a good byte offset mod 32bit.
// Assume header size is less than IMU_SAMPLE_SIZE
volatile uint32_t *imuDumpPacket = ((uint32_t *) imuDumpPacketMemory) + (6 * IMU_SAMPLE_SIZE - OUT_PACKET_BODY_BEGIN);

// Where the telemetry goes
volatile expandedPidSample *imuDumpPacketBegin = (expandedPidSample *) (imuDumpPacket + OUT_PACKET_BODY_BEGIN);
// Where the samples go
volatile expandedPidSample *imuDumpPacketBody = imuDumpPacketBegin + 0;
volatile uint16_t imuPacketChecksum = 0;
volatile unsigned int imuPacketBodyPointer = 0;
volatile bool imuPacketReady = false;

// Telemetry
volatile unsigned int imuSamplesRead = 0;
volatile unsigned int imuSamplesQueued = 0;

// Runs in main's setup()
void imuSetup() {

    assert(((unsigned int) imuDumpPacketBody) % 4 == 0);  // Check offset; Misaligned data may segfault at 0x20000000
    // assert(((unsigned int) imuSamples) % 4 == 0); // GCC says this is statically checkable
    debugPrintf("imuSamples location (we want this to be far from 0x2000000): %p to %p\n", imuSamples, imuSamples + IMU_BUFFER_SIZE);
    debugPrintf("imuDumpPacket location (we want this to be far from 0x2000000): memory begins %p, samples %p to %p\n", imuDumpPacketMemory, imuDumpPacket, imuDumpPacketMemory + IMU_DATA_DUMP_SIZE + OUT_PACKET_OVERHEAD);
    pinMode(IMU_DATA_READY_PIN, OUTPUT);
    /* TODO: put check back in // for (int i = 0; i < 10; i++) {
        imuSamples[IMU_BUFFER_SIZE + i] = 0xbeef;
        imuDumpPacket[IMU_DATA_DUMP_SIZE + OUT_PACKET_OVERHEAD + i] = 0xbeef;
    }
    assert (imuSamples[IMU_BUFFER_SIZE] == 0xbeef);*/
}

void writeExpandedPidSampleWithChecksum(const pidSample* in, volatile expandedPidSample* out, volatile uint16_t& pidBufferChecksum) {
    assert(sizeof(pidSample) * 2 == sizeof(expandedPidSample));
    assert(sizeof(pidSample) == 4 * 4 * 3);
    unsigned int num_uint32 = sizeof(pidSample) / 4;
    for (unsigned int i = 0; i < num_uint32; i++) {
        uint32_t num = ((uint32_t *) in)[i];
        ((uint32_t *) out)[2 * i] = num >> 16; // msb
        pidBufferChecksum += num >> 16;
        ((uint32_t *) out)[2 * i + 1] = num % (1 << 16); // lsb
        pidBufferChecksum += num % (1 << 16);
    }
}

void checkDataDump() {
    noInterrupts();
    unsigned int imuPacketBodyPointerSave = imuPacketBodyPointer;
    unsigned int imuPacketReadySave = imuPacketReady;
    if(!assert((imuPacketBodyPointerSave == IMU_DATA_DUMP_SIZE) == imuPacketReadySave)) {
        debugPrintf("packetBodyPointer %d, ready? %d\n", imuPacketBodyPointerSave, imuPacketReadySave);
    }
    if (imuPacketReady) {
        interrupts();
        return;
    }
    noInterrupts();
    if ((imuPacketBodyPointer < IMU_DATA_DUMP_SIZE) && (imuSentDataPointer % IMU_BUFFER_SIZE) != (imuDataPointer % IMU_BUFFER_SIZE)) {
        pidSample sample = imuSamples[imuSentDataPointer];
        //imuPacketChecksum += sample.getChecksum();
        writeExpandedPidSampleWithChecksum(&sample, &(imuDumpPacketBody[imuPacketBodyPointer]), imuPacketChecksum);
        imuPacketBodyPointer++;
        imuSentDataPointer++;
    }
    imuSentDataPointer = imuSentDataPointer % IMU_BUFFER_SIZE;
    assert(imuPacketBodyPointer <= IMU_DATA_DUMP_SIZE);
    if (imuPacketBodyPointer >= IMU_DATA_DUMP_SIZE) {
        // Prepare packet!
        noInterrupts();
        assert((sizeof(pidSample) * 8) % 16 == 0);
        imuPacketReady = true;

        digitalWriteFast(IMU_DATA_READY_PIN, HIGH);
    }

    interrupts();
}

void recordPid(const volatile pidSample& s) {
    //debugPrintf("Sampling %d imuDataPointer %d IMU_BUFFER_SIZE %d\n", sampling, imuDataPointer, IMU_BUFFER_SIZE);
    //assert(sampling);
    if (!sampling) {
        //debugPrintf("Warning: buffer is full!\n");
        return;
    }
    //assert(imuDataPointer % IMU_NUM_CHANNELS == 0);
    ((pidSample *) imuSamples)[imuDataPointer] = s;
    imuDataPointer = (imuDataPointer + 1) % IMU_BUFFER_SIZE;
    imuSamplesRead++;
    //debugPrintf("Base array %p, writing to %p, end of array %p\n", &((pidSample *) imuSamples)[0], &((pidSample *) imuSamples)[imuDataPointer], &imuSamples[IMU_BUFFER_SIZE]);
    assert(imuDataPointer <= IMU_BUFFER_SIZE);

    if (((imuDataPointer + 1) % IMU_BUFFER_SIZE) == (imuSentDataPointer % IMU_BUFFER_SIZE)) {
        sampling = false;
    }
}

// Runs in main loop
void taskIMU() {
    // TODO: replace // assert (imuSamples[IMU_BUFFER_SIZE] == 0xbeef);
    /* // TODO: replace // if (imuSamples[IMU_BUFFER_SIZE] != 0xbeef) {
        debugPrintf("End of buf is %x\n", imuSamples[IMU_BUFFER_SIZE]);
    } */
    //assert (imuDumpPacket[IMU_DATA_DUMP_SIZE + OUT_PACKET_OVERHEAD] == 0xbeef);
    // assert (imuDataPointer % IMU_SAMPLE_SIZE == 0);
    assert (imuDataPointer <= IMU_BUFFER_SIZE);
    assert (!(sampling && (imuDataPointer >= IMU_BUFFER_SIZE)));
    checkDataDump();
}

void imuPacketSent() {
    digitalWrite(IMU_DATA_READY_PIN, LOW);
    if ((assert(imuPacketReady))) {
        noInterrupts();
        imuPacketChecksum = 0;
        imuPacketBodyPointer = 0;
        imuPacketReady = false;
        imuSamplesSent += IMU_DATA_DUMP_SIZE;
        interrupts();
    }
}

void enterIMU() {
    digitalWriteFast(IMU_DATA_READY_PIN, LOW);
    noInterrupts();
    imuPacketChecksum = 0;
    imuPacketReady = false;
    imuSentDataPointer = 0;
    imuDataPointer = 0;
    timeSinceLastRead = 0;
    imuPacketBodyPointer = 0;
    sampling = true;
    interrupts();
}

void leaveIMU() {
    digitalWriteFast(IMU_DATA_READY_PIN, LOW);
    noInterrupts();
    imuPacketReady = false;
    sampling = false;
    imuDataPointer = 0;
    interrupts();
}

void imuHeartbeat() {
    Serial.printf("IMU front of buffer %d, back of buffer %d, packet ready? %d, chksum %d, packet pointer %d, sampling %d, packet %d, sent %d\n", imuDataPointer, imuSentDataPointer, imuPacketReady, imuPacketChecksum, imuPacketBodyPointer, sampling, imuPacketBodyPointer, imuSamplesSent);
}
<commit_msg>Add back boundary check<commit_after>#include <main.h>
#include <pidData.h>

// Imu samples go here
// These are processed on the same main thread so hopefully no race conditions
// Indexes into imuSamples; Marks index of next data point to transmit to audacy
// If sentDataPointer == dataPointer, buffer is empty
// If dataPointer == sentDataPointer - IMU_SAMPLE_SIZE, buffer is full
volatile unsigned int imuSentDataPointer = 0;
volatile unsigned int imuDataPointer = 0; // Marks index of next place to read into
volatile unsigned int imuSamplesSent = 0;
volatile pidSample imuSamples[IMU_BUFFER_SIZE + 10]; // Add some extra space on the end in case we overflow
volatile bool sampling = false;
elapsedMicros timeSinceLastRead;

// This packet ships out directly to audacy
// This is more than we need; OUT_PACKET_OVERHEAD is measured in units of uint16_t, not pidSample
volatile expandedPidSample imuDumpPacketMemory[IMU_DATA_DUMP_SIZE + OUT_PACKET_OVERHEAD + 10];
// We skip the first few uint16 because we want the packet body to begin at imuDumpPacketMemory[1], which has a good byte offset mod 32bit.
// Assume header size is less than IMU_SAMPLE_SIZE
volatile uint32_t *imuDumpPacket = ((uint32_t *) imuDumpPacketMemory) + (6 * IMU_SAMPLE_SIZE - OUT_PACKET_BODY_BEGIN);

// Where the telemetry goes
volatile expandedPidSample *imuDumpPacketBegin = (expandedPidSample *) (imuDumpPacket + OUT_PACKET_BODY_BEGIN);
// Where the samples go
volatile expandedPidSample *imuDumpPacketBody = imuDumpPacketBegin + 0;
volatile uint16_t imuPacketChecksum = 0;
volatile unsigned int imuPacketBodyPointer = 0;
volatile bool imuPacketReady = false;

// Telemetry
volatile unsigned int imuSamplesRead = 0;
volatile unsigned int imuSamplesQueued = 0;

// Runs in main's setup()
void imuSetup() {

    assert(((unsigned int) imuDumpPacketBody) % 4 == 0);  // Check offset; Misaligned data may segfault at 0x20000000
    (void) assert(((unsigned int) imuSamples) % 4 == 0);
    debugPrintf("imuSamples location (we want this to be far from 0x2000000): %p to %p\n", imuSamples, imuSamples + IMU_BUFFER_SIZE);
    debugPrintf("imuDumpPacket location (we want this to be far from 0x2000000): memory begins %p, samples %p to %p\n", imuDumpPacketMemory, imuDumpPacket, imuDumpPacketMemory + IMU_DATA_DUMP_SIZE + OUT_PACKET_OVERHEAD);
    pinMode(IMU_DATA_READY_PIN, OUTPUT);
    for (int i = 0; i < 10; i++) {
        ((uint16_t *) &imuSamples[IMU_BUFFER_SIZE])[i] = 0xbeef;
        imuDumpPacket[IMU_DATA_DUMP_SIZE + OUT_PACKET_OVERHEAD + i] = 0xbeef;
    }
    assert (imuSamples[IMU_BUFFER_SIZE].sample.axis1 == 0xbeefbeef);
}

void writeExpandedPidSampleWithChecksum(const pidSample* in, volatile expandedPidSample* out, volatile uint16_t& pidBufferChecksum) {
    assert(sizeof(pidSample) * 2 == sizeof(expandedPidSample));
    assert(sizeof(pidSample) == 4 * 4 * 3);
    unsigned int num_uint32 = sizeof(pidSample) / 4;
    for (unsigned int i = 0; i < num_uint32; i++) {
        uint32_t num = ((uint32_t *) in)[i];
        ((uint32_t *) out)[2 * i] = num >> 16; // msb
        pidBufferChecksum += num >> 16;
        ((uint32_t *) out)[2 * i + 1] = num % (1 << 16); // lsb
        pidBufferChecksum += num % (1 << 16);
    }
}

void checkDataDump() {
    noInterrupts();
    unsigned int imuPacketBodyPointerSave = imuPacketBodyPointer;
    unsigned int imuPacketReadySave = imuPacketReady;
    if(!assert((imuPacketBodyPointerSave == IMU_DATA_DUMP_SIZE) == imuPacketReadySave)) {
        debugPrintf("packetBodyPointer %d, ready? %d\n", imuPacketBodyPointerSave, imuPacketReadySave);
    }
    if (imuPacketReady) {
        interrupts();
        return;
    }
    noInterrupts();
    if ((imuPacketBodyPointer < IMU_DATA_DUMP_SIZE) && (imuSentDataPointer % IMU_BUFFER_SIZE) != (imuDataPointer % IMU_BUFFER_SIZE)) {
        pidSample sample = imuSamples[imuSentDataPointer];
        writeExpandedPidSampleWithChecksum(&sample, &(imuDumpPacketBody[imuPacketBodyPointer]), imuPacketChecksum);
        imuPacketBodyPointer++;
        imuSentDataPointer++;
    }
    imuSentDataPointer = imuSentDataPointer % IMU_BUFFER_SIZE;
    assert(imuPacketBodyPointer <= IMU_DATA_DUMP_SIZE);
    if (imuPacketBodyPointer >= IMU_DATA_DUMP_SIZE) {
        // Prepare packet!
        noInterrupts();
        assert((sizeof(pidSample) * 8) % 16 == 0);
        imuPacketReady = true;

        digitalWriteFast(IMU_DATA_READY_PIN, HIGH);
    }

    interrupts();
}

void recordPid(const volatile pidSample& s) {
    if (!sampling) {
        return;
    }
    ((pidSample *) imuSamples)[imuDataPointer] = s;
    imuDataPointer = (imuDataPointer + 1) % IMU_BUFFER_SIZE;
    imuSamplesRead++;
    assert(imuDataPointer <= IMU_BUFFER_SIZE);

    if (((imuDataPointer + 1) % IMU_BUFFER_SIZE) == (imuSentDataPointer % IMU_BUFFER_SIZE)) {
        sampling = false;
    }
}

// Runs in main loop
void taskIMU() {
    if (!assert (imuSamples[IMU_BUFFER_SIZE].sample.axis1 == 0xbeefbeef)) {
        debugPrintf("End of buf is %x\n", imuSamples[IMU_BUFFER_SIZE].sample.axis1);
    }
    assert (imuDataPointer <= IMU_BUFFER_SIZE);
    assert (!(sampling && (imuDataPointer >= IMU_BUFFER_SIZE)));
    checkDataDump();
}

void imuPacketSent() {
    digitalWrite(IMU_DATA_READY_PIN, LOW);
    if ((assert(imuPacketReady))) {
        noInterrupts();
        imuPacketChecksum = 0;
        imuPacketBodyPointer = 0;
        imuPacketReady = false;
        imuSamplesSent += IMU_DATA_DUMP_SIZE;
        interrupts();
    }
}

void enterIMU() {
    digitalWriteFast(IMU_DATA_READY_PIN, LOW);
    noInterrupts();
    imuPacketChecksum = 0;
    imuPacketReady = false;
    imuSentDataPointer = 0;
    imuDataPointer = 0;
    timeSinceLastRead = 0;
    imuPacketBodyPointer = 0;
    sampling = true;
    interrupts();
}

void leaveIMU() {
    digitalWriteFast(IMU_DATA_READY_PIN, LOW);
    noInterrupts();
    imuPacketReady = false;
    sampling = false;
    imuDataPointer = 0;
    interrupts();
}

void imuHeartbeat() {
    Serial.printf("IMU front of buffer %d, back of buffer %d, packet ready? %d, chksum %d, packet pointer %d, sampling %d, packet %d, sent %d\n", imuDataPointer, imuSentDataPointer, imuPacketReady, imuPacketChecksum, imuPacketBodyPointer, sampling, imuPacketBodyPointer, imuSamplesSent);
}
<|endoftext|>


<commit_before>#include <fstream>
#include "HashTable.hpp"

void BFS_corners(std::ofstream *file, int end);

void BFS_edges(std::ofstream *file);

int main(int argc, char const *argv[]) {
    std::ofstream file;
    int end = -1;

    if (argc > 1) {
        end = 1 + atoi(argv[1]);
    }

    file.open("../pdbs/cPDB.txt");
    BFS_corners(&file, end);
    file.close();

    file.open("../pdbs/ePDB.txt");
    //BFS_edges(&file);
    file.close();

    return 0;
}

void BFS_corners(std::ofstream *file, int end) {
    std::queue<std::tuple<int,char,int>> queue;
    std::queue<Cube*> *succ;
    HashTable closed(1);
    bool enqueued[264539520];

    Cube* cube = new Cube;
    int info, size, level = 0, last_level = -1;
    int *corners = cube->get_corners();
    char last = cube->get_last();
    std::tuple<int,char,int> node;

    delete cube;

    for (int i = 0; i < 264539520; ++i) {
        enqueued[i] = false;
    }

    info = rank(8,corners);
    node = std::make_tuple(info, last, level);

    queue.push(node);
    enqueued[info] = true;

    while (!queue.empty()) {
        std::tie (info, last, level) = queue.front();
        queue.pop();

        cube = new Cube(info, 0, last);

        if (!closed.contains(cube)) {
            closed.insert(cube);

            if (level == end) {
                delete cube;
                break;
            }

            if (level != last_level) {
                last_level = level;
                std::cout << "LEVEL " << last_level << " | queue " << queue.size() << " | closed " << closed.size() << std::endl << std::flush;
            }

            (*file) << cube->corners_to_string() << " [" << level << "]\n";

            succ = cube->succ();
            size = succ->size();

            delete cube;

            for (int i = 0; i < size; ++i) {
                cube = succ->front();
                succ->pop();

                if (!closed.contains(cube)) {
                    corners = cube->get_corners();
                    info = rank(8, corners);
                    last = cube->get_last();
                    node = std::make_tuple(info, last, level+1);

                    if (!enqueued[info]) {
                        queue.push(node);
                        enqueued[info] = true;
                    }
                }

                delete cube;
            }

            delete succ;
        } else {
            delete cube;
        }
    }

    while (!queue.empty()) {
        std::tie (info, last, level) = queue.front();

        queue.pop();
    }
}
<commit_msg>evitando repetidos en la queue<commit_after>#include <fstream>
#include "HashTable.hpp"

void BFS_corners(std::ofstream *file, int end);

void BFS_edges(std::ofstream *file);

int main(int argc, char const *argv[]) {
    std::ofstream file;
    int end = -1;

    if (argc > 1) {
        end = 1 + atoi(argv[1]);
    }

    file.open("../pdbs/cPDB.txt");
    BFS_corners(&file, end);
    file.close();

    file.open("../pdbs/ePDB.txt");
    //BFS_edges(&file);
    file.close();

    return 0;
}

void BFS_corners(std::ofstream *file, int end) {
    std::queue<std::tuple<int,char,int>> queue;
    std::queue<Cube*> *succ;
    HashTable closed(1);
    bool *in_queue = new bool[264539520];

    Cube* cube = new Cube;
    int info, size, level = 0, last_level = -1;
    int *corners = cube->get_corners();
    char last = cube->get_last();
    std::tuple<int,char,int> node;

    delete cube;

    for (int i = 0; i < 264539520; ++i) {
        in_queue[i] = false;
    }

    std::cout << "starting\n" << std::flush;

    info = rank(8,corners);
    node = std::make_tuple(info, last, level);

    queue.push(node);
    in_queue[info] = true;

    while (!queue.empty()) {
        std::tie (info, last, level) = queue.front();
        queue.pop();

        cube = new Cube(info, 0, last);

        if (!closed.contains(cube)) {
            closed.insert(cube);

            if (level == end) {
                delete cube;
                break;
            }

            if (level != last_level) {
                last_level = level;
                std::cout << "LEVEL " << last_level << " | queue " << queue.size() << " | closed " << closed.size() << std::endl << std::flush;
            }

            (*file) << cube->corners_to_string() << " [" << level << "]\n";

            succ = cube->succ();
            size = succ->size();

            delete cube;

            for (int i = 0; i < size; ++i) {
                cube = succ->front();
                succ->pop();

                if (!closed.contains(cube)) {
                    corners = cube->get_corners();
                    info = rank(8, corners);
                    last = cube->get_last();
                    node = std::make_tuple(info, last, level+1);

                    if (!in_queue[info]) {
                        queue.push(node);
                        in_queue[info] = true;
                    }
                }

                delete cube;
            }

            delete succ;
        } else {
            delete cube;
        }
    }

    while (!queue.empty()) {
        std::tie (info, last, level) = queue.front();

        queue.pop();
    }

    delete[] in_queue;
}
<|endoftext|>


<commit_before>#ifndef _C4_TEST_HPP_
#define _C4_TEST_HPP_

#include "c4/config.hpp"
#include "c4/memory_resource.hpp"

#include <gtest/gtest.h>

#define C4_EXPECT(expr) C4_EXPECT_EQ(expr, true)

#define C4_EXPECT_NE(expr1, expr2) EXPECT_NE(expr1, expr2) << C4_PRETTY_FUNC << "\n"
#define C4_EXPECT_EQ(expr1, expr2) EXPECT_EQ(expr1, expr2) << C4_PRETTY_FUNC << "\n"
#define C4_EXPECT_LT(expr1, expr2) EXPECT_LT(expr1, expr2) << C4_PRETTY_FUNC << "\n"
#define C4_EXPECT_GT(expr1, expr2) EXPECT_GT(expr1, expr2) << C4_PRETTY_FUNC << "\n"
#define C4_EXPECT_GE(expr1, expr2) EXPECT_GE(expr1, expr2) << C4_PRETTY_FUNC << "\n"
#define C4_EXPECT_LE(expr1, expr2) EXPECT_LE(expr1, expr2) << C4_PRETTY_FUNC << "\n"

#define C4_EXPECT_STREQ(expr1, expr2) EXPECT_STREQ(expr1, expr2) << C4_PRETTY_FUNC << "\n"
#define C4_EXPECT_STRNE(expr1, expr2) EXPECT_STRNE(expr1, expr2) << C4_PRETTY_FUNC << "\n"

#define C4_EXPECT_STRCASEEQ(expr1, expr2) EXPECT_STRCASEEQ(expr1, expr2) << C4_PRETTY_FUNC << "\n"
#define C4_EXPECT_STRCASENE(expr1, expr2) EXPECT_STRCASENE(expr1, expr2) << C4_PRETTY_FUNC << "\n"

#define C4_TEST(ts, tn) TEST_F(::c4::TestFixture, ts##_##tn)

C4_BEGIN_NAMESPACE(c4)

class TestFixture : public ::testing::Test
{
protected:
    // You can remove any or all of the following functions if its body
    // is empty.

    // You can do set-up work for each test here.
    TestFixture() {}

    // You can do clean-up work that doesn't throw exceptions here.
    virtual ~TestFixture() {}

    // If the constructor and destructor are not enough for setting up
    // and cleaning up each test, you can define the following methods:

    // Code here will be called immediately after the constructor (right
    // before each test).
    virtual void SetUp() {}

    // Code here will be called immediately after each test (right
    // before the destructor).
    virtual void TearDown() {}

    // Objects declared here can be used by all tests in the test case for Foo.
};

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
struct AllocationCountsChecker : public ScopedMemoryResourceCounts
{
    AllocationCounts first;

public:

    AllocationCountsChecker()
    :
        ScopedMemoryResourceCounts(),
        first(mr.counts())
    {
    }

    AllocationCountsChecker(MemoryResource *mr_)
    :
        ScopedMemoryResourceCounts(mr_),
        first(mr.counts())
    {
    }

    void reset()
    {
        first = mr.counts();
    }

    /** check value of curr allocations and size */
    void check_curr(ssize_t expected_allocs, ssize_t expected_size) const
    {
        EXPECT_EQ(mr.counts().curr.allocs, expected_allocs);
        EXPECT_EQ(mr.counts().curr.size, expected_size);
    }
    /** check delta of curr allocations and size since construction or last reset() */
    void check_curr_delta(ssize_t expected_allocs, ssize_t expected_size) const
    {
        AllocationCounts delta = mr.counts() - first;
        EXPECT_EQ(delta.curr.allocs, expected_allocs);
        EXPECT_EQ(delta.curr.size, expected_size);
    }

    /** check value of total allocations and size */
    void check_total(ssize_t expected_allocs, ssize_t expected_size) const
    {
        EXPECT_EQ(mr.counts().total.allocs, expected_allocs);
        EXPECT_EQ(mr.counts().total.size, expected_size);
    }
    /** check delta of total allocations and size since construction or last reset() */
    void check_total_delta(ssize_t expected_allocs, ssize_t expected_size) const
    {
        AllocationCounts delta = mr.counts() - first;
        EXPECT_EQ(delta.total.allocs, expected_allocs);
        EXPECT_EQ(delta.total.size, expected_size);
    }

    /** check value of max allocations and size */
    void check_max(ssize_t expected_max_allocs, ssize_t expected_max_size) const
    {
        EXPECT_EQ(mr.counts().max.allocs, expected_max_allocs);
        EXPECT_EQ(mr.counts().max.size, expected_max_size);
    }

    /** check that since construction or the last reset():
     *    - num_allocs occcurred
     *    - totaling total_size
     *    - of which the largest is max_size */
    void check_all_delta(ssize_t num_allocs, ssize_t total_size, ssize_t max_size) const
    {
        check_curr_delta(num_allocs, total_size);
        check_total_delta(num_allocs, total_size);
        check_max(num_allocs > mr.counts().max.allocs ? num_allocs : mr.counts().max.allocs,
                  max_size   > mr.counts().max.size   ? max_size   : mr.counts().max.size);
    }
};

C4_END_NAMESPACE(c4)

#endif // _C4_TEST_HPP_
<commit_msg>adding test archetypes<commit_after>#ifndef _C4_TEST_HPP_
#define _C4_TEST_HPP_

#include "c4/config.hpp"
#include "c4/memory_resource.hpp"

#include <gtest/gtest.h>

#define C4_EXPECT(expr) C4_EXPECT_EQ(expr, true)

#define C4_EXPECT_NE(expr1, expr2) EXPECT_NE(expr1, expr2) << C4_PRETTY_FUNC << "\n"
#define C4_EXPECT_EQ(expr1, expr2) EXPECT_EQ(expr1, expr2) << C4_PRETTY_FUNC << "\n"
#define C4_EXPECT_LT(expr1, expr2) EXPECT_LT(expr1, expr2) << C4_PRETTY_FUNC << "\n"
#define C4_EXPECT_GT(expr1, expr2) EXPECT_GT(expr1, expr2) << C4_PRETTY_FUNC << "\n"
#define C4_EXPECT_GE(expr1, expr2) EXPECT_GE(expr1, expr2) << C4_PRETTY_FUNC << "\n"
#define C4_EXPECT_LE(expr1, expr2) EXPECT_LE(expr1, expr2) << C4_PRETTY_FUNC << "\n"

#define C4_EXPECT_STREQ(expr1, expr2) EXPECT_STREQ(expr1, expr2) << C4_PRETTY_FUNC << "\n"
#define C4_EXPECT_STRNE(expr1, expr2) EXPECT_STRNE(expr1, expr2) << C4_PRETTY_FUNC << "\n"

#define C4_EXPECT_STRCASEEQ(expr1, expr2) EXPECT_STRCASEEQ(expr1, expr2) << C4_PRETTY_FUNC << "\n"
#define C4_EXPECT_STRCASENE(expr1, expr2) EXPECT_STRCASENE(expr1, expr2) << C4_PRETTY_FUNC << "\n"

#define C4_TEST(ts, tn) TEST_F(::c4::TestFixture, ts##_##tn)

C4_BEGIN_NAMESPACE(c4)

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

class TestFixture : public ::testing::Test
{
protected:
    // You can remove any or all of the following functions if its body
    // is empty.

    // You can do set-up work for each test here.
    TestFixture() {}

    // You can do clean-up work that doesn't throw exceptions here.
    virtual ~TestFixture() {}

    // If the constructor and destructor are not enough for setting up
    // and cleaning up each test, you can define the following methods:

    // Code here will be called immediately after the constructor (right
    // before each test).
    virtual void SetUp() {}

    // Code here will be called immediately after each test (right
    // before the destructor).
    virtual void TearDown() {}

    // Objects declared here can be used by all tests in the test case for Foo.
};

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

C4_BEGIN_NAMESPACE(archetypes)

/** Resource owning archetype */
template< class T >
struct AtDirectResource
{
    T* resource;

};

/** base class archetype */
struct AtBase
{
    virtual ~AtBase() = default;
};
/** derived class archetype */
struct AtDerived : public AtBase
{

};

/** base class archetype */
template< class T >
struct AtInsidePtr
{
    T a;
    T b;
    T c;
    T *ptr;

    AtInsidePtr() { ptr = &b; }
    AtInsidePtr(AtInsidePtr const& that) : a(that.a), b(that.b), c(that.c), ptr(&a + (that.ptr - &that.a)) {}
    AtInsidePtr(AtInsidePtr     && that) : a(that.a), b(that.b), c(that.c), ptr(&a + (that.ptr - &that.a)) { that.ptr = nullptr; }
    AtInsidePtr& operator= (AtInsidePtr const& that) { a = (that.a); b = (that.b); c = (that.c); ptr = (&a + (that.ptr - &that.a)); }
    AtInsidePtr& operator= (AtInsidePtr     && that) { a = (that.a); b = (that.b); c = (that.c); ptr = (&a + (that.ptr - &that.a)); that.ptr = nullptr; }
    ~AtInsidePtr() { EXPECT_TRUE(ptr == &a || ptr == &b || ptr == &c); }

    void check() const
    {
        EXPECT_TRUE(ptr == &a || ptr == &b || ptr == &c);
    }
    void check(AtInsidePtr const& that) const
    {
        check();
        EXPECT_EQ(ptr - &a, that.ptr - &that.a);
    }
};

using scalars = ::testing::Types< char, wchar_t, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t, float, double >;
using containees = ::testing::Types< char, wchar_t, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t, float, double,
    AtInsidePtr<int>, AtInsidePtr<std::string>
>;

C4_END_NAMESPACE(archetypes)

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
struct AllocationCountsChecker : public ScopedMemoryResourceCounts
{
    AllocationCounts first;

public:

    AllocationCountsChecker()
    :
        ScopedMemoryResourceCounts(),
        first(mr.counts())
    {
    }

    AllocationCountsChecker(MemoryResource *mr_)
    :
        ScopedMemoryResourceCounts(mr_),
        first(mr.counts())
    {
    }

    void reset()
    {
        first = mr.counts();
    }

    /** check value of curr allocations and size */
    void check_curr(ssize_t expected_allocs, ssize_t expected_size) const
    {
        EXPECT_EQ(mr.counts().curr.allocs, expected_allocs);
        EXPECT_EQ(mr.counts().curr.size, expected_size);
    }
    /** check delta of curr allocations and size since construction or last reset() */
    void check_curr_delta(ssize_t expected_allocs, ssize_t expected_size) const
    {
        AllocationCounts delta = mr.counts() - first;
        EXPECT_EQ(delta.curr.allocs, expected_allocs);
        EXPECT_EQ(delta.curr.size, expected_size);
    }

    /** check value of total allocations and size */
    void check_total(ssize_t expected_allocs, ssize_t expected_size) const
    {
        EXPECT_EQ(mr.counts().total.allocs, expected_allocs);
        EXPECT_EQ(mr.counts().total.size, expected_size);
    }
    /** check delta of total allocations and size since construction or last reset() */
    void check_total_delta(ssize_t expected_allocs, ssize_t expected_size) const
    {
        AllocationCounts delta = mr.counts() - first;
        EXPECT_EQ(delta.total.allocs, expected_allocs);
        EXPECT_EQ(delta.total.size, expected_size);
    }

    /** check value of max allocations and size */
    void check_max(ssize_t expected_max_allocs, ssize_t expected_max_size) const
    {
        EXPECT_EQ(mr.counts().max.allocs, expected_max_allocs);
        EXPECT_EQ(mr.counts().max.size, expected_max_size);
    }

    /** check that since construction or the last reset():
     *    - num_allocs occcurred
     *    - totaling total_size
     *    - of which the largest is max_size */
    void check_all_delta(ssize_t num_allocs, ssize_t total_size, ssize_t max_size) const
    {
        check_curr_delta(num_allocs, total_size);
        check_total_delta(num_allocs, total_size);
        check_max(num_allocs > mr.counts().max.allocs ? num_allocs : mr.counts().max.allocs,
                  max_size   > mr.counts().max.size   ? max_size   : mr.counts().max.size);
    }
};

C4_END_NAMESPACE(c4)

#endif // _C4_TEST_HPP_
<|endoftext|>