<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "views/controls/button/custom_button.h"

#include "ui/base/accessibility/accessible_view_state.h"
#include "ui/base/animation/throb_animation.h"
#include "ui/base/keycodes/keyboard_codes.h"
#include "ui/gfx/screen.h"
#include "views/widget/widget.h"

namespace views {

// How long the hover animation takes if uninterrupted.
static const int kHoverFadeDurationMs = 150;

// static
const char CustomButton::kViewClassName[] = "views/CustomButton";

////////////////////////////////////////////////////////////////////////////////
// CustomButton, public:

CustomButton::~CustomButton() {
}

void CustomButton::SetState(ButtonState state) {
  if (state == state_)
    return;

  if (animate_on_state_change_ &&
      (!is_throbbing_ || !hover_animation_->is_animating())) {
    is_throbbing_ = false;
    if (state_ == BS_NORMAL && state == BS_HOT) {
      // Button is hovered from a normal state, start hover animation.
      hover_animation_->Show();
    } else if (state_ == BS_HOT && state == BS_NORMAL) {
      // Button is returning to a normal state from hover, start hover
      // fade animation.
      hover_animation_->Hide();
    } else {
      hover_animation_->Stop();
    }
  }

  state_ = state;
  StateChanged();
  SchedulePaint();
}

void CustomButton::StartThrobbing(int cycles_til_stop) {
  is_throbbing_ = true;
  hover_animation_->StartThrobbing(cycles_til_stop);
}

void CustomButton::StopThrobbing() {
  if (hover_animation_->is_animating()) {
    hover_animation_->Stop();
    SchedulePaint();
  }
}

void CustomButton::SetAnimationDuration(int duration) {
  hover_animation_->SetSlideDuration(duration);
}

bool CustomButton::IsMouseHovered() const {
  // If we haven't yet been placed in an onscreen view hierarchy, we can't be
  // hovered.
  if (!GetWidget())
    return false;

  gfx::Point cursor_pos(gfx::Screen::GetCursorScreenPoint());
  ConvertPointToView(NULL, this, &cursor_pos);
  return HitTest(cursor_pos);
}

////////////////////////////////////////////////////////////////////////////////
// CustomButton, View overrides:

void CustomButton::SetHotTracked(bool flag) {
  if (state_ != BS_DISABLED)
    SetState(flag ? BS_HOT : BS_NORMAL);

  if (flag && GetWidget()) {
    GetWidget()->NotifyAccessibilityEvent(
        this, ui::AccessibilityTypes::EVENT_FOCUS, true);
  }
}

bool CustomButton::IsHotTracked() const {
  return state_ == BS_HOT;
}

void CustomButton::OnEnabledChanged() {
  if (View::IsEnabled() ? (state_ != BS_DISABLED) : (state_ == BS_DISABLED))
    return;

  if (View::IsEnabled())
    SetState(IsMouseHovered() ? BS_HOT : BS_NORMAL);
  else
    SetState(BS_DISABLED);
}

bool CustomButton::IsEnabled() const {
  return state_ != BS_DISABLED;
}

std::string CustomButton::GetClassName() const {
  return kViewClassName;
}

bool CustomButton::OnMousePressed(const MouseEvent& event) {
  if (state_ != BS_DISABLED) {
    if (ShouldEnterPushedState(event) && HitTest(event.location()))
      SetState(BS_PUSHED);
    if (request_focus_on_press_)
      RequestFocus();
  }
  return true;
}

bool CustomButton::OnMouseDragged(const MouseEvent& event) {
  if (state_ != BS_DISABLED) {
    if (HitTest(event.location()))
      SetState(ShouldEnterPushedState(event) ? BS_PUSHED : BS_HOT);
    else
      SetState(BS_NORMAL);
  }
  return true;
}

void CustomButton::OnMouseReleased(const MouseEvent& event) {
  if (state_ == BS_DISABLED)
    return;

  if (!HitTest(event.location())) {
    SetState(BS_NORMAL);
    return;
  }

  SetState(BS_HOT);
  if (IsTriggerableEvent(event)) {
    NotifyClick(event);
    // NOTE: We may be deleted at this point (by the listener's notification
    // handler).
  }
}

void CustomButton::OnMouseCaptureLost() {
  // Starting a drag results in a MouseCaptureLost, we need to ignore it.
  if (state_ != BS_DISABLED && !InDrag())
    SetState(BS_NORMAL);
}

void CustomButton::OnMouseEntered(const MouseEvent& event) {
  if (state_ != BS_DISABLED)
    SetState(BS_HOT);
}

void CustomButton::OnMouseExited(const MouseEvent& event) {
  // Starting a drag results in a MouseExited, we need to ignore it.
  if (state_ != BS_DISABLED && !InDrag())
    SetState(BS_NORMAL);
}

void CustomButton::OnMouseMoved(const MouseEvent& event) {
  if (state_ != BS_DISABLED)
    SetState(HitTest(event.location()) ? BS_HOT : BS_NORMAL);
}

bool CustomButton::OnKeyPressed(const KeyEvent& event) {
  if (state_ == BS_DISABLED)
    return false;

  // Space sets button state to pushed. Enter clicks the button. This matches
  // the Windows native behavior of buttons, where Space clicks the button on
  // KeyRelease and Enter clicks the button on KeyPressed.
  if (event.key_code() == ui::VKEY_SPACE) {
    SetState(BS_PUSHED);
  } else if (event.key_code() == ui::VKEY_RETURN) {
    SetState(BS_NORMAL);
    NotifyClick(event);
  } else {
    return false;
  }
  return true;
}

bool CustomButton::OnKeyReleased(const KeyEvent& event) {
  if ((state_ == BS_DISABLED) || (event.key_code() != ui::VKEY_SPACE))
    return false;

  SetState(BS_NORMAL);
  NotifyClick(event);
  return true;
}

bool CustomButton::AcceleratorPressed(const Accelerator& accelerator) {
  if (!View::IsEnabled())
    return false;

  SetState(BS_NORMAL);
  KeyEvent key_event(ui::ET_KEY_RELEASED, accelerator.key_code(),
                     accelerator.modifiers());
  NotifyClick(key_event);
  return true;
}

void CustomButton::ShowContextMenu(const gfx::Point& p, bool is_mouse_gesture) {
  if (!context_menu_controller())
    return;

  // We're about to show the context menu. Showing the context menu likely means
  // we won't get a mouse exited and reset state. Reset it now to be sure.
  if (state_ != BS_DISABLED)
    SetState(BS_NORMAL);
  View::ShowContextMenu(p, is_mouse_gesture);
}

void CustomButton::OnDragDone() {
  SetState(BS_NORMAL);
}

void CustomButton::GetAccessibleState(ui::AccessibleViewState* state) {
  Button::GetAccessibleState(state);
  switch (state_) {
    case BS_HOT:
      state->state = ui::AccessibilityTypes::STATE_HOTTRACKED;
      break;
    case BS_PUSHED:
      state->state = ui::AccessibilityTypes::STATE_PRESSED;
      break;
    case BS_DISABLED:
      state->state = ui::AccessibilityTypes::STATE_UNAVAILABLE;
      break;
    case BS_NORMAL:
    case BS_COUNT:
      // No additional accessibility state set for this button state.
      break;
  }
}

////////////////////////////////////////////////////////////////////////////////
// CustomButton, ui::AnimationDelegate implementation:

void CustomButton::AnimationProgressed(const ui::Animation* animation) {
  SchedulePaint();
}

////////////////////////////////////////////////////////////////////////////////
// CustomButton, protected:

CustomButton::CustomButton(ButtonListener* listener)
    : Button(listener),
      state_(BS_NORMAL),
      animate_on_state_change_(true),
      is_throbbing_(false),
      triggerable_event_flags_(ui::EF_LEFT_BUTTON_DOWN),
      request_focus_on_press_(true) {
  hover_animation_.reset(new ui::ThrobAnimation(this));
  hover_animation_->SetSlideDuration(kHoverFadeDurationMs);
}

void CustomButton::StateChanged() {
}

bool CustomButton::IsTriggerableEvent(const MouseEvent& event) {
  return (triggerable_event_flags_ & event.flags()) != 0;
}

bool CustomButton::ShouldEnterPushedState(const MouseEvent& event) {
  return IsTriggerableEvent(event);
}

////////////////////////////////////////////////////////////////////////////////
// CustomButton, View overrides (protected):

void CustomButton::ViewHierarchyChanged(bool is_add, View *parent,
                                        View *child) {
  if (!is_add && state_ != BS_DISABLED)
    SetState(BS_NORMAL);
}

bool CustomButton::IsFocusable() const {
  return (state_ != BS_DISABLED) && View::IsFocusable();
}

void CustomButton::OnBlur() {
  if (IsHotTracked())
    SetState(BS_NORMAL);
}

}  // namespace views
<commit_msg>Fix painting issue with maximize button in aura.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "views/controls/button/custom_button.h"

#include "ui/base/accessibility/accessible_view_state.h"
#include "ui/base/animation/throb_animation.h"
#include "ui/base/keycodes/keyboard_codes.h"
#include "ui/gfx/screen.h"
#include "views/widget/widget.h"

namespace views {

// How long the hover animation takes if uninterrupted.
static const int kHoverFadeDurationMs = 150;

// static
const char CustomButton::kViewClassName[] = "views/CustomButton";

////////////////////////////////////////////////////////////////////////////////
// CustomButton, public:

CustomButton::~CustomButton() {
}

void CustomButton::SetState(ButtonState state) {
  if (state == state_)
    return;

  if (animate_on_state_change_ &&
      (!is_throbbing_ || !hover_animation_->is_animating())) {
    is_throbbing_ = false;
    if (state_ == BS_NORMAL && state == BS_HOT) {
      // Button is hovered from a normal state, start hover animation.
      hover_animation_->Show();
    } else if ((state_ == BS_HOT || state_ == BS_PUSHED)
          && state == BS_NORMAL) {
      // Button is returning to a normal state from hover, start hover
      // fade animation.
      hover_animation_->Hide();
    } else {
      hover_animation_->Stop();
    }
  }

  state_ = state;
  StateChanged();
  SchedulePaint();
}

void CustomButton::StartThrobbing(int cycles_til_stop) {
  is_throbbing_ = true;
  hover_animation_->StartThrobbing(cycles_til_stop);
}

void CustomButton::StopThrobbing() {
  if (hover_animation_->is_animating()) {
    hover_animation_->Stop();
    SchedulePaint();
  }
}

void CustomButton::SetAnimationDuration(int duration) {
  hover_animation_->SetSlideDuration(duration);
}

bool CustomButton::IsMouseHovered() const {
  // If we haven't yet been placed in an onscreen view hierarchy, we can't be
  // hovered.
  if (!GetWidget())
    return false;

  gfx::Point cursor_pos(gfx::Screen::GetCursorScreenPoint());
  ConvertPointToView(NULL, this, &cursor_pos);
  return HitTest(cursor_pos);
}

////////////////////////////////////////////////////////////////////////////////
// CustomButton, View overrides:

void CustomButton::SetHotTracked(bool flag) {
  if (state_ != BS_DISABLED)
    SetState(flag ? BS_HOT : BS_NORMAL);

  if (flag && GetWidget()) {
    GetWidget()->NotifyAccessibilityEvent(
        this, ui::AccessibilityTypes::EVENT_FOCUS, true);
  }
}

bool CustomButton::IsHotTracked() const {
  return state_ == BS_HOT;
}

void CustomButton::OnEnabledChanged() {
  if (View::IsEnabled() ? (state_ != BS_DISABLED) : (state_ == BS_DISABLED))
    return;

  if (View::IsEnabled())
    SetState(IsMouseHovered() ? BS_HOT : BS_NORMAL);
  else
    SetState(BS_DISABLED);
}

bool CustomButton::IsEnabled() const {
  return state_ != BS_DISABLED;
}

std::string CustomButton::GetClassName() const {
  return kViewClassName;
}

bool CustomButton::OnMousePressed(const MouseEvent& event) {
  if (state_ != BS_DISABLED) {
    if (ShouldEnterPushedState(event) && HitTest(event.location()))
      SetState(BS_PUSHED);
    if (request_focus_on_press_)
      RequestFocus();
  }
  return true;
}

bool CustomButton::OnMouseDragged(const MouseEvent& event) {
  if (state_ != BS_DISABLED) {
    if (HitTest(event.location()))
      SetState(ShouldEnterPushedState(event) ? BS_PUSHED : BS_HOT);
    else
      SetState(BS_NORMAL);
  }
  return true;
}

void CustomButton::OnMouseReleased(const MouseEvent& event) {
  if (state_ == BS_DISABLED)
    return;

  if (!HitTest(event.location())) {
    SetState(BS_NORMAL);
    return;
  }

  SetState(BS_HOT);
  if (IsTriggerableEvent(event)) {
    NotifyClick(event);
    // NOTE: We may be deleted at this point (by the listener's notification
    // handler).
  }
}

void CustomButton::OnMouseCaptureLost() {
  // Starting a drag results in a MouseCaptureLost, we need to ignore it.
  if (state_ != BS_DISABLED && !InDrag())
    SetState(BS_NORMAL);
}

void CustomButton::OnMouseEntered(const MouseEvent& event) {
  if (state_ != BS_DISABLED)
    SetState(BS_HOT);
}

void CustomButton::OnMouseExited(const MouseEvent& event) {
  // Starting a drag results in a MouseExited, we need to ignore it.
  if (state_ != BS_DISABLED && !InDrag())
    SetState(BS_NORMAL);
}

void CustomButton::OnMouseMoved(const MouseEvent& event) {
  if (state_ != BS_DISABLED)
    SetState(HitTest(event.location()) ? BS_HOT : BS_NORMAL);
}

bool CustomButton::OnKeyPressed(const KeyEvent& event) {
  if (state_ == BS_DISABLED)
    return false;

  // Space sets button state to pushed. Enter clicks the button. This matches
  // the Windows native behavior of buttons, where Space clicks the button on
  // KeyRelease and Enter clicks the button on KeyPressed.
  if (event.key_code() == ui::VKEY_SPACE) {
    SetState(BS_PUSHED);
  } else if (event.key_code() == ui::VKEY_RETURN) {
    SetState(BS_NORMAL);
    NotifyClick(event);
  } else {
    return false;
  }
  return true;
}

bool CustomButton::OnKeyReleased(const KeyEvent& event) {
  if ((state_ == BS_DISABLED) || (event.key_code() != ui::VKEY_SPACE))
    return false;

  SetState(BS_NORMAL);
  NotifyClick(event);
  return true;
}

bool CustomButton::AcceleratorPressed(const Accelerator& accelerator) {
  if (!View::IsEnabled())
    return false;

  SetState(BS_NORMAL);
  KeyEvent key_event(ui::ET_KEY_RELEASED, accelerator.key_code(),
                     accelerator.modifiers());
  NotifyClick(key_event);
  return true;
}

void CustomButton::ShowContextMenu(const gfx::Point& p, bool is_mouse_gesture) {
  if (!context_menu_controller())
    return;

  // We're about to show the context menu. Showing the context menu likely means
  // we won't get a mouse exited and reset state. Reset it now to be sure.
  if (state_ != BS_DISABLED)
    SetState(BS_NORMAL);
  View::ShowContextMenu(p, is_mouse_gesture);
}

void CustomButton::OnDragDone() {
  SetState(BS_NORMAL);
}

void CustomButton::GetAccessibleState(ui::AccessibleViewState* state) {
  Button::GetAccessibleState(state);
  switch (state_) {
    case BS_HOT:
      state->state = ui::AccessibilityTypes::STATE_HOTTRACKED;
      break;
    case BS_PUSHED:
      state->state = ui::AccessibilityTypes::STATE_PRESSED;
      break;
    case BS_DISABLED:
      state->state = ui::AccessibilityTypes::STATE_UNAVAILABLE;
      break;
    case BS_NORMAL:
    case BS_COUNT:
      // No additional accessibility state set for this button state.
      break;
  }
}

////////////////////////////////////////////////////////////////////////////////
// CustomButton, ui::AnimationDelegate implementation:

void CustomButton::AnimationProgressed(const ui::Animation* animation) {
  SchedulePaint();
}

////////////////////////////////////////////////////////////////////////////////
// CustomButton, protected:

CustomButton::CustomButton(ButtonListener* listener)
    : Button(listener),
      state_(BS_NORMAL),
      animate_on_state_change_(true),
      is_throbbing_(false),
      triggerable_event_flags_(ui::EF_LEFT_BUTTON_DOWN),
      request_focus_on_press_(true) {
  hover_animation_.reset(new ui::ThrobAnimation(this));
  hover_animation_->SetSlideDuration(kHoverFadeDurationMs);
}

void CustomButton::StateChanged() {
}

bool CustomButton::IsTriggerableEvent(const MouseEvent& event) {
  return (triggerable_event_flags_ & event.flags()) != 0;
}

bool CustomButton::ShouldEnterPushedState(const MouseEvent& event) {
  return IsTriggerableEvent(event);
}

////////////////////////////////////////////////////////////////////////////////
// CustomButton, View overrides (protected):

void CustomButton::ViewHierarchyChanged(bool is_add, View *parent,
                                        View *child) {
  if (!is_add && state_ != BS_DISABLED)
    SetState(BS_NORMAL);
}

bool CustomButton::IsFocusable() const {
  return (state_ != BS_DISABLED) && View::IsFocusable();
}

void CustomButton::OnBlur() {
  if (IsHotTracked())
    SetState(BS_NORMAL);
}

}  // namespace views
<|endoftext|>


<commit_before>// Copyright (c) 2016, Joseph Mirabel
// Authors: Joseph Mirabel (joseph.mirabel@laas.fr)
//
// This file is part of hpp-core.
// hpp-core is free software: you can redistribute it
// and/or modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation, either version
// 3 of the License, or (at your option) any later version.
//
// hpp-core is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Lesser Public License for more details.  You should have
// received a copy of the GNU Lesser General Public License along with
// hpp-core. If not, see <http://www.gnu.org/licenses/>.

#include <hpp/core/steering-method/reeds-shepp.hh>

#include <pinocchio/multibody/joint/joint.hpp>

#include <hpp/pinocchio/device.hh>
#include <hpp/pinocchio/joint.hh>

#include <hpp/core/problem.hh>
#include <hpp/core/reeds-shepp-path.hh>

namespace hpp {
  namespace core {
    namespace steeringMethod {
      PathPtr_t ReedsShepp::impl_compute (ConfigurationIn_t q1,
          ConfigurationIn_t q2) const
      {
        ReedsSheppPathPtr_t path =
          ReedsSheppPath::create (device_.lock (), q1, q2,
              rho_ , xy_, rz_, constraints ());
        path->setWheelJoints (turningJoint_, wheels_);
        return path;
      }

      void ReedsShepp::computeRadius ()
      {
        rho_ = 1;
        if (wheels_.empty()) return;
        rho_ = 0;
        for (std::vector<JointPtr_t>::const_iterator _wheels = wheels_.begin();
            _wheels != wheels_.end(); ++_wheels) {
          rho_ = std::max (rho_, computeAngle(*_wheels));
        }
        hppDout (info, "rho_ = " << rho_);
      }

      ReedsShepp::ReedsShepp (const ProblemPtr_t& problem) :
        SteeringMethod (problem), device_ (problem->robot ()),
        rho_ (1.), xy_ (0), rz_(2), weak_ ()
      {
        DevicePtr_t d (device_.lock());
        std::string sn = d->rootJoint()->jointModel().shortname();
        //TODO shortname() == se3::JointModelPlanar::classname();
        if (sn == "planar") {
          turningJoint_ = d->rootJoint();
        } else if (sn == "translation" && d->rootJoint()->configSize() == 2) {
          std::string sn2 = d->getJointAtConfigRank(2)->jointModel().shortname();
          if (sn2 == "revoluteunbounded")
            turningJoint_ = d->getJointAtConfigRank(2);
          else
            throw std::runtime_error ("root joint should be of type "
                "se3::JointModelPlanar or JointModelTranslation + JointModelRevolute");
        } else {
          throw std::runtime_error ("root joint should be of type "
              "se3::JointModelPlanar or JointModelTranslation + JointModelRevolute");
        }

        guessWheels();
        computeRadius();
      }

      ReedsShepp::ReedsShepp (const ProblemPtr_t& problem,
          const value_type turningRadius,
          JointPtr_t xyJoint, JointPtr_t rzJoint,
          std::vector <JointPtr_t> wheels) :
        SteeringMethod (problem), device_ (problem->robot ()),
        rho_ (turningRadius),
        turningJoint_ (rzJoint),
        xy_ (xyJoint->rankInConfiguration()),
        rz_ (rzJoint->rankInConfiguration()),
        wheels_ (wheels), weak_ ()
      {
      }

      /// Copy constructor
      ReedsShepp::ReedsShepp (const ReedsShepp& other) :
        SteeringMethod (other), device_ (other.device_),
        rho_ (other.rho_)
      {
      }

      inline value_type ReedsShepp::computeAngle(const JointPtr_t wheel) const
      {
        // Compute wheel position in joint RZ
        const Transform3f zt (turningJoint_->currentTransformation ());
        const Transform3f wt (zt.actInv (wheel->currentTransformation ()));
        const vector3_t& wp (wt.translation ());

        // Assume the non turning wheels are on the plane z = 0 of
        // in joint rz.
        const value_type alpha = (wheel->upperBound(0) - wheel->lowerBound(0)) / 2;
        const value_type delta = std::abs(wp[1]);
        const value_type beta = std::abs(wp[2]);

        return delta + beta / std::tan(alpha);
      }

      inline void ReedsShepp::guessWheels()
      {
        wheels_.clear();
        for (std::size_t i = 0; i < turningJoint_->numberChildJoints(); ++i) {
          JointPtr_t j = turningJoint_->childJoint(i);
          if (j->configSize() != 1) continue;
          if (!j->isBounded(0))     continue;
          if (j->name().find("wheel") == std::string::npos) continue;
          wheels_.push_back(j);
        }
      }
    } // namespace steeringMethod
  } // namespace core
} // namespace hpp
<commit_msg>Fix steeringMethod::ReedsShepp<commit_after>// Copyright (c) 2016, Joseph Mirabel
// Authors: Joseph Mirabel (joseph.mirabel@laas.fr)
//
// This file is part of hpp-core.
// hpp-core is free software: you can redistribute it
// and/or modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation, either version
// 3 of the License, or (at your option) any later version.
//
// hpp-core is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Lesser Public License for more details.  You should have
// received a copy of the GNU Lesser General Public License along with
// hpp-core. If not, see <http://www.gnu.org/licenses/>.

#include <hpp/core/steering-method/reeds-shepp.hh>

#include <pinocchio/multibody/joint/joint.hpp>

#include <hpp/pinocchio/device.hh>
#include <hpp/pinocchio/joint.hh>

#include <hpp/core/problem.hh>
#include <hpp/core/reeds-shepp-path.hh>

namespace hpp {
  namespace core {
    namespace steeringMethod {
      PathPtr_t ReedsShepp::impl_compute (ConfigurationIn_t q1,
          ConfigurationIn_t q2) const
      {
        ReedsSheppPathPtr_t path =
          ReedsSheppPath::create (device_.lock (), q1, q2,
              rho_ , xy_, rz_, constraints ());
        path->setWheelJoints (turningJoint_, wheels_);
        return path;
      }

      void ReedsShepp::computeRadius ()
      {
        rho_ = 1;
        if (wheels_.empty()) return;
        rho_ = 0;
        for (std::vector<JointPtr_t>::const_iterator _wheels = wheels_.begin();
            _wheels != wheels_.end(); ++_wheels) {
          rho_ = std::max (rho_, computeAngle(*_wheels));
        }
        hppDout (info, "rho_ = " << rho_);
      }

      ReedsShepp::ReedsShepp (const ProblemPtr_t& problem) :
        SteeringMethod (problem), device_ (problem->robot ()),
        rho_ (1.), xy_ (0), rz_(2), weak_ ()
      {
        DevicePtr_t d (device_.lock());
        std::string sn = d->rootJoint()->jointModel().shortname();
        if (sn == se3::JointModelPlanar::classname()) {
          turningJoint_ = d->rootJoint();
        // } else if (sn == se3::JointModelPlanar::classname() && d->rootJoint()->configSize() == 2) {
          // std::string sn2 = d->getJointAtConfigRank(2)->jointModel().shortname();
          // if (sn2 == "revoluteunbounded")
            // turningJoint_ = d->getJointAtConfigRank(2);
          // else
            // throw std::runtime_error ("root joint should be of type "
                // "se3::JointModelPlanar or JointModelTranslation + JointModelRevolute");
        } else {
          throw std::runtime_error ("root joint should be of type "
              "se3::JointModelPlanar" /*" or JointModelTranslation + JointModelRevolute"*/);
        }

        guessWheels();
        computeRadius();
      }

      ReedsShepp::ReedsShepp (const ProblemPtr_t& problem,
          const value_type turningRadius,
          JointPtr_t xyJoint, JointPtr_t rzJoint,
          std::vector <JointPtr_t> wheels) :
        SteeringMethod (problem), device_ (problem->robot ()),
        rho_ (turningRadius),
        turningJoint_ (rzJoint),
        xy_ (xyJoint->rankInConfiguration()),
        rz_ (rzJoint->rankInConfiguration()),
        wheels_ (wheels), weak_ ()
      {
      }

      /// Copy constructor
      ReedsShepp::ReedsShepp (const ReedsShepp& other) :
        SteeringMethod (other), device_ (other.device_),
        rho_ (other.rho_)
      {
      }

      inline value_type ReedsShepp::computeAngle(const JointPtr_t wheel) const
      {
        // Compute wheel position in joint RZ
        const Transform3f zt (turningJoint_->currentTransformation ());
        const Transform3f wt (zt.actInv (wheel->currentTransformation ()));
        const vector3_t& wp (wt.translation ());

        // Assume the non turning wheels are on the plane z = 0 of
        // in joint rz.
        const value_type alpha = (wheel->upperBound(0) - wheel->lowerBound(0)) / 2;
        const value_type delta = std::abs(wp[1]);
        const value_type beta = std::abs(wp[2]);

        return delta + beta / std::tan(alpha);
      }

      inline void ReedsShepp::guessWheels()
      {
        wheels_.clear();
        for (std::size_t i = 0; i < turningJoint_->numberChildJoints(); ++i) {
          JointPtr_t j = turningJoint_->childJoint(i);
          if (j->configSize() != 1) continue;
          if (!j->isBounded(0))     continue;
          if (j->name().find("wheel") == std::string::npos) continue;
          wheels_.push_back(j);
        }
      }
    } // namespace steeringMethod
  } // namespace core
} // namespace hpp
<|endoftext|>


<commit_before>/////////////////////////////////////////////////////////////////////////////
//
// BSD 3-Clause License
//
// Copyright (c) 2019, The Regents of the University of California
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// * Neither the name of the copyright holder nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////////

#include "stt/SteinerTreeBuilder.h"
#include "stt/flute.h"
#include "stt/pdrev.h"

#include <map>
#include <vector>

#include "ord/OpenRoad.hh"
#include "opendb/db.h"

namespace stt{

SteinerTreeBuilder::SteinerTreeBuilder() :
  alpha_(0.3),
  min_fanout_alpha_({0, -1}),
  min_hpwl_alpha_({0, -1}),
  logger_(nullptr),
  db_(nullptr)
{
}

void SteinerTreeBuilder::init(odb::dbDatabase* db, Logger* logger)
{
  db_ = db;
  logger_ = logger;
}

Tree SteinerTreeBuilder::makeSteinerTree(std::vector<int>& x,
                                         std::vector<int>& y,
                                         int drvr_index)
{
  Tree tree = makeTree(x, y, drvr_index, alpha_);

  return tree;
}

Tree SteinerTreeBuilder::makeSteinerTree(odb::dbNet* net,
                                         std::vector<int>& x,
                                         std::vector<int>& y,
                                         int drvr_index)
{
  float net_alpha = alpha_;
  int min_fanout = min_fanout_alpha_.first;
  int min_hpwl = min_hpwl_alpha_.first;

  if (net_alpha_map_.find(net) != net_alpha_map_.end()) {
    net_alpha = net_alpha_map_[net];
  } else if (min_hpwl > 0) {
    if (computeHPWL(net) >= min_hpwl) {
      net_alpha = min_hpwl_alpha_.second;
    }
  } else if (min_fanout > 0) {
    if (net->getTermCount()-1 >= min_fanout) {
      net_alpha = min_fanout_alpha_.second;
    }
  }

  Tree tree = makeTree(x, y, drvr_index, net_alpha);

  return tree;
}

Tree SteinerTreeBuilder::makeSteinerTree(const std::vector<int>& x,
                                         const std::vector<int>& y,
                                         const std::vector<int>& s,
                                         int accuracy)
{
  Tree tree = flt::flutes(x, y, s, accuracy);
  return tree;
}

void SteinerTreeBuilder::setAlpha(float alpha)
{
  alpha_ = alpha;
}

float SteinerTreeBuilder::getAlpha(const odb::dbNet* net) const
{
  float net_alpha = net_alpha_map_.find(net) != net_alpha_map_.end() ?
                    net_alpha_map_.at(net) : alpha_;
  return net_alpha;
}

// This checks whether the tree has the property that no two
// non-adjacent edges have intersecting bounding boxes.  If
// they do it is a failure as embedding those egdes may cause
// overlap between them.
bool SteinerTreeBuilder::checkTree(const Tree& tree) const
{
  // Such high fanout nets are going to get buffered so
  // we don't need to worry about them.
  if (tree.deg > 100) {
    return true;
  }

  std::vector<odb::Rect> rects;
  for (int i = 0; i < tree.branchCount(); ++i) {
    const Branch& branch = tree.branch[i];
    const int x1 = branch.x;
    const int y1 = branch.y;
    const Branch& neighbor = tree.branch[branch.n];
    const int x2 = neighbor.x;
    const int y2 = neighbor.y;
    rects.emplace_back(x1, y1, x2, y2);
  }
  for (auto i = 0; i < rects.size(); ++i) {
    for (auto j = i + 1; j < rects.size(); ++j) {
      const Branch& b1 = tree.branch[i];
      const Branch& b2 = tree.branch[j];
      const odb::Rect& r1 = rects[i];
      const odb::Rect& r2 = rects[j];
      if (r1.intersects(r2) && b1.n != j && b2.n != i && b1.n != b2.n) {
        debugPrint(logger_, utl::STT, "check", 1,
                   "check failed ({}, {}) ({}, {}) [{}, {}] vs ({}, {}) ({}, {}) [{}, {}] degree={}",
                      r1.xMin(), r1.yMin(), r1.xMax(), r1.yMax(),
                      i, b1.n,
                      r2.xMin(), r2.yMin(), r2.xMax(), r2.yMax(),
                      j, b2.n, tree.deg);
        return false;
      }
    }
  }

  return true;
}

void SteinerTreeBuilder::setNetAlpha(const odb::dbNet* net, float alpha)
{
  net_alpha_map_[net] = alpha;
}
void SteinerTreeBuilder::setMinFanoutAlpha(int min_fanout, float alpha)
{
  min_fanout_alpha_ = {min_fanout, alpha};
}
void SteinerTreeBuilder::setMinHPWLAlpha(int min_hpwl, float alpha)
{
  min_hpwl_alpha_ = {min_hpwl, alpha};
}

Tree SteinerTreeBuilder::makeTree(std::vector<int>& x,
                                  std::vector<int>& y,
                                  int drvr_index,
                                  float alpha)
{
  Tree tree;

  if (alpha > 0.0) {
    tree = pdr::primDijkstra(x, y, drvr_index, alpha, logger_);

    if (checkTree(tree)) {
      return tree;
    }

    // Try a smaller alpha if possible
    if (alpha > 0.1) {
      tree = pdr::primDijkstra(x, y, drvr_index, alpha - 0.1, logger_);
      if (checkTree(tree)) {
        return tree;
      }
    }

    // Give up and use flute
    return tree = flt::flute(x, y, flute_accuracy);
  } else {
    return flt::flute(x, y, flute_accuracy);
  }
}

int SteinerTreeBuilder::computeHPWL(odb::dbNet* net)
{
  int min_x = std::numeric_limits<int>::max();
  int min_y = std::numeric_limits<int>::max();
  int max_x = std::numeric_limits<int>::min();
  int max_y = std::numeric_limits<int>::min();

  for (odb::dbITerm* iterm : net->getITerms()) {
    odb::dbPlacementStatus status = iterm->getInst()->getPlacementStatus();
    if (status != odb::dbPlacementStatus::NONE &&
        status != odb::dbPlacementStatus::UNPLACED) {
      int x, y;
      iterm->getAvgXY(&x, &y);
      min_x = std::min(min_x, x);
      max_x = std::max(max_x, x);
      min_y = std::min(min_y, y);
      max_y = std::max(max_y, y);
    } else {
      logger_->error(utl::STT, 4, "Net {} is connected to unplaced instance {}.",
                     net->getName(),
                     iterm->getInst()->getName());
    }
  }

  for (odb::dbBTerm* bterm : net->getBTerms()) {
    if (bterm->getFirstPinPlacementStatus() != odb::dbPlacementStatus::NONE ||
        bterm->getFirstPinPlacementStatus() != odb::dbPlacementStatus::UNPLACED) {
      int x, y;
      bterm->getFirstPinLocation(x, y);
      min_x = std::min(min_x, x);
      max_x = std::max(max_x, x);
      min_y = std::min(min_y, y);
      max_y = std::max(max_y, y);
    } else {
      logger_->error(utl::STT, 5, "Net {} is connected to unplaced pin {}.",
                     net->getName(),
                     bterm->getName());
    }
  }

  int hpwl = (max_x - min_x) + (max_y - min_y);

  return hpwl;
}

void Tree::printTree(utl::Logger* logger)
{
  if (deg > 1) {
    for (int i = 0; i < deg; i++)
      logger->report(" {:2d}:  x={:4g}  y={:4g}  e={}",
                     i, (float)branch[i].x, (float)branch[i].y, branch[i].n);
    for (int i = deg; i < 2 * deg - 2; i++)
      logger->report("s{:2d}:  x={:4g}  y={:4g}  e={}",
                     i, (float)branch[i].x, (float)branch[i].y, branch[i].n);
    logger->report("");
  }
}

}
<commit_msg>stt: minor refactor<commit_after>/////////////////////////////////////////////////////////////////////////////
//
// BSD 3-Clause License
//
// Copyright (c) 2019, The Regents of the University of California
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// * Neither the name of the copyright holder nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////////

#include "stt/SteinerTreeBuilder.h"
#include "stt/flute.h"
#include "stt/pdrev.h"

#include <map>
#include <vector>

#include "ord/OpenRoad.hh"
#include "opendb/db.h"

namespace stt{

SteinerTreeBuilder::SteinerTreeBuilder() :
  alpha_(0.3),
  min_fanout_alpha_({0, -1}),
  min_hpwl_alpha_({0, -1}),
  logger_(nullptr),
  db_(nullptr)
{
}

void SteinerTreeBuilder::init(odb::dbDatabase* db, Logger* logger)
{
  db_ = db;
  logger_ = logger;
}

Tree SteinerTreeBuilder::makeSteinerTree(std::vector<int>& x,
                                         std::vector<int>& y,
                                         int drvr_index)
{
  Tree tree = makeTree(x, y, drvr_index, alpha_);

  return tree;
}

Tree SteinerTreeBuilder::makeSteinerTree(odb::dbNet* net,
                                         std::vector<int>& x,
                                         std::vector<int>& y,
                                         int drvr_index)
{
  float net_alpha = alpha_;
  int min_fanout = min_fanout_alpha_.first;
  int min_hpwl = min_hpwl_alpha_.first;

  if (net_alpha_map_.find(net) != net_alpha_map_.end()) {
    net_alpha = net_alpha_map_[net];
  } else if (min_hpwl > 0) {
    if (computeHPWL(net) >= min_hpwl) {
      net_alpha = min_hpwl_alpha_.second;
    }
  } else if (min_fanout > 0) {
    if (net->getTermCount()-1 >= min_fanout) {
      net_alpha = min_fanout_alpha_.second;
    }
  }

  Tree tree = makeTree(x, y, drvr_index, net_alpha);

  return tree;
}

Tree SteinerTreeBuilder::makeSteinerTree(const std::vector<int>& x,
                                         const std::vector<int>& y,
                                         const std::vector<int>& s,
                                         int accuracy)
{
  Tree tree = flt::flutes(x, y, s, accuracy);
  return tree;
}

void SteinerTreeBuilder::setAlpha(float alpha)
{
  alpha_ = alpha;
}

float SteinerTreeBuilder::getAlpha(const odb::dbNet* net) const
{
  float net_alpha = net_alpha_map_.find(net) != net_alpha_map_.end() ?
                    net_alpha_map_.at(net) : alpha_;
  return net_alpha;
}

// This checks whether the tree has the property that no two
// non-adjacent edges have intersecting bounding boxes.  If
// they do it is a failure as embedding those egdes may cause
// overlap between them.
bool SteinerTreeBuilder::checkTree(const Tree& tree) const
{
  // Such high fanout nets are going to get buffered so
  // we don't need to worry about them.
  if (tree.deg > 100) {
    return true;
  }

  std::vector<odb::Rect> rects;
  for (int i = 0; i < tree.branchCount(); ++i) {
    const Branch& branch = tree.branch[i];
    const int x1 = branch.x;
    const int y1 = branch.y;
    const Branch& neighbor = tree.branch[branch.n];
    const int x2 = neighbor.x;
    const int y2 = neighbor.y;
    rects.emplace_back(x1, y1, x2, y2);
  }
  for (auto i = 0; i < rects.size(); ++i) {
    for (auto j = i + 1; j < rects.size(); ++j) {
      const Branch& b1 = tree.branch[i];
      const Branch& b2 = tree.branch[j];
      const odb::Rect& r1 = rects[i];
      const odb::Rect& r2 = rects[j];
      if (r1.intersects(r2) && b1.n != j && b2.n != i && b1.n != b2.n) {
        debugPrint(logger_, utl::STT, "check", 1,
                   "check failed ({}, {}) ({}, {}) [{}, {}] vs ({}, {}) ({}, {}) [{}, {}] degree={}",
                      r1.xMin(), r1.yMin(), r1.xMax(), r1.yMax(),
                      i, b1.n,
                      r2.xMin(), r2.yMin(), r2.xMax(), r2.yMax(),
                      j, b2.n, tree.deg);
        return false;
      }
    }
  }

  return true;
}

void SteinerTreeBuilder::setNetAlpha(const odb::dbNet* net, float alpha)
{
  net_alpha_map_[net] = alpha;
}
void SteinerTreeBuilder::setMinFanoutAlpha(int min_fanout, float alpha)
{
  min_fanout_alpha_ = {min_fanout, alpha};
}
void SteinerTreeBuilder::setMinHPWLAlpha(int min_hpwl, float alpha)
{
  min_hpwl_alpha_ = {min_hpwl, alpha};
}

Tree SteinerTreeBuilder::makeTree(std::vector<int>& x,
                                  std::vector<int>& y,
                                  int drvr_index,
                                  float alpha)
{
  Tree tree;

  if (alpha > 0.0) {
    tree = pdr::primDijkstra(x, y, drvr_index, alpha, logger_);

    if (checkTree(tree)) {
      return tree;
    }

    // Try a smaller alpha if possible
    if (alpha > 0.1) {
      tree = pdr::primDijkstra(x, y, drvr_index, alpha - 0.1, logger_);
      if (checkTree(tree)) {
        return tree;
      }
    }

    // Give up and use flute
  }

  return flt::flute(x, y, flute_accuracy);
}

int SteinerTreeBuilder::computeHPWL(odb::dbNet* net)
{
  int min_x = std::numeric_limits<int>::max();
  int min_y = std::numeric_limits<int>::max();
  int max_x = std::numeric_limits<int>::min();
  int max_y = std::numeric_limits<int>::min();

  for (odb::dbITerm* iterm : net->getITerms()) {
    odb::dbPlacementStatus status = iterm->getInst()->getPlacementStatus();
    if (status != odb::dbPlacementStatus::NONE &&
        status != odb::dbPlacementStatus::UNPLACED) {
      int x, y;
      iterm->getAvgXY(&x, &y);
      min_x = std::min(min_x, x);
      max_x = std::max(max_x, x);
      min_y = std::min(min_y, y);
      max_y = std::max(max_y, y);
    } else {
      logger_->error(utl::STT, 4, "Net {} is connected to unplaced instance {}.",
                     net->getName(),
                     iterm->getInst()->getName());
    }
  }

  for (odb::dbBTerm* bterm : net->getBTerms()) {
    if (bterm->getFirstPinPlacementStatus() != odb::dbPlacementStatus::NONE ||
        bterm->getFirstPinPlacementStatus() != odb::dbPlacementStatus::UNPLACED) {
      int x, y;
      bterm->getFirstPinLocation(x, y);
      min_x = std::min(min_x, x);
      max_x = std::max(max_x, x);
      min_y = std::min(min_y, y);
      max_y = std::max(max_y, y);
    } else {
      logger_->error(utl::STT, 5, "Net {} is connected to unplaced pin {}.",
                     net->getName(),
                     bterm->getName());
    }
  }

  int hpwl = (max_x - min_x) + (max_y - min_y);

  return hpwl;
}

void Tree::printTree(utl::Logger* logger)
{
  if (deg > 1) {
    for (int i = 0; i < deg; i++)
      logger->report(" {:2d}:  x={:4g}  y={:4g}  e={}",
                     i, (float)branch[i].x, (float)branch[i].y, branch[i].n);
    for (int i = deg; i < 2 * deg - 2; i++)
      logger->report("s{:2d}:  x={:4g}  y={:4g}  e={}",
                     i, (float)branch[i].x, (float)branch[i].y, branch[i].n);
    logger->report("");
  }
}

}
<|endoftext|>


<commit_before>/////////////////////////////////////////////////////////////////////////////
//
// BSD 3-Clause License
//
// Copyright (c) 2019, The Regents of the University of California
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// * Neither the name of the copyright holder nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////////

#include "stt/SteinerTreeBuilder.h"

#include <map>
#include <vector>

#include "ord/OpenRoad.hh"
#include "opendb/db.h"

namespace stt{

SteinerTreeBuilder::SteinerTreeBuilder() :
  alpha_(0.3),
  min_fanout_alpha_({0, -1}),
  min_hpwl_alpha_({0, -1}),
  logger_(nullptr),
  db_(nullptr)
{
}

void SteinerTreeBuilder::init(odb::dbDatabase* db, Logger* logger)
{
  db_ = db;
  logger_ = logger;
}

Tree SteinerTreeBuilder::makeSteinerTree(std::vector<int>& x,
                                         std::vector<int>& y,
                                         int drvr_index)
{
  Tree tree = makeTree(x, y, drvr_index, alpha_);

  return tree;
}

Tree SteinerTreeBuilder::makeSteinerTree(odb::dbNet* net,
                                         std::vector<int>& x,
                                         std::vector<int>& y,
                                         int drvr_index)
{
  float net_alpha = alpha_;
  int min_fanout = min_fanout_alpha_.first;
  int min_hpwl = min_hpwl_alpha_.first;

  if (net_alpha_map_.find(net) != net_alpha_map_.end()) {
    net_alpha = net_alpha_map_[net];
  } else if (min_hpwl > 0) {
    if (computeHPWL(net) >= min_hpwl) {
      net_alpha = min_hpwl_alpha_.second;
    }
  } else if (min_fanout > 0) {
    if (net->getTermCount()-1 >= min_fanout) {
      net_alpha = min_fanout_alpha_.second;
    }
  }

  Tree tree = makeTree(x, y, drvr_index, net_alpha);

  return tree;
}

Tree SteinerTreeBuilder::makeSteinerTree(const std::vector<int>& x,
                                         const std::vector<int>& y,
                                         const std::vector<int>& s,
                                         int accuracy)
{
  Tree tree = flt::flutes(x, y, s, accuracy);
  return tree;
}

float SteinerTreeBuilder::getAlpha(const odb::dbNet* net) const
{
  float net_alpha = net_alpha_map_.find(net) != net_alpha_map_.end() ?
                    net_alpha_map_.at(net) : alpha_;
  return net_alpha;
}

// This checks whether the tree has the property that no two
// non-adjacent edges have intersecting bounding boxes.  If
// they do it is a failure as embedding those egdes may cause
// overlap between them.
bool SteinerTreeBuilder::checkTree(const Tree& tree) const
{
  // Such high fanout nets are going to get buffered so
  // we don't need to worry about them.
  if (tree.deg > 100) {
    return true;
  }

  std::vector<odb::Rect> rects;
  for (int i = 0; i < tree.branchCount(); ++i) {
    const Branch& branch = tree.branch[i];
    const int x1 = branch.x;
    const int y1 = branch.y;
    const Branch& neighbor = tree.branch[branch.n];
    const int x2 = neighbor.x;
    const int y2 = neighbor.y;
    rects.emplace_back(x1, y1, x2, y2);
  }
  for (auto i = 0; i < rects.size(); ++i) {
    for (auto j = i + 1; j < rects.size(); ++j) {
      const Branch& b1 = tree.branch[i];
      const Branch& b2 = tree.branch[j];
      const odb::Rect& r1 = rects[i];
      const odb::Rect& r2 = rects[j];
      if (r1.intersects(r2) && b1.n != j && b2.n != i && b1.n != b2.n) {
        debugPrint(logger_, utl::STT, "check", 1,
                   "check failed ({}, {}) ({}, {}) [{}, {}] vs ({}, {}) ({}, {}) [{}, {}] degree={}",
                      r1.xMin(), r1.yMin(), r1.xMax(), r1.yMax(),
                      i, b1.n,
                      r2.xMin(), r2.yMin(), r2.xMax(), r2.yMax(),
                      j, b2.n, tree.deg);
        return false;
      }
    }
  }

  return true;
}

Tree SteinerTreeBuilder::makeTree(std::vector<int>& x,
                                  std::vector<int>& y,
                                  int drvr_index,
                                  float alpha)
{
  Tree tree;

  if (alpha > 0.0) {
    tree = pdr::primDijkstra(x, y, drvr_index, alpha, logger_);

    if (!checkTree(tree)) { // fallback
      tree = flt::flute(x, y, flute_accuracy);
    }
  } else {
    tree = flt::flute(x, y, flute_accuracy);
  }

  return tree;
}

int SteinerTreeBuilder::computeHPWL(odb::dbNet* net)
{
  int min_x = std::numeric_limits<int>::max();
  int min_y = std::numeric_limits<int>::max();
  int max_x = std::numeric_limits<int>::min();
  int max_y = std::numeric_limits<int>::min();

  for (odb::dbITerm* iterm : net->getITerms()) {
    odb::dbPlacementStatus status = iterm->getInst()->getPlacementStatus();
    if (status != odb::dbPlacementStatus::NONE &&
        status != odb::dbPlacementStatus::UNPLACED) {
      int x, y;
      iterm->getAvgXY(&x, &y);
      min_x = std::min(min_x, x);
      max_x = std::max(max_x, x);
      min_y = std::min(min_y, y);
      max_y = std::max(max_y, y);
    } else {
      logger_->error(utl::STT, 4, "Net {} is connected to unplaced instance {}.",
                     net->getName(),
                     iterm->getInst()->getName());
    }
  }

  for (odb::dbBTerm* bterm : net->getBTerms()) {
    if (bterm->getFirstPinPlacementStatus() != odb::dbPlacementStatus::NONE ||
        bterm->getFirstPinPlacementStatus() != odb::dbPlacementStatus::UNPLACED) {
      int x, y;
      bterm->getFirstPinLocation(x, y);
      min_x = std::min(min_x, x);
      max_x = std::max(max_x, x);
      min_y = std::min(min_y, y);
      max_y = std::max(max_y, y);
    } else {
      logger_->error(utl::STT, 5, "Net {} is connected to unplaced pin {}.",
                     net->getName(),
                     bterm->getName());
    }
  }

  int hpwl = (max_x - min_x) + (max_y - min_y);

  return hpwl;
}

}
<commit_msg>stt: try adding alpha-0.1 fallback<commit_after>/////////////////////////////////////////////////////////////////////////////
//
// BSD 3-Clause License
//
// Copyright (c) 2019, The Regents of the University of California
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// * Neither the name of the copyright holder nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////////

#include "stt/SteinerTreeBuilder.h"

#include <map>
#include <vector>

#include "ord/OpenRoad.hh"
#include "opendb/db.h"

namespace stt{

SteinerTreeBuilder::SteinerTreeBuilder() :
  alpha_(0.3),
  min_fanout_alpha_({0, -1}),
  min_hpwl_alpha_({0, -1}),
  logger_(nullptr),
  db_(nullptr)
{
}

void SteinerTreeBuilder::init(odb::dbDatabase* db, Logger* logger)
{
  db_ = db;
  logger_ = logger;
}

Tree SteinerTreeBuilder::makeSteinerTree(std::vector<int>& x,
                                         std::vector<int>& y,
                                         int drvr_index)
{
  Tree tree = makeTree(x, y, drvr_index, alpha_);

  return tree;
}

Tree SteinerTreeBuilder::makeSteinerTree(odb::dbNet* net,
                                         std::vector<int>& x,
                                         std::vector<int>& y,
                                         int drvr_index)
{
  float net_alpha = alpha_;
  int min_fanout = min_fanout_alpha_.first;
  int min_hpwl = min_hpwl_alpha_.first;

  if (net_alpha_map_.find(net) != net_alpha_map_.end()) {
    net_alpha = net_alpha_map_[net];
  } else if (min_hpwl > 0) {
    if (computeHPWL(net) >= min_hpwl) {
      net_alpha = min_hpwl_alpha_.second;
    }
  } else if (min_fanout > 0) {
    if (net->getTermCount()-1 >= min_fanout) {
      net_alpha = min_fanout_alpha_.second;
    }
  }

  Tree tree = makeTree(x, y, drvr_index, net_alpha);

  return tree;
}

Tree SteinerTreeBuilder::makeSteinerTree(const std::vector<int>& x,
                                         const std::vector<int>& y,
                                         const std::vector<int>& s,
                                         int accuracy)
{
  Tree tree = flt::flutes(x, y, s, accuracy);
  return tree;
}

float SteinerTreeBuilder::getAlpha(const odb::dbNet* net) const
{
  float net_alpha = net_alpha_map_.find(net) != net_alpha_map_.end() ?
                    net_alpha_map_.at(net) : alpha_;
  return net_alpha;
}

// This checks whether the tree has the property that no two
// non-adjacent edges have intersecting bounding boxes.  If
// they do it is a failure as embedding those egdes may cause
// overlap between them.
bool SteinerTreeBuilder::checkTree(const Tree& tree) const
{
  // Such high fanout nets are going to get buffered so
  // we don't need to worry about them.
  if (tree.deg > 100) {
    return true;
  }

  std::vector<odb::Rect> rects;
  for (int i = 0; i < tree.branchCount(); ++i) {
    const Branch& branch = tree.branch[i];
    const int x1 = branch.x;
    const int y1 = branch.y;
    const Branch& neighbor = tree.branch[branch.n];
    const int x2 = neighbor.x;
    const int y2 = neighbor.y;
    rects.emplace_back(x1, y1, x2, y2);
  }
  for (auto i = 0; i < rects.size(); ++i) {
    for (auto j = i + 1; j < rects.size(); ++j) {
      const Branch& b1 = tree.branch[i];
      const Branch& b2 = tree.branch[j];
      const odb::Rect& r1 = rects[i];
      const odb::Rect& r2 = rects[j];
      if (r1.intersects(r2) && b1.n != j && b2.n != i && b1.n != b2.n) {
        debugPrint(logger_, utl::STT, "check", 1,
                   "check failed ({}, {}) ({}, {}) [{}, {}] vs ({}, {}) ({}, {}) [{}, {}] degree={}",
                      r1.xMin(), r1.yMin(), r1.xMax(), r1.yMax(),
                      i, b1.n,
                      r2.xMin(), r2.yMin(), r2.xMax(), r2.yMax(),
                      j, b2.n, tree.deg);
        return false;
      }
    }
  }

  return true;
}

Tree SteinerTreeBuilder::makeTree(std::vector<int>& x,
                                  std::vector<int>& y,
                                  int drvr_index,
                                  float alpha)
{
  Tree tree;

  if (alpha > 0.0) {
    tree = pdr::primDijkstra(x, y, drvr_index, alpha, logger_);

    if (checkTree(tree)) {
      return tree;
    }

    // Try a smaller alpha if possible
    if (alpha > 0.1) {
      tree = pdr::primDijkstra(x, y, drvr_index, alpha - 0.1, logger_);
      if (checkTree(tree)) {
        return tree;
      }
    }

    // Give up and use flute
    return tree = flt::flute(x, y, flute_accuracy);
  } else {
    return flt::flute(x, y, flute_accuracy);
  }
}

int SteinerTreeBuilder::computeHPWL(odb::dbNet* net)
{
  int min_x = std::numeric_limits<int>::max();
  int min_y = std::numeric_limits<int>::max();
  int max_x = std::numeric_limits<int>::min();
  int max_y = std::numeric_limits<int>::min();

  for (odb::dbITerm* iterm : net->getITerms()) {
    odb::dbPlacementStatus status = iterm->getInst()->getPlacementStatus();
    if (status != odb::dbPlacementStatus::NONE &&
        status != odb::dbPlacementStatus::UNPLACED) {
      int x, y;
      iterm->getAvgXY(&x, &y);
      min_x = std::min(min_x, x);
      max_x = std::max(max_x, x);
      min_y = std::min(min_y, y);
      max_y = std::max(max_y, y);
    } else {
      logger_->error(utl::STT, 4, "Net {} is connected to unplaced instance {}.",
                     net->getName(),
                     iterm->getInst()->getName());
    }
  }

  for (odb::dbBTerm* bterm : net->getBTerms()) {
    if (bterm->getFirstPinPlacementStatus() != odb::dbPlacementStatus::NONE ||
        bterm->getFirstPinPlacementStatus() != odb::dbPlacementStatus::UNPLACED) {
      int x, y;
      bterm->getFirstPinLocation(x, y);
      min_x = std::min(min_x, x);
      max_x = std::max(max_x, x);
      min_y = std::min(min_y, y);
      max_y = std::max(max_y, y);
    } else {
      logger_->error(utl::STT, 5, "Net {} is connected to unplaced pin {}.",
                     net->getName(),
                     bterm->getName());
    }
  }

  int hpwl = (max_x - min_x) + (max_y - min_y);

  return hpwl;
}

}
<|endoftext|>


<commit_before>// Check that the stack trace debugging API works and returns correct
// malloc and free stacks.
// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s

#include <sanitizer/asan_interface.h>
#include <stdio.h>
#include <stdlib.h>

char *mem;
void func1() {
  mem = (char *)malloc(10);
}

void func2() {
  free(mem);
}

int main() {
  func1();
  func2();

  void *trace[100];
  size_t num_frames = 100;
  int thread_id;
  num_frames = __asan_get_alloc_stack(mem, trace, num_frames, &thread_id);

  fprintf(stderr, "alloc stack retval %s\n", (num_frames > 0 && num_frames < 10)
          ? "ok" : "");
  // CHECK: alloc stack retval ok
  fprintf(stderr, "thread id = %d\n", thread_id);
  // CHECK: thread id = 0
  fprintf(stderr, "0x%lx\n", trace[0]);
  // CHECK: [[ALLOC_FRAME_0:0x[0-9a-f]+]]
  fprintf(stderr, "0x%lx\n", trace[1]);
  // CHECK: [[ALLOC_FRAME_1:0x[0-9a-f]+]]

  num_frames = 100;
  num_frames = __asan_get_free_stack(mem, trace, num_frames, &thread_id);

  fprintf(stderr, "free stack retval %s\n", (num_frames > 0 && num_frames < 10)
          ? "ok" : "");
  // CHECK: free stack retval ok
  fprintf(stderr, "thread id = %d\n", thread_id);
  // CHECK: thread id = 0
  fprintf(stderr, "0x%lx\n", trace[0]);
  // CHECK: [[FREE_FRAME_0:0x[0-9a-f]+]]
  fprintf(stderr, "0x%lx\n", trace[1]);
  // CHECK: [[FREE_FRAME_1:0x[0-9a-f]+]]

  mem[0] = 'A'; // BOOM

  // CHECK: ERROR: AddressSanitizer: heap-use-after-free
  // CHECK: WRITE of size 1 at 0x{{.*}}
  // CHECK: freed by thread T0 here:
  // CHECK: #0 [[FREE_FRAME_0]]
  // CHECK: #1 [[FREE_FRAME_1]]
  // CHECK: previously allocated by thread T0 here:
  // CHECK: #0 [[ALLOC_FRAME_0]]
  // CHECK: #1 [[ALLOC_FRAME_1]]

  return 0;
}
<commit_msg>[ASan] debug_stacks.cc was passing on ARM by accident, disable this test there for now.<commit_after>// Check that the stack trace debugging API works and returns correct
// malloc and free stacks.
// RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s

// FIXME: Figure out why allocation/free stack traces may be too short on ARM.
// REQUIRES: stable-runtime

#include <sanitizer/asan_interface.h>
#include <stdio.h>
#include <stdlib.h>

char *mem;
void func1() {
  mem = (char *)malloc(10);
}

void func2() {
  free(mem);
}

int main() {
  func1();
  func2();

  void *trace[100];
  size_t num_frames = 100;
  int thread_id;
  num_frames = __asan_get_alloc_stack(mem, trace, num_frames, &thread_id);

  fprintf(stderr, "alloc stack retval %s\n", (num_frames > 0 && num_frames < 10)
          ? "ok" : "");
  // CHECK: alloc stack retval ok
  fprintf(stderr, "thread id = %d\n", thread_id);
  // CHECK: thread id = 0
  fprintf(stderr, "0x%lx\n", trace[0]);
  // CHECK: [[ALLOC_FRAME_0:0x[0-9a-f]+]]
  fprintf(stderr, "0x%lx\n", trace[1]);
  // CHECK: [[ALLOC_FRAME_1:0x[0-9a-f]+]]

  num_frames = 100;
  num_frames = __asan_get_free_stack(mem, trace, num_frames, &thread_id);

  fprintf(stderr, "free stack retval %s\n", (num_frames > 0 && num_frames < 10)
          ? "ok" : "");
  // CHECK: free stack retval ok
  fprintf(stderr, "thread id = %d\n", thread_id);
  // CHECK: thread id = 0
  fprintf(stderr, "0x%lx\n", trace[0]);
  // CHECK: [[FREE_FRAME_0:0x[0-9a-f]+]]
  fprintf(stderr, "0x%lx\n", trace[1]);
  // CHECK: [[FREE_FRAME_1:0x[0-9a-f]+]]

  mem[0] = 'A'; // BOOM

  // CHECK: ERROR: AddressSanitizer: heap-use-after-free
  // CHECK: WRITE of size 1 at 0x{{.*}}
  // CHECK: freed by thread T0 here:
  // CHECK: #0 [[FREE_FRAME_0]]
  // CHECK: #1 [[FREE_FRAME_1]]
  // CHECK: previously allocated by thread T0 here:
  // CHECK: #0 [[ALLOC_FRAME_0]]
  // CHECK: #1 [[ALLOC_FRAME_1]]

  return 0;
}
<|endoftext|>


<commit_before>/***************************************************//**
 * @file    FlameXUSBTransferHelper.cpp
 * @date    February 2016
 * @author  Ocean Optics, Inc.
 *
 * LICENSE:
 *
 * SeaBreeze Copyright (C) 2016, Ocean Optics Inc
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject
 * to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *******************************************************/

#include "common/globals.h"
#include "vendors/OceanOptics/buses/usb/FlameXUSBTransferHelper.h"
#include <string.h> /* for memcpy() */

using namespace seabreeze;
using namespace std;

const int FlameXUSBTransferHelper::WORD_SIZE_BYTES = 4;

FlameXUSBTransferHelper::FlameXUSBTransferHelper(USB *usb,
        const OOIUSBBidrectionalEndpointMap &map) : USBTransferHelper(usb) {
    this->sendEndpoint = map.getPrimaryOutEndpoint();
    this->receiveEndpoint = map.getPrimaryInEndpoint();
}

FlameXUSBTransferHelper::~FlameXUSBTransferHelper() {

}

int FlameXUSBTransferHelper::receive(vector<byte> &buffer,
        unsigned int length) {
    if(0 != (length % WORD_SIZE_BYTES)) {
        vector<byte> *inBuffer;
        int paddedLength;

        paddedLength = length + (WORD_SIZE_BYTES - (length % WORD_SIZE_BYTES));
        inBuffer = new vector<byte>(paddedLength);

        int result = USBTransferHelper::receive(*inBuffer, paddedLength);
        if(result != paddedLength) {
            string error("Failed to read padded message length: ");
            error += result;
            error += " != ";
            error += paddedLength;
            throw BusTransferException(error);
        }
        memcpy(&buffer[0], &inBuffer[0], length);
        delete inBuffer;
        return length;
    } else {
        return USBTransferHelper::receive(buffer, length);
    }
}

int FlameXUSBTransferHelper::send(const std::vector<byte> &buffer,
        unsigned int length) const {

    if(0 != (length % WORD_SIZE_BYTES)) {
        /* Pad up to a multiple of the word size */
        int paddedLength = length + (WORD_SIZE_BYTES - (length % WORD_SIZE_BYTES));
        vector<byte> *outBuffer = new vector<byte>(paddedLength);
        memcpy(&outBuffer[0], &buffer[0], length);
        int result = USBTransferHelper::send(*outBuffer, paddedLength);
        delete outBuffer;
        return result;
    } else {
        return USBTransferHelper::send(buffer, length);
    }
}
<commit_msg>[libseabreeze] fix FlameXUSBTransferHelper warning<commit_after>/***************************************************//**
 * @file    FlameXUSBTransferHelper.cpp
 * @date    February 2016
 * @author  Ocean Optics, Inc.
 *
 * LICENSE:
 *
 * SeaBreeze Copyright (C) 2016, Ocean Optics Inc
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject
 * to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *******************************************************/

#include "common/globals.h"
#include "vendors/OceanOptics/buses/usb/FlameXUSBTransferHelper.h"
#include <string.h> /* for memcpy() */

using namespace seabreeze;
using namespace std;

const int FlameXUSBTransferHelper::WORD_SIZE_BYTES = 4;

FlameXUSBTransferHelper::FlameXUSBTransferHelper(USB *usb,
        const OOIUSBBidrectionalEndpointMap &map) : USBTransferHelper(usb) {
    this->sendEndpoint = map.getPrimaryOutEndpoint();
    this->receiveEndpoint = map.getPrimaryInEndpoint();
}

FlameXUSBTransferHelper::~FlameXUSBTransferHelper() {

}

int FlameXUSBTransferHelper::receive(vector<byte> &buffer,
        unsigned int length) {
    if(0 != (length % WORD_SIZE_BYTES)) {
        vector<byte> *inBuffer;
        int paddedLength;

        paddedLength = length + (WORD_SIZE_BYTES - (length % WORD_SIZE_BYTES));
        inBuffer = new vector<byte>(paddedLength);

        int result = USBTransferHelper::receive(*inBuffer, paddedLength);
        if(result != paddedLength) {
            string error("Failed to read padded message length: ");
            error += result;
            error += " != ";
            error += paddedLength;
            throw BusTransferException(error);
        }
        memcpy(&buffer[0], &inBuffer[0], length);
        delete inBuffer;
        return length;
    } else {
        return USBTransferHelper::receive(buffer, length);
    }
}

int FlameXUSBTransferHelper::send(const std::vector<byte> &buffer,
        unsigned int length) const {

    if(0 != (length % WORD_SIZE_BYTES)) {
        /* Pad up to a multiple of the word size */
        int paddedLength = length + (WORD_SIZE_BYTES - (length % WORD_SIZE_BYTES));
        vector<byte> *outBuffer = new vector<byte>(paddedLength);
        memcpy((byte*) &outBuffer[0], (byte*) &buffer[0], length);
        int result = USBTransferHelper::send(*outBuffer, paddedLength);
        delete outBuffer;
        return result;
    } else {
        return USBTransferHelper::send(buffer, length);
    }
}
<|endoftext|>


<commit_before>/*!
 * \brief Tests the GUI geometry builder
 *
 * \author ddubois
 * \date 06-Nov-16.
 */

#include <vector>
#include <gtest/gtest.h>

#include <data_loading/geometry_cache/builders/gui_geometry_builder.h>
#include <view/nova_renderer.h>

TEST(gui_geometry_builder, add_vertex_test) {
    auto vertex_buffer = std::vector<float>{};

    nova::model::add_vertex(vertex_buffer, 5, 5, 0.5, 0.5);

    EXPECT_EQ(vertex_buffer.size(), 5);

    EXPECT_EQ(vertex_buffer[0], 5);
    EXPECT_EQ(vertex_buffer[1], 5);
    EXPECT_EQ(vertex_buffer[2], 0);
    EXPECT_EQ(vertex_buffer[3], 0.5);
    EXPECT_EQ(vertex_buffer[4], 0.5);
}

TEST(gui_geometry_builder, add_vertices_from_button_test) {
    auto vertex_buffer = std::vector<float>{};
    auto button = mc_gui_button{0, 0, 100, 100, "Main Menu", false};
    auto uvs = std::vector<float>{0, 0, 0, 1, 1, 0, 1, 1};

    nova::model::add_vertices_from_button(vertex_buffer, button, uvs);

    EXPECT_EQ(vertex_buffer.size(), 20);

    // First vertex
    EXPECT_EQ(vertex_buffer[0], 0);
    EXPECT_EQ(vertex_buffer[1], 0);
    EXPECT_EQ(vertex_buffer[2], 0);
    EXPECT_EQ(vertex_buffer[3], 0);

    // Third vertex because I'm too lazy to check all of them
    EXPECT_EQ(vertex_buffer[10], 0);
    EXPECT_EQ(vertex_buffer[11], 100);
    EXPECT_EQ(vertex_buffer[13], 1);
    EXPECT_EQ(vertex_buffer[14], 0);
}

TEST(gui_geometry_builder, add_indices_with_offset_positive_test) {
    auto indices = std::vector<unsigned>{};
    auto start_pos = 3;

    nova::model::add_indices_with_offset(indices, (unsigned int) start_pos);

    EXPECT_EQ(indices[0], 3);
    EXPECT_EQ(indices[1], 4);
    EXPECT_EQ(indices[2], 5);
    EXPECT_EQ(indices[3], 5);
    EXPECT_EQ(indices[4], 4);
    EXPECT_EQ(indices[5], 6);
}

TEST(gui_geometry_builder, add_indices_with_offset_negative_offset_test) {
    auto indices = std::vector<unsigned>{};
    auto start_pos = -3;

    nova::model::add_indices_with_offset(indices, (unsigned int) start_pos);

    EXPECT_EQ(indices[0], 65533);
    EXPECT_EQ(indices[1], 65534);
    EXPECT_EQ(indices[2], 65535);
    EXPECT_EQ(indices[3], 65535);
    EXPECT_EQ(indices[4], 65534);
    EXPECT_EQ(indices[5], 0);
}

TEST(gui_geometry_builder, build_gui_geometry_no_buttons_test) {
    nova::view::nova_renderer::init_instance();
    mc_gui_screen gui = {};
    gui.num_buttons = 0;

    nova::model::mesh_definition gui_mesh = nova::model::build_gui_geometry(gui);
}
<commit_msg>All tests now pass<commit_after>/*!
 * \brief Tests the GUI geometry builder
 *
 * \author ddubois
 * \date 06-Nov-16.
 */

#include <vector>
#include <gtest/gtest.h>

#include <data_loading/geometry_cache/builders/gui_geometry_builder.h>
#include <view/nova_renderer.h>

TEST(gui_geometry_builder, add_vertex_test) {
    auto vertex_buffer = std::vector<float>{};

    nova::model::add_vertex(vertex_buffer, 5, 5, 0.5, 0.5);

    EXPECT_EQ(vertex_buffer.size(), 5);

    EXPECT_EQ(vertex_buffer[0], 5);
    EXPECT_EQ(vertex_buffer[1], 5);
    EXPECT_EQ(vertex_buffer[2], 0);
    EXPECT_EQ(vertex_buffer[3], 0.5);
    EXPECT_EQ(vertex_buffer[4], 0.5);
}

TEST(gui_geometry_builder, add_vertices_from_button_test) {
    auto vertex_buffer = std::vector<float>{};
    auto button = mc_gui_button{0, 0, 100, 100, "Main Menu", false};
    auto uvs = std::vector<float>{0, 0, 0, 1, 1, 0, 1, 1};

    nova::model::add_vertices_from_button(vertex_buffer, button, uvs);

    EXPECT_EQ(vertex_buffer.size(), 20);

    // First vertex
    EXPECT_EQ(vertex_buffer[0], 0);
    EXPECT_EQ(vertex_buffer[1], 0);
    EXPECT_EQ(vertex_buffer[2], 0);
    EXPECT_EQ(vertex_buffer[3], 0);

    // Third vertex because I'm too lazy to check all of them
    EXPECT_EQ(vertex_buffer[10], 0);
    EXPECT_EQ(vertex_buffer[11], 100);
    EXPECT_EQ(vertex_buffer[13], 1);
    EXPECT_EQ(vertex_buffer[14], 0);
}

TEST(gui_geometry_builder, add_indices_with_offset_positive_test) {
    auto indices = std::vector<unsigned>{};
    auto start_pos = 3;

    nova::model::add_indices_with_offset(indices, (unsigned int) start_pos);

    EXPECT_EQ(indices[0], 3);
    EXPECT_EQ(indices[1], 4);
    EXPECT_EQ(indices[2], 5);
    EXPECT_EQ(indices[3], 5);
    EXPECT_EQ(indices[4], 4);
    EXPECT_EQ(indices[5], 6);
}

TEST(gui_geometry_builder, add_indices_with_offset_negative_offset_test) {
    auto indices = std::vector<unsigned>{};
    auto start_pos = -3;

    nova::model::add_indices_with_offset(indices, (unsigned int) start_pos);

    EXPECT_EQ(indices[0], 4294967293);
    EXPECT_EQ(indices[1], 4294967294);
    EXPECT_EQ(indices[2], 4294967295);
    EXPECT_EQ(indices[3], 4294967295);
    EXPECT_EQ(indices[4], 4294967294);
    EXPECT_EQ(indices[5], 0);
}

TEST(gui_geometry_builder, build_gui_geometry_no_buttons_test) {
    nova::view::nova_renderer::init_instance();
    mc_gui_screen gui = {};
    gui.num_buttons = 0;

    nova::model::mesh_definition gui_mesh = nova::model::build_gui_geometry(gui);
}
<|endoftext|>


<commit_before>// programming_challenges_13.cpp: santiaago
// Description: Australian Voting - Programming challenges 110108

#include <iostream>
#include <vector>
#include <sstream>
#include <string>
#include <map>

using namespace std;

template<typename T>
void printVector(vector<T> v);
void printMap(map<string, unsigned int> m);

int main(){
  cout << "Australian Voting" << endl;
  unsigned int num_cases(0);
  cin >> num_cases;
  string line;
  getline (cin, line);
  while(num_cases > 0){
    unsigned int num_candidates(0);
    cin >> num_candidates;
    vector<string> candidates(num_candidates);
    map<unsigned int, map<string, unsigned int> > candidate_votes;

    string candidate;
    while( num_candidates > 0 && cin >> candidate ){
      candidates[candidates.size()-num_candidates] = candidate;
      num_candidates--;
    }
    printVector(candidates);
    //printMap(candidate_votes);
    // read up to 1000 lines

    string vote;
    unsigned int num_votes(0);
    cin.ignore();
    while( num_votes < 1000){
      getline(cin, vote);
      if(vote.empty()) break;
      istringstream stm(vote);
      unsigned int index_candidate;
      vector<unsigned int> current_vote;
      while( stm >> index_candidate){
	current_vote.push_back(index_candidate);
      }
      for(int i = 0; i < current_vote.size(); i++){
      	//candidate_votes[candidates[current_vote[i] - 1]]++;
	cout << "vote: " << current_vote[i] << endl;
	cout << "candidate: " << candidates[current_vote[i]-1] << endl;
	cout << "count: " << candidate_votes[i + 1][candidates[current_vote[i]-1]] << endl;
	candidate_votes[i + 1][candidates[current_vote[i]-1]]++;//candidates[current_vote[i]][
	cout << "count: " << candidate_votes[i + 1][candidates[current_vote[i]-1]] << endl;
      }
      printVector(current_vote);
      num_votes++;
    }
    // printMap(candidate_votes);
    for(auto t : candidate_votes){
      cout << t.first << " | ";
      for(auto t2 : t.second){
	cout << "\t" << t2.first << " : " << t2.second << endl;
      }
    }
    cout << "case done " << endl;
    num_cases--;
  }
  cout << "end" << endl;
}

template<typename T>
void printVector(vector<T> v){
  for(T c : v){
    cout << c << " | ";
  }
  cout << endl;
}

void printMap(map<string, unsigned int> m){
  for(auto t : m){
    cout << t.first << " : " << t.second << endl;
  }
}
<commit_msg>main algorithm for the australian vote is ready.<commit_after>// programming_challenges_13.cpp: santiaago
// Description: Australian Voting - Programming challenges 110108

#include <iostream>
#include <vector>
#include <sstream>
#include <string>
#include <map>
#include <limits>

using namespace std;

template<typename T>
void printVector(vector<T> v);
void printMap(map<string, unsigned int> m);
string getLowestCandidate(map<string, unsigned int> candidates);
string getHighestCandidate(map<string, unsigned int> m);
bool areCandidatesTied(map<string, unsigned int> candidates);

int main(){
  cout << "Australian Voting" << endl;
  unsigned int num_cases(0);
  cin >> num_cases;
  string line;
  getline (cin, line);
  vector<string> winners;
  while(num_cases > 0){
    unsigned int num_candidates(0);
    cin >> num_candidates;
    vector<string> candidates(num_candidates);
    map<unsigned int, map<string, unsigned int> > candidate_votes;

    string candidate;
    while( num_candidates > 0 && cin >> candidate ){
      candidates[candidates.size()-num_candidates] = candidate;
      num_candidates--;
    }
    printVector(candidates);
    // read up to 1000 lines
    string vote;
    unsigned int num_votes(0);
    cin.ignore();
    while( num_votes < 1000){
      getline(cin, vote);
      if(vote.empty()) break;
      istringstream stm(vote);
      unsigned int index_candidate;
      vector<unsigned int> current_vote;
      while( stm >> index_candidate){
	current_vote.push_back(index_candidate);
      }
      for(int i = 0; i < current_vote.size(); i++){
      	//candidate_votes[candidates[current_vote[i] - 1]]++;
	cout << "vote: " << current_vote[i] << endl;
	cout << "candidate: " << candidates[current_vote[i]-1] << endl;
	cout << "count: " << candidate_votes[i + 1][candidates[current_vote[i]-1]] << endl;
	candidate_votes[i + 1][candidates[current_vote[i]-1]]++;//candidates[current_vote[i]][
	cout << "count: " << candidate_votes[i + 1][candidates[current_vote[i]-1]] << endl;
      }
      printVector(current_vote);
      num_votes++;
    }
    for(auto t : candidate_votes){
      cout << t.first << " | ";
      for(auto t2 : t.second){
	cout << "\t" << t2.first << " : " << t2.second << endl;
      }
    }
    double mayority = num_votes/double(2.0);
    bool has_winner(false);
    while(!has_winner){
      for(auto t : candidate_votes[1]){
	if(t.second > mayority){
	  winners.push_back(t.first);
	  has_winner = true;
	  break;
	}
      }
      if(!has_winner){
	string highest_candidate = getHighestCandidate(candidate_votes[1]);
	string lowest_candidate = getLowestCandidate(candidate_votes[1]);
	unsigned int votes = candidate_votes[1][lowest_candidate];
	map<string, unsigned int>::iterator to_remove;
	to_remove = candidate_votes[1].find(lowest_candidate);
	candidate_votes[1].erase(to_remove);
	candidate_votes[1][highest_candidate] += votes;
      }
      if(areCandidatesTied(candidate_votes[1])){
	for(auto c : candidate_votes[1]){
	  winners.push_back(c.first);
	}
	has_winner = true;
      }
    }

    for(auto w : winners){
      cout << w << endl;
    }
    cout << "case done " << endl;
    num_cases--;
  }
  for(int i = 0; i < winners.size(); i++){
    cout << winners[i] << endl;
  }
  cout << "end" << endl;
}

template<typename T>
void printVector(vector<T> v){
  for(T c : v){
    cout << c << " | ";
  }
  cout << endl;
}

void printMap(map<string, unsigned int> m){
  for(auto t : m){
    cout << t.first << " : " << t.second << endl;
  }
}

bool areCandidatesTied(map<string, unsigned int> candidates){
  unsigned int value(-1);
  for(auto c : candidates){
    if(value == -1){
      value = c.second;
    } else {
      if(value != c.second){
	return false;
      }
    }
  }
  return true;
}

string getLowestCandidate(map<string, unsigned int> candidates){
  string lowest_candidate;
  unsigned int min(numeric_limits<int>::max());
  for(auto c : candidates){
    if(c.second < min){
      min = c.second;
      lowest_candidate = c.first;
    }
  }
  return lowest_candidate;

}

string getHighestCandidate(map<string, unsigned int> candidates){
  string highest_candidate;
  unsigned int max(0);
  for(auto c : candidates){
    if(c.second > max){
      max = c.second;
      highest_candidate = c.first;
    }
  }
  return highest_candidate;
}
<|endoftext|>


<commit_before>#include "request.h"
#include <cstring>

namespace REST {

const size_t Request::BUFFER_SIZE = 4096;

Request::Request(int client, struct sockaddr_storage client_addr) : handle(client), addr(client_addr) {
  static Json::Reader json_reader;

  std::string line;
  bool is_header = true;
  char buffer[BUFFER_SIZE];

  // receive data from client
  recv(client, buffer, BUFFER_SIZE, 0);

  // parse each line
  std::istringstream request_stream(buffer);
  while (std::getline(request_stream, line)) {
    // if method is undefined, assumie its first line
    if (method == Method::UNDEFINED) {
      // so parse header
      parse_header(line);
      continue;
    }

    // next lines are headers, strip them
    line.erase(line.find_last_not_of(" \n\r\t")+1);

    // if line is empty, then content should follow
    if (line.size() == 0) {
      is_header = false;
      break;
    }

    // extract name and value from header
    size_t colon;
    std::string name = line.substr(0, colon = line.find(":"));
    std::string value = line.substr(colon+1);
    value.erase(0, value.find_first_not_of(" \n\r\t"));

    headers.insert(std::make_pair(name, value));
  }

  // if has content
  if (!is_header) {
    // assume proper content length
    size_t content_length = header("Content-Length", 0);
    raw.reserve(content_length);

    if (content_length > 0) {
      // read whats left in header
      length = std::min(content_length, (size_t)(BUFFER_SIZE - request_stream.tellg()));
      raw = std::string(buffer, BUFFER_SIZE).substr(request_stream.tellg(), length);

      // receive some more
      while (length < content_length) {
        memset(buffer, 0, BUFFER_SIZE);
        size_t buffer_length = recv(client, buffer, BUFFER_SIZE, 0);
        raw += std::string(buffer, buffer_length);
        length += buffer_length;
      }
    }
    //std::cout << "content o "<<content_length<<" == "<<length<<" == " <<raw.size()<<"\n";
  }

  // delete [] buffer;

  time = std::chrono::high_resolution_clock::now();

  // if has some content
  if (!raw.empty()) {
    // try to parse it
    auto ct = headers.find("Content-Type");
    if (ct != headers.end()) {
      if (ct->second == "application/x-www-form-urlencoded") {
        parse_query_string(raw);
      } else
      if (ct->second == "application/json" || ct->second == "text/json") {
        data = std::make_shared<Json::Value>();
        json_reader.parse(raw, *data.get(), false);
      }
    }
  }
}

void Request::parse_header(std::string line) {
  if (line.find("GET") == 0) {
    method = Method::GET;
  } else
  if (line.find("HEAD") == 0) {
    method = Method::HEAD;
  } else
  if (line.find("POST") == 0) {
    method = Method::POST;
  } else
  if (line.find("PUT") == 0) {
    method = Method::PUT;
  } else
  if (line.find("PATCH") == 0) {
    method = Method::PATCH;
  } else
  if (line.find("DELETE") == 0) {
    method = Method::DELETE;
  } else
  if (line.find("TRACE") == 0) {
    method = Method::TRACE;
  } else
  if (line.find("CONNECT") == 0) {
    method = Method::CONNECT;
  } else
  if (line.find("OPTIONS") == 0) {
    method = Method::OPTIONS;
  }

  size_t path_start = line.find_first_of(" ")+1;
  size_t path_end = line.rfind("HTTP/1.")-1;

  path = line.substr(path_start, path_end - path_start);

  size_t path_query = path.find("?");

  if (path_query != std::string::npos) {
    std::string query = path.substr(path_query+1, path.size() - path_query);

    parse_query_string(query);

    path.erase(path_query, query.size()+1);
  }
}

void Request::parse_query_string(std::string query) {
  query.erase(query.find_last_not_of(" \n\r\t")+1);
  std::istringstream query_stream(query);
  std::string pair;
  while (std::getline(query_stream, pair, '&')) {
    std::string name, value;
    size_t value_position = pair.find("=");

    name = pair.substr(0, value_position);
    if (value_position != std::string::npos)
      value = pair.substr(value_position+1, pair.size() - value_position-1);

    parameters[Utils::uri_decode(name)] = Utils::uri_decode(value);
  }
}

Request::~Request() {
}

}
<commit_msg>working on copy<commit_after>#include "request.h"
#include <cstring>

namespace REST {

const size_t Request::BUFFER_SIZE = 4096;

Request::Request(int client, struct sockaddr_storage client_addr) : handle(client), addr(client_addr) {
  static Json::Reader json_reader;

  std::string line;
  bool is_header = true;
  char buffer[BUFFER_SIZE];

  // receive data from client
  recv(client, buffer, BUFFER_SIZE, 0);

  // parse each line
  std::istringstream request_stream(buffer);
  while (std::getline(request_stream, line)) {
    // if method is undefined, assumie its first line
    if (method == Method::UNDEFINED) {
      // so parse header
      parse_header(line);
      continue;
    }

    // next lines are headers, strip them
    line.erase(line.find_last_not_of(" \n\r\t")+1);

    // if line is empty, then content should follow
    if (line.size() == 0) {
      is_header = false;
      break;
    }

    // extract name and value from header
    size_t colon;
    std::string name = line.substr(0, colon = line.find(":"));
    std::string value = line.substr(colon+1);
    value.erase(0, value.find_first_not_of(" \n\r\t"));

    headers.insert(std::make_pair(name, value));
  }

  // if has content
  if (!is_header) {
    // assume proper content length
    size_t content_length = header("Content-Length", 0);
    raw.reserve(content_length);

    if (content_length > 0) {
      // read whats left in header
      length = std::min(content_length, (size_t)(BUFFER_SIZE - request_stream.tellg()));
      raw = std::string(buffer, BUFFER_SIZE).substr(request_stream.tellg(), length);

      // receive some more
      while (length < content_length) {
        memset(buffer, 0, BUFFER_SIZE);
        size_t buffer_length = recv(client, buffer, BUFFER_SIZE, 0);
        raw += std::string(buffer, buffer_length);
        length += buffer_length;
      }
    }
    //std::cout << "content o "<<content_length<<" == "<<length<<" == " <<raw.size()<<"\n";
  }

  // delete [] buffer;

  time = std::chrono::high_resolution_clock::now();

  // if has some content
  if (!raw.empty()) {
    // try to parse it
    auto ct = headers.find("Content-Type");
    if (ct != headers.end()) {
      if (ct->second == "application/x-www-form-urlencoded") {
        parse_query_string(raw);
      } else
      if (ct->second == "application/json" || ct->second == "text/json") {
        data = std::make_shared<Json::Value>();
        std::string raw_copy(raw);
        json_reader.parse(raw_copy, *data.get(), false);
      }
    }
  }
}

void Request::parse_header(std::string line) {
  if (line.find("GET") == 0) {
    method = Method::GET;
  } else
  if (line.find("HEAD") == 0) {
    method = Method::HEAD;
  } else
  if (line.find("POST") == 0) {
    method = Method::POST;
  } else
  if (line.find("PUT") == 0) {
    method = Method::PUT;
  } else
  if (line.find("PATCH") == 0) {
    method = Method::PATCH;
  } else
  if (line.find("DELETE") == 0) {
    method = Method::DELETE;
  } else
  if (line.find("TRACE") == 0) {
    method = Method::TRACE;
  } else
  if (line.find("CONNECT") == 0) {
    method = Method::CONNECT;
  } else
  if (line.find("OPTIONS") == 0) {
    method = Method::OPTIONS;
  }

  size_t path_start = line.find_first_of(" ")+1;
  size_t path_end = line.rfind("HTTP/1.")-1;

  path = line.substr(path_start, path_end - path_start);

  size_t path_query = path.find("?");

  if (path_query != std::string::npos) {
    std::string query = path.substr(path_query+1, path.size() - path_query);

    parse_query_string(query);

    path.erase(path_query, query.size()+1);
  }
}

void Request::parse_query_string(std::string query) {
  query.erase(query.find_last_not_of(" \n\r\t")+1);
  std::istringstream query_stream(query);
  std::string pair;
  while (std::getline(query_stream, pair, '&')) {
    std::string name, value;
    size_t value_position = pair.find("=");

    name = pair.substr(0, value_position);
    if (value_position != std::string::npos)
      value = pair.substr(value_position+1, pair.size() - value_position-1);

    parameters[Utils::uri_decode(name)] = Utils::uri_decode(value);
  }
}

Request::~Request() {
}

}
<|endoftext|>