<commit_before>#include "location_state.hpp"
#include "navigator.hpp"
#include "framework.hpp"
#include "compass_filter.hpp"
#include "rotate_screen_task.hpp"
#include "change_viewport_task.hpp"

#include "../yg/display_list.hpp"
#include "../yg/skin.hpp"

#include "../anim/controller.hpp"
#include "../anim/angle_interpolation.hpp"

#include "../gui/controller.hpp"

#include "../platform/location.hpp"
#include "../platform/platform.hpp"
#include "../platform/settings.hpp"

#include "../geometry/rect2d.hpp"
#include "../geometry/transformations.hpp"

#include "../indexer/mercator.hpp"

namespace location
{
  State::State(Params const & p)
    : base_t(p),
      m_hasPosition(false),
      m_hasCompass(false),
      m_isCentered(false),
      m_locationProcessMode(ELocationDoNothing),
      m_compassProcessMode(ECompassDoNothing)
  {
    m_drawHeading = m_compassFilter.GetHeadingRad();
    m_locationAreaColor = p.m_locationAreaColor;
    m_locationBorderColor = p.m_locationBorderColor;
    m_compassAreaColor = p.m_compassAreaColor;
    m_compassBorderColor = p.m_compassBorderColor;
    m_framework = p.m_framework;
    m_arrowScale = 0.7;
    m_arrowWidth = 40 * m_arrowScale;
    m_arrowHeight = 50 * m_arrowScale;
    m_arrowBackHeight = 10 * m_arrowScale;
    m_boundRects.resize(1);

    setColor(EActive, yg::Color(0x2f, 0xb5, 0xea, 128));
    setColor(EPressed, yg::Color(0x1f, 0x22, 0x59, 128));
    setState(EActive);
  }

  bool State::HasPosition() const
  {
    return m_hasPosition;
  }

  m2::PointD const & State::Position() const
  {
    return m_position;
  }

  bool State::HasCompass() const
  {
    return m_hasCompass;
  }

  void State::TurnOff()
  {
    m_hasPosition = false;
    m_hasCompass = false;
    setIsVisible(false);
  }

  void State::SkipLocationCentering()
  {
    m_locationProcessMode = ELocationSkipCentering;
  }

  ELocationProcessMode State::LocationProcessMode() const
  {
    return m_locationProcessMode;
  }

  void State::SetLocationProcessMode(ELocationProcessMode mode)
  {
    m_locationProcessMode = mode;
  }

  ECompassProcessMode State::CompassProcessMode() const
  {
    return m_compassProcessMode;
  }

  void State::SetCompassProcessMode(ECompassProcessMode mode)
  {
    m_compassProcessMode = mode;
  }

  void State::OnLocationStatusChanged(location::TLocationStatus newStatus)
  {
    switch (newStatus)
    {
    case location::EStarted:

      if (m_locationProcessMode != ELocationSkipCentering)
        m_locationProcessMode = ELocationCenterAndScale;
      break;

    case location::EFirstEvent:

      if (m_locationProcessMode != ELocationSkipCentering)
      {
        // set centering mode for the first location
        m_locationProcessMode = ELocationCenterAndScale;
        m_compassProcessMode = ECompassDoNothing;
      }
      break;

    default:
      m_locationProcessMode = ELocationDoNothing;
      TurnOff();
    }

    m_framework->Invalidate();
  }

  void State::OnGpsUpdate(location::GpsInfo const & info)
  {
    double lon = info.m_longitude;
    double lat = info.m_latitude;

    m2::RectD rect = MercatorBounds::MetresToXY(lon, lat, info.m_horizontalAccuracy);
    m2::PointD const center = rect.Center();

    m_hasPosition = true;
    setIsVisible(true);
    m_position = center;
    m_errorRadius = rect.SizeX() / 2;

    switch (m_locationProcessMode)
    {
    case ELocationCenterAndScale:
    {
      int const rectScale = scales::GetScaleLevel(rect);
      int setScale = -1;

      // correct rect scale if country isn't downloaded
      int const upperScale = scales::GetUpperWorldScale();
      if (rectScale > upperScale && !m_framework->IsCountryLoaded(center))
        setScale = upperScale;
      else
      {
        // correct rect scale for best user experience
        int const bestScale = scales::GetUpperScale() - 1;
        if (rectScale > bestScale)
          setScale = bestScale;
      }

      if (setScale != -1)
        rect = scales::GetRectForLevel(setScale, center, 1.0);

      double a = m_framework->GetNavigator().Screen().GetAngle();
      double dx = rect.SizeX();
      double dy = rect.SizeY();

      m_framework->ShowRectFixed(m2::AnyRectD(rect.Center(), a, m2::RectD(-dx/2, -dy/2, dx/2, dy/2)));

      SetIsCentered(true);
      CheckCompassRotation();
      CheckFollowCompass();

      m_locationProcessMode = ELocationCenterOnly;
      break;
    }

    case ELocationCenterOnly:
      m_framework->SetViewportCenter(center);

      SetIsCentered(true);
      CheckCompassRotation();
      CheckFollowCompass();

      break;

    case ELocationSkipCentering:
      SetIsCentered(false);
      m_locationProcessMode = ELocationDoNothing;
      break;

    case ELocationDoNothing:
      break;
    }

    m_framework->Invalidate();
  }

  void State::OnCompassUpdate(location::CompassInfo const & info)
  {
    m_hasCompass = true;

    m_compassFilter.OnCompassUpdate(info);

    CheckCompassRotation();
    CheckFollowCompass();

    m_framework->Invalidate();
  }

  vector<m2::AnyRectD> const & State::boundRects() const
  {
    if (isDirtyRect())
    {
      m_boundRects[0] = m2::AnyRectD(m_boundRect);
      setIsDirtyRect(false);
    }

    return m_boundRects;
  }

  void State::cacheArrowBorder(EState state)
  {
    yg::gl::Screen * cacheScreen = m_controller->GetCacheScreen();

    shared_ptr<yg::gl::DisplayList> & dl = m_arrowBorderLists[state];

    dl.reset();
    dl.reset(cacheScreen->createDisplayList());

    cacheScreen->beginFrame();
    cacheScreen->setDisplayList(dl.get());

    shared_ptr<yg::Skin> const & skin = cacheScreen->skin();

    double k = m_controller->GetVisualScale();

    m2::PointD ptsD[5] =
    {
      m2::PointD(0, 0),
      m2::PointD(-(m_arrowWidth * k) / 2, (m_arrowBackHeight * k)),
      m2::PointD(0, -m_arrowHeight * k + m_arrowBackHeight * k),
      m2::PointD((m_arrowWidth * k) / 2, m_arrowBackHeight * k),
      m2::PointD(0, 0)
    };

    yg::Color borderColor = m_locationAreaColor;
    borderColor.a = 255;

    uint32_t penStyle = skin->mapPenInfo(yg::PenInfo(borderColor, 1 * k, 0, 0, 0));

    cacheScreen->drawPath(ptsD, 5, 0, penStyle, depth());

    cacheScreen->setDisplayList(0);
    cacheScreen->endFrame();
  }

  void State::cacheArrowBody(EState state)
  {
    yg::gl::Screen * cacheScreen = m_controller->GetCacheScreen();

    shared_ptr<yg::gl::DisplayList> & dl = m_arrowBodyLists[state];

    dl.reset();
    dl.reset(cacheScreen->createDisplayList());

    cacheScreen->beginFrame();
    cacheScreen->setDisplayList(dl.get());

    double k = m_controller->GetVisualScale();

    m2::PointF pts[4] =
    {
      m2::PointF(0, 0),
      m2::PointF(-(m_arrowWidth * k) / 2, (m_arrowBackHeight * k)),
      m2::PointF(0, -m_arrowHeight * k + m_arrowBackHeight * k),
      m2::PointF((m_arrowWidth * k) / 2, m_arrowBackHeight * k),
    };

    shared_ptr<yg::Skin> const & skin = cacheScreen->skin();

    uint32_t colorStyle = skin->mapColor(color(state));

    cacheScreen->drawTrianglesFan(pts, 4,
                                  colorStyle,
                                  depth());

    cacheScreen->setDisplayList(0);
    cacheScreen->endFrame();
  }

  void State::cache()
  {
    cacheArrowBody(EActive);
    cacheArrowBorder(EActive);
    cacheArrowBody(EPressed);
    cacheArrowBorder(EPressed);

    m_controller->GetCacheScreen()->completeCommands();
  }

  void State::purge()
  {
    m_arrowBorderLists.clear();
    m_arrowBodyLists.clear();
  }

  void State::update()
  {
    m2::PointD const pxPosition = m_framework->GetNavigator().GtoP(Position());

    setPivot(pxPosition);

    double const pxErrorRadius = pxPosition.Length(m_framework->GetNavigator().GtoP(Position() + m2::PointD(m_errorRadius, 0.0)));

    m2::RectD newRect(pxPosition - m2::PointD(pxErrorRadius, pxErrorRadius),
                      pxPosition + m2::PointD(pxErrorRadius, pxErrorRadius));

    double const pxArrowRadius = m_arrowHeight * m_controller->GetVisualScale();

    m2::RectD arrowRect(pxPosition - m2::PointD(pxArrowRadius, pxArrowRadius),
                        pxPosition + m2::PointD(pxArrowRadius, pxArrowRadius));

    newRect.Add(arrowRect);

    if (newRect != m_boundRect)
    {
      m_boundRect = newRect;
      setIsDirtyRect(true);
    }
  }

  void State::draw(yg::gl::OverlayRenderer * r,
                   math::Matrix<double, 3, 3> const & m) const
  {
    if (isVisible())
    {
      checkDirtyDrawing();

      if (m_hasPosition)
      {
        double screenAngle = m_framework->GetNavigator().Screen().GetAngle();
        math::Matrix<double, 3, 3> compassDrawM;

        /// drawing border first
        if (m_hasCompass)
        {
          double const headingRad = m_drawHeading;

          double k = m_controller->GetVisualScale();

          compassDrawM =
              math::Shift(
                math::Rotate(
                  math::Shift(
                    math::Identity<double, 3>(),
                    m2::PointD(0, 0.4 * m_arrowHeight * k - m_arrowBackHeight * k)),
                  screenAngle + headingRad),
                pivot());

          map<EState, shared_ptr<yg::gl::DisplayList> >::const_iterator it;
          it = m_arrowBodyLists.find(state());

          if (it != m_arrowBodyLists.end())
            it->second->draw(compassDrawM * m);
          else
            LOG(LWARNING, ("m_compassDisplayLists[state()] is not set!"));
        }

        /// then position
        m2::PointD const pxPosition = m_framework->GetNavigator().GtoP(Position());
        double const pxErrorRadius = pxPosition.Length(
              m_framework->GetNavigator().GtoP(Position() + m2::PointD(m_errorRadius, 0.0)));

        if (!m_hasCompass)
          r->drawSymbol(pxPosition,
                       "current-position",
                        yg::EPosCenter,
                        depth() - 2);

        r->fillSector(pxPosition,
                      0, 2.0 * math::pi,
                      pxErrorRadius,
                      m_locationAreaColor,
                      depth() - 3);

        if (m_hasCompass)
        {
          map<EState, shared_ptr<yg::gl::DisplayList> >::const_iterator it;
          it = m_arrowBorderLists.find(state());

          if (it != m_arrowBorderLists.end())
            it->second->draw(compassDrawM * m);
          else
            LOG(LWARNING, ("m_arrowBorderLists[state()] is not set!"));
        }
      }
    }
  }

  bool State::hitTest(m2::PointD const & pt) const
  {
    double radius = m_arrowHeight * m_controller->GetVisualScale();

    return m_hasCompass && (pt.SquareLength(pivot()) <= my::sq(radius));
  }

  void State::CheckCompassRotation()
  {
#ifndef OMIM_OS_IPHONE

    if (m_headingInterpolation)
      m_headingInterpolation->Lock();

    double headingDelta = 0;
    bool isRunning = m_headingInterpolation
                  && m_headingInterpolation->IsRunning();

    if (isRunning)
      headingDelta = fabs(ang::GetShortestDistance(m_headingInterpolation->EndAngle(), m_compassFilter.GetHeadingRad()));

    if (floor(ang::RadToDegree(headingDelta)) > 0)
      m_headingInterpolation->SetEndAngle(m_compassFilter.GetHeadingRad());
    else
    {
      if (!isRunning)
      {
        headingDelta = fabs(ang::GetShortestDistance(m_drawHeading, m_compassFilter.GetHeadingRad()));

        if (my::rounds(ang::RadToDegree(headingDelta)) > 0)
        {
          if (m_headingInterpolation
           &&!m_headingInterpolation->IsCancelled()
           &&!m_headingInterpolation->IsEnded())
          {
            m_headingInterpolation->Unlock();
            m_headingInterpolation->Cancel();
            m_headingInterpolation.reset();
          }

          m_headingInterpolation.reset(new anim::AngleInterpolation(m_drawHeading,
                                                                    m_compassFilter.GetHeadingRad(),
                                                                    1,
                                                                    m_drawHeading));

          m_framework->GetAnimController()->AddTask(m_headingInterpolation);
          return;
        }
      }
    }

    if (m_headingInterpolation)
      m_headingInterpolation->Unlock();

#else
    m_drawHeading = m_compassFilter.GetHeadingRad();
#endif
  }

  void State::CheckFollowCompass()
  {
    if (m_hasCompass
    && (CompassProcessMode() == ECompassFollow)
    && IsCentered())
      FollowCompass();
  }

  void State::FollowCompass()
  {
    if (!m_framework->GetNavigator().DoSupportRotation())
      return;

    anim::Controller * controller = m_framework->GetAnimController();

    controller->Lock();

    double startAngle = m_framework->GetNavigator().Screen().GetAngle();
    double endAngle = -m_compassFilter.GetHeadingRad();

    m_framework->GetAnimator().RotateScreen(startAngle, endAngle, 2);

    controller->Unlock();
  }

  void State::MarkCenteredAndFollowCompass()
  {
    m_isCentered = true;
    SetCompassProcessMode(ECompassFollow);
    FollowCompass();
    (void)Settings::Set("SuggestAutoFollowMode", false);
  }

  void State::CenterScreenAndEnqueueFollowing()
  {
    anim::Controller * controller = m_framework->GetAnimController();

    controller->Lock();

    m2::AnyRectD startRect = m_framework->GetNavigator().Screen().GlobalRect();
    m2::AnyRectD endRect = m2::AnyRectD(Position(),
                                        -m_compassFilter.GetHeadingRad(),
                                        m2::RectD(startRect.GetLocalRect()));

    shared_ptr<ChangeViewportTask> const & t = m_framework->GetAnimator().ChangeViewport(startRect, endRect, 2);

    t->Lock();
    t->SetCallback(anim::Task::EEnded, bind(&State::MarkCenteredAndFollowCompass, this));
    t->Unlock();

    controller->Unlock();
  }

  void State::StopCompassFollowing()
  {
    SetCompassProcessMode(ECompassDoNothing);
    m_framework->GetAnimator().StopRotation();
    m_framework->GetAnimator().StopChangeViewport();
    setState(EActive);
  }

  bool State::IsCentered() const
  {
    return m_isCentered;
  }

  void State::SetIsCentered(bool flag)
  {
    m_isCentered = flag;
  }

  bool State::onTapEnded(m2::PointD const & pt)
  {
    if (!m_framework->GetNavigator().DoSupportRotation())
      return false;

    anim::Controller * controller = m_framework->GetAnimController();

    controller->Lock();

    switch (state())
    {
    case EActive:
      if (m_hasCompass)
      {
        if (!IsCentered())
          CenterScreenAndEnqueueFollowing();
        else
        {
          SetCompassProcessMode(ECompassFollow);
          FollowCompass();

          (void)Settings::Set("SuggestAutoFollowMode", false);
        }

        setState(EPressed);
      }
      break;
    case EPressed:
      setState(EActive);
      StopCompassFollowing();
      break;
    default:
      LOG(LWARNING, ("not-used EState values encountered"));
    };

    controller->Unlock();

    m_framework->Invalidate();

    return true;
  }
}
<commit_msg>turned off location::State visibility at construction time.<commit_after>#include "location_state.hpp"
#include "navigator.hpp"
#include "framework.hpp"
#include "compass_filter.hpp"
#include "rotate_screen_task.hpp"
#include "change_viewport_task.hpp"

#include "../yg/display_list.hpp"
#include "../yg/skin.hpp"

#include "../anim/controller.hpp"
#include "../anim/angle_interpolation.hpp"

#include "../gui/controller.hpp"

#include "../platform/location.hpp"
#include "../platform/platform.hpp"
#include "../platform/settings.hpp"

#include "../geometry/rect2d.hpp"
#include "../geometry/transformations.hpp"

#include "../indexer/mercator.hpp"

namespace location
{
  State::State(Params const & p)
    : base_t(p),
      m_hasPosition(false),
      m_hasCompass(false),
      m_isCentered(false),
      m_locationProcessMode(ELocationDoNothing),
      m_compassProcessMode(ECompassDoNothing)
  {
    m_drawHeading = m_compassFilter.GetHeadingRad();
    m_locationAreaColor = p.m_locationAreaColor;
    m_locationBorderColor = p.m_locationBorderColor;
    m_compassAreaColor = p.m_compassAreaColor;
    m_compassBorderColor = p.m_compassBorderColor;
    m_framework = p.m_framework;
    m_arrowScale = 0.7;
    m_arrowWidth = 40 * m_arrowScale;
    m_arrowHeight = 50 * m_arrowScale;
    m_arrowBackHeight = 10 * m_arrowScale;
    m_boundRects.resize(1);

    setColor(EActive, yg::Color(0x2f, 0xb5, 0xea, 128));
    setColor(EPressed, yg::Color(0x1f, 0x22, 0x59, 128));
    setState(EActive);
    setIsVisible(false);
  }

  bool State::HasPosition() const
  {
    return m_hasPosition;
  }

  m2::PointD const & State::Position() const
  {
    return m_position;
  }

  bool State::HasCompass() const
  {
    return m_hasCompass;
  }

  void State::TurnOff()
  {
    m_hasPosition = false;
    m_hasCompass = false;
    setIsVisible(false);
  }

  void State::SkipLocationCentering()
  {
    m_locationProcessMode = ELocationSkipCentering;
  }

  ELocationProcessMode State::LocationProcessMode() const
  {
    return m_locationProcessMode;
  }

  void State::SetLocationProcessMode(ELocationProcessMode mode)
  {
    m_locationProcessMode = mode;
  }

  ECompassProcessMode State::CompassProcessMode() const
  {
    return m_compassProcessMode;
  }

  void State::SetCompassProcessMode(ECompassProcessMode mode)
  {
    m_compassProcessMode = mode;
  }

  void State::OnLocationStatusChanged(location::TLocationStatus newStatus)
  {
    switch (newStatus)
    {
    case location::EStarted:

      if (m_locationProcessMode != ELocationSkipCentering)
        m_locationProcessMode = ELocationCenterAndScale;
      break;

    case location::EFirstEvent:

      if (m_locationProcessMode != ELocationSkipCentering)
      {
        // set centering mode for the first location
        m_locationProcessMode = ELocationCenterAndScale;
        m_compassProcessMode = ECompassDoNothing;
      }
      break;

    default:
      m_locationProcessMode = ELocationDoNothing;
      TurnOff();
    }

    m_framework->Invalidate();
  }

  void State::OnGpsUpdate(location::GpsInfo const & info)
  {
    double lon = info.m_longitude;
    double lat = info.m_latitude;

    m2::RectD rect = MercatorBounds::MetresToXY(lon, lat, info.m_horizontalAccuracy);
    m2::PointD const center = rect.Center();

    m_hasPosition = true;
    setIsVisible(true);
    m_position = center;
    m_errorRadius = rect.SizeX() / 2;

    switch (m_locationProcessMode)
    {
    case ELocationCenterAndScale:
    {
      int const rectScale = scales::GetScaleLevel(rect);
      int setScale = -1;

      // correct rect scale if country isn't downloaded
      int const upperScale = scales::GetUpperWorldScale();
      if (rectScale > upperScale && !m_framework->IsCountryLoaded(center))
        setScale = upperScale;
      else
      {
        // correct rect scale for best user experience
        int const bestScale = scales::GetUpperScale() - 1;
        if (rectScale > bestScale)
          setScale = bestScale;
      }

      if (setScale != -1)
        rect = scales::GetRectForLevel(setScale, center, 1.0);

      double a = m_framework->GetNavigator().Screen().GetAngle();
      double dx = rect.SizeX();
      double dy = rect.SizeY();

      m_framework->ShowRectFixed(m2::AnyRectD(rect.Center(), a, m2::RectD(-dx/2, -dy/2, dx/2, dy/2)));

      SetIsCentered(true);
      CheckCompassRotation();
      CheckFollowCompass();

      m_locationProcessMode = ELocationCenterOnly;
      break;
    }

    case ELocationCenterOnly:
      m_framework->SetViewportCenter(center);

      SetIsCentered(true);
      CheckCompassRotation();
      CheckFollowCompass();

      break;

    case ELocationSkipCentering:
      SetIsCentered(false);
      m_locationProcessMode = ELocationDoNothing;
      break;

    case ELocationDoNothing:
      break;
    }

    m_framework->Invalidate();
  }

  void State::OnCompassUpdate(location::CompassInfo const & info)
  {
    m_hasCompass = true;

    m_compassFilter.OnCompassUpdate(info);

    CheckCompassRotation();
    CheckFollowCompass();

    m_framework->Invalidate();
  }

  vector<m2::AnyRectD> const & State::boundRects() const
  {
    if (isDirtyRect())
    {
      m_boundRects[0] = m2::AnyRectD(m_boundRect);
      setIsDirtyRect(false);
    }

    return m_boundRects;
  }

  void State::cacheArrowBorder(EState state)
  {
    yg::gl::Screen * cacheScreen = m_controller->GetCacheScreen();

    shared_ptr<yg::gl::DisplayList> & dl = m_arrowBorderLists[state];

    dl.reset();
    dl.reset(cacheScreen->createDisplayList());

    cacheScreen->beginFrame();
    cacheScreen->setDisplayList(dl.get());

    shared_ptr<yg::Skin> const & skin = cacheScreen->skin();

    double k = m_controller->GetVisualScale();

    m2::PointD ptsD[5] =
    {
      m2::PointD(0, 0),
      m2::PointD(-(m_arrowWidth * k) / 2, (m_arrowBackHeight * k)),
      m2::PointD(0, -m_arrowHeight * k + m_arrowBackHeight * k),
      m2::PointD((m_arrowWidth * k) / 2, m_arrowBackHeight * k),
      m2::PointD(0, 0)
    };

    yg::Color borderColor = m_locationAreaColor;
    borderColor.a = 255;

    uint32_t penStyle = skin->mapPenInfo(yg::PenInfo(borderColor, 1 * k, 0, 0, 0));

    cacheScreen->drawPath(ptsD, 5, 0, penStyle, depth());

    cacheScreen->setDisplayList(0);
    cacheScreen->endFrame();
  }

  void State::cacheArrowBody(EState state)
  {
    yg::gl::Screen * cacheScreen = m_controller->GetCacheScreen();

    shared_ptr<yg::gl::DisplayList> & dl = m_arrowBodyLists[state];

    dl.reset();
    dl.reset(cacheScreen->createDisplayList());

    cacheScreen->beginFrame();
    cacheScreen->setDisplayList(dl.get());

    double k = m_controller->GetVisualScale();

    m2::PointF pts[4] =
    {
      m2::PointF(0, 0),
      m2::PointF(-(m_arrowWidth * k) / 2, (m_arrowBackHeight * k)),
      m2::PointF(0, -m_arrowHeight * k + m_arrowBackHeight * k),
      m2::PointF((m_arrowWidth * k) / 2, m_arrowBackHeight * k),
    };

    shared_ptr<yg::Skin> const & skin = cacheScreen->skin();

    uint32_t colorStyle = skin->mapColor(color(state));

    cacheScreen->drawTrianglesFan(pts, 4,
                                  colorStyle,
                                  depth());

    cacheScreen->setDisplayList(0);
    cacheScreen->endFrame();
  }

  void State::cache()
  {
    cacheArrowBody(EActive);
    cacheArrowBorder(EActive);
    cacheArrowBody(EPressed);
    cacheArrowBorder(EPressed);

    m_controller->GetCacheScreen()->completeCommands();
  }

  void State::purge()
  {
    m_arrowBorderLists.clear();
    m_arrowBodyLists.clear();
  }

  void State::update()
  {
    m2::PointD const pxPosition = m_framework->GetNavigator().GtoP(Position());

    setPivot(pxPosition);

    double const pxErrorRadius = pxPosition.Length(m_framework->GetNavigator().GtoP(Position() + m2::PointD(m_errorRadius, 0.0)));

    m2::RectD newRect(pxPosition - m2::PointD(pxErrorRadius, pxErrorRadius),
                      pxPosition + m2::PointD(pxErrorRadius, pxErrorRadius));

    double const pxArrowRadius = m_arrowHeight * m_controller->GetVisualScale();

    m2::RectD arrowRect(pxPosition - m2::PointD(pxArrowRadius, pxArrowRadius),
                        pxPosition + m2::PointD(pxArrowRadius, pxArrowRadius));

    newRect.Add(arrowRect);

    if (newRect != m_boundRect)
    {
      m_boundRect = newRect;
      setIsDirtyRect(true);
    }
  }

  void State::draw(yg::gl::OverlayRenderer * r,
                   math::Matrix<double, 3, 3> const & m) const
  {
    if (isVisible())
    {
      checkDirtyDrawing();

      if (m_hasPosition)
      {
        double screenAngle = m_framework->GetNavigator().Screen().GetAngle();
        math::Matrix<double, 3, 3> compassDrawM;

        /// drawing border first
        if (m_hasCompass)
        {
          double const headingRad = m_drawHeading;

          double k = m_controller->GetVisualScale();

          compassDrawM =
              math::Shift(
                math::Rotate(
                  math::Shift(
                    math::Identity<double, 3>(),
                    m2::PointD(0, 0.4 * m_arrowHeight * k - m_arrowBackHeight * k)),
                  screenAngle + headingRad),
                pivot());

          map<EState, shared_ptr<yg::gl::DisplayList> >::const_iterator it;
          it = m_arrowBodyLists.find(state());

          if (it != m_arrowBodyLists.end())
            it->second->draw(compassDrawM * m);
          else
            LOG(LWARNING, ("m_compassDisplayLists[state()] is not set!"));
        }

        /// then position
        m2::PointD const pxPosition = m_framework->GetNavigator().GtoP(Position());
        double const pxErrorRadius = pxPosition.Length(
              m_framework->GetNavigator().GtoP(Position() + m2::PointD(m_errorRadius, 0.0)));

        if (!m_hasCompass)
          r->drawSymbol(pxPosition,
                       "current-position",
                        yg::EPosCenter,
                        depth() - 2);

        r->fillSector(pxPosition,
                      0, 2.0 * math::pi,
                      pxErrorRadius,
                      m_locationAreaColor,
                      depth() - 3);

        if (m_hasCompass)
        {
          map<EState, shared_ptr<yg::gl::DisplayList> >::const_iterator it;
          it = m_arrowBorderLists.find(state());

          if (it != m_arrowBorderLists.end())
            it->second->draw(compassDrawM * m);
          else
            LOG(LWARNING, ("m_arrowBorderLists[state()] is not set!"));
        }
      }
    }
  }

  bool State::hitTest(m2::PointD const & pt) const
  {
    double radius = m_arrowHeight * m_controller->GetVisualScale();

    return m_hasCompass && (pt.SquareLength(pivot()) <= my::sq(radius));
  }

  void State::CheckCompassRotation()
  {
#ifndef OMIM_OS_IPHONE

    if (m_headingInterpolation)
      m_headingInterpolation->Lock();

    double headingDelta = 0;
    bool isRunning = m_headingInterpolation
                  && m_headingInterpolation->IsRunning();

    if (isRunning)
      headingDelta = fabs(ang::GetShortestDistance(m_headingInterpolation->EndAngle(), m_compassFilter.GetHeadingRad()));

    if (floor(ang::RadToDegree(headingDelta)) > 0)
      m_headingInterpolation->SetEndAngle(m_compassFilter.GetHeadingRad());
    else
    {
      if (!isRunning)
      {
        headingDelta = fabs(ang::GetShortestDistance(m_drawHeading, m_compassFilter.GetHeadingRad()));

        if (my::rounds(ang::RadToDegree(headingDelta)) > 0)
        {
          if (m_headingInterpolation
           &&!m_headingInterpolation->IsCancelled()
           &&!m_headingInterpolation->IsEnded())
          {
            m_headingInterpolation->Unlock();
            m_headingInterpolation->Cancel();
            m_headingInterpolation.reset();
          }

          m_headingInterpolation.reset(new anim::AngleInterpolation(m_drawHeading,
                                                                    m_compassFilter.GetHeadingRad(),
                                                                    1,
                                                                    m_drawHeading));

          m_framework->GetAnimController()->AddTask(m_headingInterpolation);
          return;
        }
      }
    }

    if (m_headingInterpolation)
      m_headingInterpolation->Unlock();

#else
    m_drawHeading = m_compassFilter.GetHeadingRad();
#endif
  }

  void State::CheckFollowCompass()
  {
    if (m_hasCompass
    && (CompassProcessMode() == ECompassFollow)
    && IsCentered())
      FollowCompass();
  }

  void State::FollowCompass()
  {
    if (!m_framework->GetNavigator().DoSupportRotation())
      return;

    anim::Controller * controller = m_framework->GetAnimController();

    controller->Lock();

    double startAngle = m_framework->GetNavigator().Screen().GetAngle();
    double endAngle = -m_compassFilter.GetHeadingRad();

    m_framework->GetAnimator().RotateScreen(startAngle, endAngle, 2);

    controller->Unlock();
  }

  void State::MarkCenteredAndFollowCompass()
  {
    m_isCentered = true;
    SetCompassProcessMode(ECompassFollow);
    FollowCompass();
    (void)Settings::Set("SuggestAutoFollowMode", false);
  }

  void State::CenterScreenAndEnqueueFollowing()
  {
    anim::Controller * controller = m_framework->GetAnimController();

    controller->Lock();

    m2::AnyRectD startRect = m_framework->GetNavigator().Screen().GlobalRect();
    m2::AnyRectD endRect = m2::AnyRectD(Position(),
                                        -m_compassFilter.GetHeadingRad(),
                                        m2::RectD(startRect.GetLocalRect()));

    shared_ptr<ChangeViewportTask> const & t = m_framework->GetAnimator().ChangeViewport(startRect, endRect, 2);

    t->Lock();
    t->SetCallback(anim::Task::EEnded, bind(&State::MarkCenteredAndFollowCompass, this));
    t->Unlock();

    controller->Unlock();
  }

  void State::StopCompassFollowing()
  {
    SetCompassProcessMode(ECompassDoNothing);
    m_framework->GetAnimator().StopRotation();
    m_framework->GetAnimator().StopChangeViewport();
    setState(EActive);
  }

  bool State::IsCentered() const
  {
    return m_isCentered;
  }

  void State::SetIsCentered(bool flag)
  {
    m_isCentered = flag;
  }

  bool State::onTapEnded(m2::PointD const & pt)
  {
    if (!m_framework->GetNavigator().DoSupportRotation())
      return false;

    anim::Controller * controller = m_framework->GetAnimController();

    controller->Lock();

    switch (state())
    {
    case EActive:
      if (m_hasCompass)
      {
        if (!IsCentered())
          CenterScreenAndEnqueueFollowing();
        else
        {
          SetCompassProcessMode(ECompassFollow);
          FollowCompass();

          (void)Settings::Set("SuggestAutoFollowMode", false);
        }

        setState(EPressed);
      }
      break;
    case EPressed:
      setState(EActive);
      StopCompassFollowing();
      break;
    default:
      LOG(LWARNING, ("not-used EState values encountered"));
    };

    controller->Unlock();

    m_framework->Invalidate();

    return true;
  }
}
<|endoftext|>


<commit_before>#include "llvm/IR/DataLayout.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"

#include "llvm/Pass.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Transforms/Utils/Cloning.h"

#include "llvm/Support/CommandLine.h"

using namespace llvm;

static cl::opt<unsigned> UnrollCount("sbt-loop-unroll-count",
                                   cl::desc("The number of loop unrollings"),
                                   cl::value_desc("N"));

static cl::opt<bool> TerminateLoop("sbt-loop-unroll-terminate",
                                    cl::desc("Terminate the paths that exceed the "
                                             "unrolling count."));

namespace {
  class LoopUnroll : public LoopPass {
    public:
      static char ID;

      LoopUnroll() : LoopPass(ID) {}

      bool runOnLoop(Loop *, LPPassManager&) override;
  };
}

static RegisterPass<LoopUnroll> SLU("sbt-loop-unroll",
                                    "Unroll loops in the program");
char LoopUnroll::ID;

bool CloneMetadata(const llvm::Instruction *, llvm::Instruction *);

static BasicBlock *createTerminatingBlock(Function *F,
                                          Instruction *I) {
  auto M = F->getParent();
  LLVMContext& Ctx = M->getContext();
  BasicBlock *block = BasicBlock::Create(Ctx, "loop_term");

  F->getBasicBlockList().push_back(block);

  auto assume = M->getOrInsertFunction("__VERIFIER_assume",
                                       Type::getVoidTy(Ctx),
                                       Type::getInt32Ty(Ctx)
#if LLVM_VERSION_MAJOR < 5
                                       , nullptr
#endif
                         );
  // The contents of the block is:
  //  __VERIFIER_assume(0)
  //  unreachable
  auto CI
    = CallInst::Create(assume, {ConstantInt::get(Type::getInt32Ty(Ctx), 0)},
                       "", block);
  new UnreachableInst(Ctx, block);

  // take the metadata from I, some passes would consider the module
  // broken without the metadata
  if (!CloneMetadata(I, CI)) {
      llvm::errs() << "[Unrolling] Failed assigning metadata to: " << *CI << "\n";
  }

  return block;
}

// redirect node successors
static void redirectEdges(const BasicBlock *origB,
                          BasicBlock *newB,
                          const std::map<BasicBlock *, BasicBlock *>& BlocksMap) {
  auto origTI = origB->getTerminator();
  auto newTI = newB->getTerminator();

  // copy the metadata from origTI,
  // some passes would consider the module
  // broken without the metadata
  if (!CloneMetadata(origTI, newTI)) {
      llvm::errs() << "[Unrolling] Failed assigning metadata to: " << *newTI << "\n";
  }

  for (unsigned i = 0; i < origTI->getNumSuccessors(); ++i) {
      auto it = BlocksMap.find(origTI->getSuccessor(i));
      if (it != BlocksMap.end()) {
        assert(it->second != nullptr);
        newTI->setSuccessor(i, it->second);
      }
  }
}

static void replaceSuccessor(const std::vector<BasicBlock *>& Blocks,
                             BasicBlock *oldB, BasicBlock *newB) {
  for (auto i = 0; i < Blocks.size(); ++i) {
    auto origTI = Blocks[i]->getTerminator();
    for (unsigned i = 0; i < origTI->getNumSuccessors(); ++i) {
      auto succ = origTI->getSuccessor(i);
      // do we jump on the header?
      if (succ == oldB) {
          origTI->setSuccessor(i, newB);
      }
    }
  }
}

// redirect value uses and PHI nodes
static void redirectValues(BasicBlock *newB,
                           ValueToValueMapTy& VMap,
                           const std::map<BasicBlock *, BasicBlock *>& BlocksMap) {

  for (auto& I : *newB) {
    if (auto PHI = dyn_cast<PHINode>(&I)) {
      llvm::errs() << "PHI nodes are not supported yet\n";
      abort();
     //for (auto i = 0; i < PHI->getNumIncomingValues(); ++i) {
     //}
    } else {
      for (auto i = 0; i < I.getNumOperands(); ++i) {
        if (VMap.count(I.getOperand(i))) {
          I.setOperand(i, VMap[I.getOperand(i)]);
        }
      }
    }
  }
}

static std::vector<BasicBlock *>
cloneLoopBody(Function *F, const std::vector<BasicBlock *> Blocks) {

  ValueToValueMapTy VMap;
  std::map<BasicBlock *, BasicBlock *> BlocksMap;

  // clone the blocks
  std::vector<BasicBlock *> NewBlocks;
  NewBlocks.reserve(Blocks.size());
  for (auto Block : Blocks) {
    NewBlocks.push_back(CloneBasicBlock(Block, VMap));
    BlocksMap[Block] = NewBlocks.back();

    F->getBasicBlockList().push_back(NewBlocks.back());
  }

  // we got new basic blocks, now redirect the edges
  // and PHI values and such
  for (auto i = 0; i < Blocks.size(); ++i) {
      redirectEdges(Blocks[i], NewBlocks[i], BlocksMap);
      redirectValues(NewBlocks[i], VMap, BlocksMap);
  }

  // reconnect the exit nodes from the old loop body
  // to the header of the new body
  replaceSuccessor(Blocks, Blocks[0], NewBlocks[0]);

  return NewBlocks;
}

bool LoopUnroll::runOnLoop(Loop *L, LPPassManager& LPM) {

  if (UnrollCount <= 1)
    return false;

  auto F = (*L->block_begin())->getParent();
  const auto& Blocks = L->getBlocks();

  std::vector<BasicBlock *> LastBlocks(Blocks.begin(), Blocks.end());
  // the code relies on the fact that the header is the first
  // basic block in the vector
  if (LastBlocks[0] != L->getHeader())
      abort();

  for (unsigned n = 1; n < UnrollCount; ++n)
      LastBlocks = cloneLoopBody(F, LastBlocks);

  // replace the next iterations with assume(false) if desired
  if (TerminateLoop) {
    auto termB = createTerminatingBlock(F, LastBlocks[0]->getTerminator());
    replaceSuccessor(LastBlocks, LastBlocks[0], termB);
  }

  return true;
}
<commit_msg>transforms: Fix -Wsign-compare warning<commit_after>#include "llvm/IR/DataLayout.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"

#include "llvm/Pass.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Transforms/Utils/Cloning.h"

#include "llvm/Support/CommandLine.h"

using namespace llvm;

static cl::opt<unsigned> UnrollCount("sbt-loop-unroll-count",
                                   cl::desc("The number of loop unrollings"),
                                   cl::value_desc("N"));

static cl::opt<bool> TerminateLoop("sbt-loop-unroll-terminate",
                                    cl::desc("Terminate the paths that exceed the "
                                             "unrolling count."));

namespace {
  class LoopUnroll : public LoopPass {
    public:
      static char ID;

      LoopUnroll() : LoopPass(ID) {}

      bool runOnLoop(Loop *, LPPassManager&) override;
  };
}

static RegisterPass<LoopUnroll> SLU("sbt-loop-unroll",
                                    "Unroll loops in the program");
char LoopUnroll::ID;

bool CloneMetadata(const llvm::Instruction *, llvm::Instruction *);

static BasicBlock *createTerminatingBlock(Function *F,
                                          Instruction *I) {
  auto M = F->getParent();
  LLVMContext& Ctx = M->getContext();
  BasicBlock *block = BasicBlock::Create(Ctx, "loop_term");

  F->getBasicBlockList().push_back(block);

  auto assume = M->getOrInsertFunction("__VERIFIER_assume",
                                       Type::getVoidTy(Ctx),
                                       Type::getInt32Ty(Ctx)
#if LLVM_VERSION_MAJOR < 5
                                       , nullptr
#endif
                         );
  // The contents of the block is:
  //  __VERIFIER_assume(0)
  //  unreachable
  auto CI
    = CallInst::Create(assume, {ConstantInt::get(Type::getInt32Ty(Ctx), 0)},
                       "", block);
  new UnreachableInst(Ctx, block);

  // take the metadata from I, some passes would consider the module
  // broken without the metadata
  if (!CloneMetadata(I, CI)) {
      llvm::errs() << "[Unrolling] Failed assigning metadata to: " << *CI << "\n";
  }

  return block;
}

// redirect node successors
static void redirectEdges(const BasicBlock *origB,
                          BasicBlock *newB,
                          const std::map<BasicBlock *, BasicBlock *>& BlocksMap) {
  auto origTI = origB->getTerminator();
  auto newTI = newB->getTerminator();

  // copy the metadata from origTI,
  // some passes would consider the module
  // broken without the metadata
  if (!CloneMetadata(origTI, newTI)) {
      llvm::errs() << "[Unrolling] Failed assigning metadata to: " << *newTI << "\n";
  }

  for (unsigned i = 0; i < origTI->getNumSuccessors(); ++i) {
      auto it = BlocksMap.find(origTI->getSuccessor(i));
      if (it != BlocksMap.end()) {
        assert(it->second != nullptr);
        newTI->setSuccessor(i, it->second);
      }
  }
}

static void replaceSuccessor(const std::vector<BasicBlock *>& Blocks,
                             BasicBlock *oldB, BasicBlock *newB) {
  for (size_t i = 0; i < Blocks.size(); ++i) {
    auto origTI = Blocks[i]->getTerminator();
    for (unsigned i = 0; i < origTI->getNumSuccessors(); ++i) {
      auto succ = origTI->getSuccessor(i);
      // do we jump on the header?
      if (succ == oldB) {
          origTI->setSuccessor(i, newB);
      }
    }
  }
}

// redirect value uses and PHI nodes
static void redirectValues(BasicBlock *newB,
                           ValueToValueMapTy& VMap,
                           const std::map<BasicBlock *, BasicBlock *>& BlocksMap) {

  for (auto& I : *newB) {
    if (auto PHI = dyn_cast<PHINode>(&I)) {
      llvm::errs() << "PHI nodes are not supported yet\n";
      abort();
     //for (auto i = 0; i < PHI->getNumIncomingValues(); ++i) {
     //}
    } else {
      for (unsigned i = 0; i < I.getNumOperands(); ++i) {
        if (VMap.count(I.getOperand(i))) {
          I.setOperand(i, VMap[I.getOperand(i)]);
        }
      }
    }
  }
}

static std::vector<BasicBlock *>
cloneLoopBody(Function *F, const std::vector<BasicBlock *> Blocks) {

  ValueToValueMapTy VMap;
  std::map<BasicBlock *, BasicBlock *> BlocksMap;

  // clone the blocks
  std::vector<BasicBlock *> NewBlocks;
  NewBlocks.reserve(Blocks.size());
  for (auto Block : Blocks) {
    NewBlocks.push_back(CloneBasicBlock(Block, VMap));
    BlocksMap[Block] = NewBlocks.back();

    F->getBasicBlockList().push_back(NewBlocks.back());
  }

  // we got new basic blocks, now redirect the edges
  // and PHI values and such
  for (size_t i = 0; i < Blocks.size(); ++i) {
      redirectEdges(Blocks[i], NewBlocks[i], BlocksMap);
      redirectValues(NewBlocks[i], VMap, BlocksMap);
  }

  // reconnect the exit nodes from the old loop body
  // to the header of the new body
  replaceSuccessor(Blocks, Blocks[0], NewBlocks[0]);

  return NewBlocks;
}

bool LoopUnroll::runOnLoop(Loop *L, LPPassManager& LPM) {

  if (UnrollCount <= 1)
    return false;

  auto F = (*L->block_begin())->getParent();
  const auto& Blocks = L->getBlocks();

  std::vector<BasicBlock *> LastBlocks(Blocks.begin(), Blocks.end());
  // the code relies on the fact that the header is the first
  // basic block in the vector
  if (LastBlocks[0] != L->getHeader())
      abort();

  for (unsigned n = 1; n < UnrollCount; ++n)
      LastBlocks = cloneLoopBody(F, LastBlocks);

  // replace the next iterations with assume(false) if desired
  if (TerminateLoop) {
    auto termB = createTerminatingBlock(F, LastBlocks[0]->getTerminator());
    replaceSuccessor(LastBlocks, LastBlocks[0], termB);
  }

  return true;
}
<|endoftext|>


<commit_before>#include <iomanip>
#include <iterator>
#include <numeric>
#include <random>
#include <chrono>

#include "./parser.hpp"
#include "./input.hpp"
#include "./wlconfT.hpp"

constexpr double kb = 0.0000861733; // [eV/K]

void dispInput(std::shared_ptr<Input> in){
	//  [INPUT]
	std::cout << "TMIN          : " << in->getDataByString("TMIN") << std::endl;
	std::cout << "TMAX          : " << in->getDataByString("TMAX") << std::endl;
	std::cout << "TMOVELIMIT    : " << in->getDataByString("TMOVELIMIT") << std::endl;
	std::cout << "BIN           : " << in->getDataByString("BIN")  << std::endl;
	std::cout << "MCSTEP        : " << in->getDataByString("MCSTEP")        << std::endl;
	std::cout << "FLATCHECKSTEP : " << in->getDataByString("FLATCHECKSTEP") << std::endl;
	std::cout << "LOGFACTOR     : " << in->getDataByString("LOGFACTOR")     << std::endl;
	std::cout << "FLATCRITERION : " << in->getDataByString("FLATCRITERION") << std::endl;

	//  [OPTION]
	std::cout << "CHEMIPOT      : " << in->getDataByString("CHEMIPOT")  << std::endl;
	std::cout << "SPININPUT     : " << in->getDataByString("SPININPUT") << std::endl;
	std::cout << "SETRANDOM     : " << in->getDataByString("SETRANDOM") << std::endl;
}

double wl_step_by_T(WLconfT::WLconfT& conf, const std::vector<double>& dos){

	conf.setTotalEnergy();
	double energy = conf.getTotalEnergy();
	int index_before = conf.getIndex();
	int index_after  = index_before;
	double temperature_before = conf.calcTemperature();

	conf.setNewConfByTemperature();
	index_after  = conf.getIndex();
	double temperature_after  = conf.calcTemperature();

	double b_wl = exp( - energy*(1.0/temperature_after-1.0/temperature_before)/kb + dos.at(index_before)-dos.at(index_after));
	if(b_wl>=1.0 or b_wl>conf.RandReal()){
	} else {
		conf.Memento();
	}
	return conf.getTotalEnergy();
}

double wl_step_by_E(WLconfT::WLconfT& conf, const std::vector<double>& dos){

	conf.setTotalEnergy();
	double ene_before = conf.getTotalEnergy();

	conf.setNewConfByEnergy();
	double ene_after  = conf.getTotalEnergy();

	double b_metropolis = exp( -(ene_after-ene_before)/kb/conf.calcTemperature() );
	if(b_metropolis>=1.0 or b_metropolis>conf.RandReal()){
	} else {
		conf.Memento();
	}

	return conf.getTotalEnergy();
}

int main(int argc, char* argv[]){
	std::shared_ptr<Input> in(new Input("directZ.ini"));

	int mcstep, bin, flatcheck_step, minstep=0;
	double logfactor, logflimit, tmin, tmax, tdelta, flat_criterion;
	double low_cutoff = 1.0;
	double probability_move_by_T = 0.0001;
	std::string filename_spin_input;

	in->setData("BIN",  bin, true);
	in->setData("MCSTEP", mcstep, true);

	in->setData("TMIN", tmin, true);
	in->setData("TMAX", tmax, true);
	tdelta = (tmax - tmin) / (double)bin;

	in->setData("LOGFACTOR", logfactor, true);
	in->setData("LOGFLIMIT", logflimit, true);
	in->setData("FLATCRITERION", flat_criterion, true);
	in->setData("PROBABILITYBYT" ,probability_move_by_T, true);

	in->setData("SPININPUT", filename_spin_input);

	in->setData("FLATCHECKSTEP", flatcheck_step);
	in->setData("MINSTEP",   minstep);
	in->setData("LOWCUTOFF", low_cutoff);

	const ParseEcicar ecicar("./ecicar");
	const ParseClusterOut cluster("./cluster.out", ecicar.getIndex());

	WLconfT::WLconfT PoscarSpin("./poscar.spin", in, cluster.getLabel(), cluster.getCluster(), ecicar.getEci(), nullptr, nullptr);

	const int N = PoscarSpin.getSpins().size();

	std::vector<int> index_neglect_bin = PoscarSpin.getNeglectBinIndex();

	std::cout << "----------  initial correlation functions" << std::endl;
	PoscarSpin.dispCorr();
	std::cout << std::endl;
	std::cout << std::endl;

	std::cout << "----------  Information about [directZ.ini]" << std::endl;
	dispInput(in);

	if( index_neglect_bin.size() and  filename_spin_input.size() ){
		std::cout << "NEGLECT BIN INDEX :" << std::endl;
		std::cout << " ";
		for(auto i : index_neglect_bin) std::cout << i << " ";
		std::cout << std::endl;
	}
	std::cout << std::endl;
	std::cout << std::endl;

	auto start = std::chrono::system_clock::now();

	std::cout << "----------  Log  ----------" << std::endl;
	std::cout << std::endl;

	std::vector<double>  dos(bin, 0);

	std::string filename_rep_macrostate = "macrostate.out";
	std::ofstream ofs_macrostate(filename_rep_macrostate);
	ofs_macrostate.setf(std::ios_base::fixed, std::ios_base::floatfield);
	ofs_macrostate.close();

	unsigned int fstep = 0;
	unsigned int tstep = 0;
	unsigned int mc_time = 0;
	bool isConverged = false;

	start = std::chrono::system_clock::now();

	auto f_start = std::chrono::system_clock::now();
	auto f_end   = std::chrono::system_clock::now();

 	int final_mcsweep = 0;
 	while(logflimit < logfactor){
		std::vector<double> histogram(bin, 0);
		std::cout.setf(std::ios_base::fixed, std::ios_base::floatfield);
		std::cout << std::setprecision(10) << "--- fstep " << fstep << " --  log(factor) = " << logfactor << std::endl;
		for(int i=1; ; ++i, ++mc_time){
			for(int j=0; j<N ; ++j){  // スピン数だけステップ回す これで1MCSweep

				int before_index = PoscarSpin.getIndex();

				if( PoscarSpin.RandReal() < probability_move_by_T ) {
					wl_step_by_T(PoscarSpin, dos);

					int index = PoscarSpin.getIndex();

					if( dos[index] == 0 ){
						auto it = find( index_neglect_bin.begin(), index_neglect_bin.end() , index);
						if( it != index_neglect_bin.end() ){
							dos[index] = dos[PoscarSpin.getBeforeIndex()];
							histogram[index] = histogram[PoscarSpin.getBeforeIndex()];
							index_neglect_bin.erase(it);
							PoscarSpin.outputEnergySpin(index, filename_rep_macrostate);
						}
					}

					dos.at(index) += logfactor;
					histogram.at(index) += 1;

				} else {
					wl_step_by_E(PoscarSpin, dos);
				}

			}  /*  end MC sweep */

			if((i % mcstep) == 0){
				WLconfT::outputHistogram(dos,  histogram, tmin, tdelta, fstep);
				std::cout << i << "sweep done " << std::endl;
			}
			if((i % flatcheck_step) == 0 and WLconfT::checkHistogramFlat(histogram, index_neglect_bin, flat_criterion, minstep, low_cutoff)){
				WLconfT::outputHistogram(dos,  histogram, tmin, tdelta, fstep);
				final_mcsweep = i;
				break;
			}
		}
		f_end = std::chrono::system_clock::now();
		auto f_sec = std::chrono::duration_cast<std::chrono::seconds>(f_end-f_start).count();
		std::cout << " fstep = " << fstep << " " << f_sec << " seconds "<< final_mcsweep << " sweeps" << std::endl;
		f_start = std::chrono::system_clock::now();
		logfactor/=2.0;
		++fstep;
	}

	auto end = std::chrono::system_clock::now();
	auto sec = std::chrono::duration_cast<std::chrono::seconds>(end-start).count();
	std::cout << "Time for calculating the DOS is " << sec << " seconds. "<< std::endl;
	std::cout << std::endl;
	std::cout << std::endl;
	std::cout << "check final correlation functions" << std::endl;
	PoscarSpin.dispCorr();
	std::cout << "---------------------------" << std::endl;
	PoscarSpin.setInitialCorrelationFunction();
	PoscarSpin.dispCorr();

	return 0;
}
<commit_msg>revise directZ.cpp and confirm by appling 2dising model<commit_after>#include <iomanip>
#include <iterator>
#include <numeric>
#include <random>
#include <chrono>

#include "./parser.hpp"
#include "./input.hpp"
#include "./wlconfT.hpp"

constexpr double kb = 0.0000861733; // [eV/K]

void dispInput(std::shared_ptr<Input> in){
	//  [INPUT]
	std::cout << "TMIN          : " << in->getDataByString("TMIN") << std::endl;
	std::cout << "TMAX          : " << in->getDataByString("TMAX") << std::endl;
	std::cout << "TMOVELIMIT    : " << in->getDataByString("TMOVELIMIT") << std::endl;
	std::cout << "BIN           : " << in->getDataByString("BIN")  << std::endl;
	std::cout << "MCSTEP        : " << in->getDataByString("MCSTEP")        << std::endl;
	std::cout << "FLATCHECKSTEP : " << in->getDataByString("FLATCHECKSTEP") << std::endl;
	std::cout << "LOGFACTOR     : " << in->getDataByString("LOGFACTOR")     << std::endl;
	std::cout << "FLATCRITERION : " << in->getDataByString("FLATCRITERION") << std::endl;

	//  [OPTION]
	std::cout << "CHEMIPOT      : " << in->getDataByString("CHEMIPOT")  << std::endl;
	std::cout << "SPININPUT     : " << in->getDataByString("SPININPUT") << std::endl;
	std::cout << "SETRANDOM     : " << in->getDataByString("SETRANDOM") << std::endl;
}

double wl_step_by_T(WLconfT::WLconfT& conf, const std::vector<double>& dos){

	conf.setTotalEnergy();
	double energy = conf.getTotalEnergy();
	int index_before = conf.getIndex();
	int index_after  = index_before;
	double temperature_before = conf.calcTemperature();

	conf.setNewConfByTemperature();
	index_after  = conf.getIndex();
	double temperature_after  = conf.calcTemperature();

	double b_wl = exp( - energy*(1.0/temperature_after-1.0/temperature_before)/kb + dos.at(index_before)-dos.at(index_after));
	if(b_wl<conf.RandReal()){
		conf.Memento();
	}
	return conf.getTotalEnergy();
}

double wl_step_by_E(WLconfT::WLconfT& conf, const std::vector<double>& dos){

	conf.setTotalEnergy();
	double ene_before = conf.getTotalEnergy();

	conf.setNewConfByEnergy();
	double ene_after  = conf.getTotalEnergy();

	double b_metropolis = exp( -(ene_after-ene_before)/kb/conf.calcTemperature() );
	if(b_metropolis<conf.RandReal()){
		conf.Memento();
	}

	return conf.getTotalEnergy();
}

int main(int argc, char* argv[]){
	std::shared_ptr<Input> in(new Input("directZ.ini"));

	int mcstep, bin, flatcheck_step, minstep=0;
	double logfactor, logflimit, tmin, tmax, tdelta, flat_criterion;
	double low_cutoff = 1.0;
	double probability_move_by_T = 0.0001;
	std::string filename_spin_input;

	in->setData("BIN",  bin, true);
	in->setData("MCSTEP", mcstep, true);

	in->setData("TMIN", tmin, true);
	in->setData("TMAX", tmax, true);
	tdelta = (tmax - tmin) / (double)bin;

	in->setData("LOGFACTOR", logfactor, true);
	in->setData("LOGFLIMIT", logflimit, true);
	in->setData("FLATCRITERION", flat_criterion, true);
	in->setData("PROBABILITYBYT" ,probability_move_by_T, true);

	in->setData("SPININPUT", filename_spin_input);

	in->setData("FLATCHECKSTEP", flatcheck_step);
	in->setData("MINSTEP",   minstep);
	in->setData("LOWCUTOFF", low_cutoff);

	const ParseEcicar ecicar("./ecicar");
	const ParseClusterOut cluster("./cluster.out", ecicar.getIndex());

	WLconfT::WLconfT PoscarSpin("./poscar.spin", in, cluster.getLabel(), cluster.getCluster(), ecicar.getEci(), nullptr, nullptr);

	const int N = PoscarSpin.getSpins().size();

	std::vector<int> index_neglect_bin = PoscarSpin.getNeglectBinIndex();

	std::cout << "----------  initial correlation functions" << std::endl;
	PoscarSpin.dispCorr();
	std::cout << std::endl;
	std::cout << std::endl;

	std::cout << "----------  Information about [directZ.ini]" << std::endl;
	dispInput(in);

	if( index_neglect_bin.size() and  filename_spin_input.size() ){
		std::cout << "NEGLECT BIN INDEX :" << std::endl;
		std::cout << " ";
		for(auto i : index_neglect_bin) std::cout << i << " ";
		std::cout << std::endl;
	}
	std::cout << std::endl;
	std::cout << std::endl;

	auto start = std::chrono::system_clock::now();

	std::cout << "----------  Log  ----------" << std::endl;
	std::cout << std::endl;

	std::vector<double>  dos(bin, 0);

	std::string filename_rep_macrostate = "macrostate.out";
	std::ofstream ofs_macrostate(filename_rep_macrostate);
	ofs_macrostate.setf(std::ios_base::fixed, std::ios_base::floatfield);
	ofs_macrostate.close();

	unsigned int fstep = 0;
	unsigned int tstep = 0;
	unsigned int mc_time = 0;
	bool isConverged = false;

	start = std::chrono::system_clock::now();

	auto f_start = std::chrono::system_clock::now();
	auto f_end   = std::chrono::system_clock::now();

 	int final_mcsweep = 0;
 	while(logflimit < logfactor){
		std::vector<double> histogram(bin, 0);
		std::cout.setf(std::ios_base::fixed, std::ios_base::floatfield);
		std::cout << std::setprecision(10) << "--- fstep " << fstep << " --  log(factor) = " << logfactor << std::endl;
		for(int i=1; ; ++i, ++mc_time){
			for(int j=0; j<N ; ++j){  // スピン数だけステップ回す これで1MCSweep

				int before_index = PoscarSpin.getIndex();

				if( PoscarSpin.RandReal() < probability_move_by_T ) {
					wl_step_by_T(PoscarSpin, dos);
				} else {
					wl_step_by_E(PoscarSpin, dos);
				}

				int index = PoscarSpin.getIndex();

				if( dos[index] == 0 ){
					auto it = find( index_neglect_bin.begin(), index_neglect_bin.end() , index);
					if( it != index_neglect_bin.end() ){
						dos[index] = dos[PoscarSpin.getBeforeIndex()];
						histogram[index] = histogram[PoscarSpin.getBeforeIndex()];
						index_neglect_bin.erase(it);
						PoscarSpin.outputEnergySpin(index, filename_rep_macrostate);
					}
				}

				dos.at(index) += logfactor;
				histogram.at(index) += 1;

			}  /*  end MC sweep */

			if((i % mcstep) == 0){
				WLconfT::outputHistogram(dos,  histogram, tmin, tdelta, fstep);
				std::cout << i << "sweep done " << std::endl;
			}
			if((i % flatcheck_step) == 0 and WLconfT::checkHistogramFlat(histogram, index_neglect_bin, flat_criterion, minstep, low_cutoff)){
				WLconfT::outputHistogram(dos,  histogram, tmin, tdelta, fstep);
				final_mcsweep = i;
				break;
			}
		}
		f_end = std::chrono::system_clock::now();
		auto f_sec = std::chrono::duration_cast<std::chrono::seconds>(f_end-f_start).count();
		std::cout << " fstep = " << fstep << " " << f_sec << " seconds "<< final_mcsweep << " sweeps" << std::endl;
		f_start = std::chrono::system_clock::now();
		logfactor/=2.0;
		++fstep;
	}

	auto end = std::chrono::system_clock::now();
	auto sec = std::chrono::duration_cast<std::chrono::seconds>(end-start).count();
	std::cout << "Time for calculating the DOS is " << sec << " seconds. "<< std::endl;
	std::cout << std::endl;
	std::cout << std::endl;
	std::cout << "check final correlation functions" << std::endl;
	PoscarSpin.dispCorr();
	std::cout << "---------------------------" << std::endl;
	PoscarSpin.setInitialCorrelationFunction();
	PoscarSpin.dispCorr();

	return 0;
}
<|endoftext|>


<commit_before>//  $Id$
//
//   Copyright (C) 2003-2006 Rational Discovery LLC
//
//   @@ All Rights Reserved  @@
//
#include "MolTransforms.h"
#include <GraphMol/RDKitBase.h>
#include <Numerics/EigenSolvers/PowerEigenSolver.h>
#include <Numerics/SymmMatrix.h>
#include <Numerics/Matrix.h>
#include <Geometry/Transform3D.h>

#define EIGEN_TOLERANCE 1.0e-2
namespace MolTransforms {

  using namespace RDKit;
  void transformAtom(Atom *atom,RDGeom::Transform3D &tform){
    PRECONDITION(atom,"no atom");
    ROMol &mol = atom->getOwningMol();
    for (ROMol::ConstConformerIterator ci = mol.beginConformers();
	 ci != mol.endConformers(); ci++) {
      RDGeom::Point3D &pos = (*ci)->getAtomPos(atom->getIdx());
      tform.TransformPoint(pos);
    }
    //atom->setPos(pos);
  }
  void transformMolsAtoms(ROMol *mol,RDGeom::Transform3D &tform){
    PRECONDITION(mol,"no molecule");

    ROMol::AtomIterator atomIt;
    for(atomIt=mol->beginAtoms();atomIt!=mol->endAtoms();atomIt++){
      transformAtom(*atomIt,tform);
    }
  }

  RDGeom::Point3D computeCentroid(const Conformer &conf, bool ignoreHs) {
    RDGeom::Point3D res(0.0, 0.0, 0.0);
    const ROMol &mol = conf.getOwningMol();
    ROMol::ConstAtomIterator cai;
    unsigned int nAtms = 0;

    for (cai = mol.beginAtoms(); cai != mol.endAtoms(); cai++) {
      if (((*cai)->getAtomicNum() == 1) && (ignoreHs)) {
        continue;
      }
      res += conf.getAtomPos((*cai)->getIdx());
      nAtms++;
    }
    res /= nAtms;
    return res;
  }

  RDNumeric::DoubleSymmMatrix *computeCovarianceMatrix(const Conformer &conf,
                                                       const RDGeom::Point3D &center,
                                                       bool normalize, bool ignoreHs) {
    double xx, xy, xz, yy, yz, zz;
    xx = xy = xz = yy = yz = zz = 0.0;
    const ROMol &mol = conf.getOwningMol();
    ROMol::ConstAtomIterator cai;
    unsigned int nAtms = 0;
    for (cai = mol.beginAtoms(); cai != mol.endAtoms(); cai++) {
      if (((*cai)->getAtomicNum() == 1) && (ignoreHs) ) {
        continue;
      }
      RDGeom::Point3D loc = conf.getAtomPos((*cai)->getIdx());
      loc -= center;
      xx += loc.x*loc.x;
      xy += loc.x*loc.y;
      xz += loc.x*loc.z;
      yy += loc.y*loc.y;
      yz += loc.y*loc.z;
      zz += loc.z*loc.z;
      nAtms++;
    }
    if (normalize) {
      xx /= nAtms;
      xy /= nAtms;
      xz /= nAtms;
      yy /= nAtms;
      yz /= nAtms;
      zz /= nAtms;
    }
    RDNumeric::DoubleSymmMatrix *res = new RDNumeric::DoubleSymmMatrix(3,3);
    res->setVal(0,0, xx);
    res->setVal(0,1, xy);
    res->setVal(0,2, xz);
    res->setVal(1,1, yy);
    res->setVal(1,2, yz);
    res->setVal(2,2, zz);
    return res;
  }

  RDGeom::Transform3D *computeCanonicalTransform(const Conformer &conf,
                                                 const RDGeom::Point3D *center,
                                                 bool normalizeCovar,
                                                 bool ignoreHs) {
    RDGeom::Point3D origin;
    if (!center) {
      origin = computeCentroid(conf, ignoreHs);
    } else {
      origin = (*center);
    }
    RDNumeric::DoubleSymmMatrix *covMat = computeCovarianceMatrix(conf, origin,
                                                                  normalizeCovar, ignoreHs);
    // find the eigen values and eigen vectors for the covMat
    RDNumeric::DoubleMatrix eigVecs(3,3);
    RDNumeric::DoubleVector eigVals(3);
    // if we have a single atom system we don't need to do anyhting other than setting translation
    // translation
    unsigned int nAtms = conf.getNumAtoms();
    RDGeom::Transform3D *trans = new RDGeom::Transform3D;

    // set the translation
    origin *= -1.0;
    //trans->SetTranslation(origin);
    // if we have a single atom system we don't need to do anyhting setting translation is sufficient
    if (nAtms > 1) {
      RDNumeric::EigenSolvers::powerEigenSolver(3, *covMat, eigVecs, eigVals,
                                                 conf.getNumAtoms());
      // deal with zero eigen value systems
      unsigned int i, j, dim = 3;
      for (i = 0; i < 3; ++i) {
        if (fabs(eigVals.getVal(i)) < EIGEN_TOLERANCE) {
          dim--;
        }
      }
      CHECK_INVARIANT(dim >= 1, "");
      if (dim < 3) {
        RDGeom::Point3D first(eigVecs.getVal(0,0), eigVecs.getVal(0,1), eigVecs.getVal(0,2));
        if (dim == 1) {
          // pick an arbitrary eigen vector perpendicular to the first vector
          RDGeom::Point3D  second(first.getPerpendicular());
          eigVecs.setVal(1,0, second.x);
          eigVecs.setVal(1,1, second.y);
          eigVecs.setVal(1,2, second.z);
          if (eigVals.getVal(0) > 1.0) {
            eigVals.setVal(1, 1.0);
          } else {
            eigVals.setVal(1, eigVals.getVal(0)/2.0);
          }
        }
        RDGeom::Point3D second(eigVecs.getVal(1,0), eigVecs.getVal(1,1), eigVecs.getVal(1,2));
        // pick the third eigen vector perpendicular to the first two
        RDGeom::Point3D third = first.crossProduct(second);
        eigVecs.setVal(2,0, third.x);
        eigVecs.setVal(2,1, third.y);
        eigVecs.setVal(2,2, third.z);
        if (eigVals.getVal(1) > 1.0) {
          eigVals.setVal(2, 1.0);
        } else {
          eigVals.setVal(2, eigVals.getVal(1)/2.0);
        }
      }
      // now set the transformation
      for (i = 0; i < 3; ++i) {
        for (j = 0; j < 3; ++j) {
          trans->setVal(i, j, eigVecs.getVal(i,j));
        }
      }
    }// end of multiple atom system
    trans->TransformPoint(origin);
    trans->SetTranslation(origin);
    delete covMat;

    return trans;
  }

  void transformConformer(Conformer &conf, const RDGeom::Transform3D &trans) {
    RDGeom::POINT3D_VECT &positions = conf.getPositions();
    RDGeom::POINT3D_VECT_I pi;
    for (pi = positions.begin(); pi != positions.end(); ++pi) {
      trans.TransformPoint(*pi);
    }
  }

  void canonicalizeConformer(Conformer &conf, const RDGeom::Point3D *center,
                             bool normalizeCovar, bool ignoreHs) {
    RDGeom::Transform3D *trans = computeCanonicalTransform(conf, center,
                                                           normalizeCovar, ignoreHs);
    transformConformer(conf, *trans);
    delete trans;
  }

  void canonicalizeMol(RDKit::ROMol &mol, bool normalizeCovar, bool ignoreHs) {
    ROMol::ConformerIterator ci;
    for (ci = mol.beginConformers(); ci != mol.endConformers(); ci++) {
      canonicalizeConformer(*(*ci), 0, normalizeCovar, ignoreHs);
    }
  }
}

<commit_msg>reflect changes in eigenvects code<commit_after>//  $Id$
//
//   Copyright (C) 2003-2006 Rational Discovery LLC
//
//   @@ All Rights Reserved  @@
//
#include "MolTransforms.h"
#include <GraphMol/RDKitBase.h>
#include <Numerics/EigenSolvers/PowerEigenSolver.h>
#include <Numerics/SymmMatrix.h>
#include <Numerics/Matrix.h>
#include <Geometry/Transform3D.h>

#define EIGEN_TOLERANCE 1.0e-2
namespace MolTransforms {

  using namespace RDKit;
  void transformAtom(Atom *atom,RDGeom::Transform3D &tform){
    PRECONDITION(atom,"no atom");
    ROMol &mol = atom->getOwningMol();
    for (ROMol::ConstConformerIterator ci = mol.beginConformers();
	 ci != mol.endConformers(); ci++) {
      RDGeom::Point3D &pos = (*ci)->getAtomPos(atom->getIdx());
      tform.TransformPoint(pos);
    }
    //atom->setPos(pos);
  }
  void transformMolsAtoms(ROMol *mol,RDGeom::Transform3D &tform){
    PRECONDITION(mol,"no molecule");

    ROMol::AtomIterator atomIt;
    for(atomIt=mol->beginAtoms();atomIt!=mol->endAtoms();atomIt++){
      transformAtom(*atomIt,tform);
    }
  }

  RDGeom::Point3D computeCentroid(const Conformer &conf, bool ignoreHs) {
    RDGeom::Point3D res(0.0, 0.0, 0.0);
    const ROMol &mol = conf.getOwningMol();
    ROMol::ConstAtomIterator cai;
    unsigned int nAtms = 0;

    for (cai = mol.beginAtoms(); cai != mol.endAtoms(); cai++) {
      if (((*cai)->getAtomicNum() == 1) && (ignoreHs)) {
        continue;
      }
      res += conf.getAtomPos((*cai)->getIdx());
      nAtms++;
    }
    res /= nAtms;
    return res;
  }

  RDNumeric::DoubleSymmMatrix *computeCovarianceMatrix(const Conformer &conf,
                                                       const RDGeom::Point3D &center,
                                                       bool normalize, bool ignoreHs) {
    double xx, xy, xz, yy, yz, zz;
    xx = xy = xz = yy = yz = zz = 0.0;
    const ROMol &mol = conf.getOwningMol();
    ROMol::ConstAtomIterator cai;
    unsigned int nAtms = 0;
    for (cai = mol.beginAtoms(); cai != mol.endAtoms(); cai++) {
      if (((*cai)->getAtomicNum() == 1) && (ignoreHs) ) {
        continue;
      }
      RDGeom::Point3D loc = conf.getAtomPos((*cai)->getIdx());
      loc -= center;
      xx += loc.x*loc.x;
      xy += loc.x*loc.y;
      xz += loc.x*loc.z;
      yy += loc.y*loc.y;
      yz += loc.y*loc.z;
      zz += loc.z*loc.z;
      nAtms++;
    }
    if (normalize) {
      xx /= nAtms;
      xy /= nAtms;
      xz /= nAtms;
      yy /= nAtms;
      yz /= nAtms;
      zz /= nAtms;
    }
    RDNumeric::DoubleSymmMatrix *res = new RDNumeric::DoubleSymmMatrix(3,3);
    res->setVal(0,0, xx);
    res->setVal(0,1, xy);
    res->setVal(0,2, xz);
    res->setVal(1,1, yy);
    res->setVal(1,2, yz);
    res->setVal(2,2, zz);
    return res;
  }

  RDGeom::Transform3D *computeCanonicalTransform(const Conformer &conf,
                                                 const RDGeom::Point3D *center,
                                                 bool normalizeCovar,
                                                 bool ignoreHs) {
    RDGeom::Point3D origin;
    if (!center) {
      origin = computeCentroid(conf, ignoreHs);
    } else {
      origin = (*center);
    }
    RDNumeric::DoubleSymmMatrix *covMat = computeCovarianceMatrix(conf, origin,
                                                                  normalizeCovar, ignoreHs);
    // find the eigen values and eigen vectors for the covMat
    RDNumeric::DoubleMatrix eigVecs(3,3);
    RDNumeric::DoubleVector eigVals(3);
    // if we have a single atom system we don't need to do anyhting other than setting translation
    // translation
    unsigned int nAtms = conf.getNumAtoms();
    RDGeom::Transform3D *trans = new RDGeom::Transform3D;

    // set the translation
    origin *= -1.0;
    //trans->SetTranslation(origin);
    // if we have a single atom system we don't need to do anyhting setting translation is sufficient
    if (nAtms > 1) {
      RDNumeric::EigenSolvers::powerEigenSolver(3, *covMat, eigVals, eigVecs,
                                                 conf.getNumAtoms());
      // deal with zero eigen value systems
      unsigned int i, j, dim = 3;
      for (i = 0; i < 3; ++i) {
        if (fabs(eigVals.getVal(i)) < EIGEN_TOLERANCE) {
          dim--;
        }
      }
      CHECK_INVARIANT(dim >= 1, "");
      if (dim < 3) {
        RDGeom::Point3D first(eigVecs.getVal(0,0), eigVecs.getVal(0,1), eigVecs.getVal(0,2));
        if (dim == 1) {
          // pick an arbitrary eigen vector perpendicular to the first vector
          RDGeom::Point3D  second(first.getPerpendicular());
          eigVecs.setVal(1,0, second.x);
          eigVecs.setVal(1,1, second.y);
          eigVecs.setVal(1,2, second.z);
          if (eigVals.getVal(0) > 1.0) {
            eigVals.setVal(1, 1.0);
          } else {
            eigVals.setVal(1, eigVals.getVal(0)/2.0);
          }
        }
        RDGeom::Point3D second(eigVecs.getVal(1,0), eigVecs.getVal(1,1), eigVecs.getVal(1,2));
        // pick the third eigen vector perpendicular to the first two
        RDGeom::Point3D third = first.crossProduct(second);
        eigVecs.setVal(2,0, third.x);
        eigVecs.setVal(2,1, third.y);
        eigVecs.setVal(2,2, third.z);
        if (eigVals.getVal(1) > 1.0) {
          eigVals.setVal(2, 1.0);
        } else {
          eigVals.setVal(2, eigVals.getVal(1)/2.0);
        }
      }
      // now set the transformation
      for (i = 0; i < 3; ++i) {
        for (j = 0; j < 3; ++j) {
          trans->setVal(i, j, eigVecs.getVal(i,j));
        }
      }
    }// end of multiple atom system
    trans->TransformPoint(origin);
    trans->SetTranslation(origin);
    delete covMat;

    return trans;
  }

  void transformConformer(Conformer &conf, const RDGeom::Transform3D &trans) {
    RDGeom::POINT3D_VECT &positions = conf.getPositions();
    RDGeom::POINT3D_VECT_I pi;
    for (pi = positions.begin(); pi != positions.end(); ++pi) {
      trans.TransformPoint(*pi);
    }
  }

  void canonicalizeConformer(Conformer &conf, const RDGeom::Point3D *center,
                             bool normalizeCovar, bool ignoreHs) {
    RDGeom::Transform3D *trans = computeCanonicalTransform(conf, center,
                                                           normalizeCovar, ignoreHs);
    transformConformer(conf, *trans);
    delete trans;
  }

  void canonicalizeMol(RDKit::ROMol &mol, bool normalizeCovar, bool ignoreHs) {
    ROMol::ConformerIterator ci;
    for (ci = mol.beginConformers(); ci != mol.endConformers(); ci++) {
      canonicalizeConformer(*(*ci), 0, normalizeCovar, ignoreHs);
    }
  }
}

<|endoftext|>


<commit_before>/******************************************************************************\
 *           ___        __                                                    *
 *          /\_ \    __/\ \                                                   *
 *          \//\ \  /\_\ \ \____    ___   _____   _____      __               *
 *            \ \ \ \/\ \ \ '__`\  /'___\/\ '__`\/\ '__`\  /'__`\             *
 *             \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_           *
 *             /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\          *
 *             \/____/ \/_/\/___/  \/____/ \ \ \/  \ \ \/  \/__/\/_/          *
 *                                          \ \_\   \ \_\                     *
 *                                           \/_/    \/_/                     *
 *                                                                            *
 * Copyright (C) 2011, 2012                                                   *
 * Dominik Charousset <dominik.charousset@haw-hamburg.de>                     *
 *                                                                            *
 * This file is part of libcppa.                                              *
 * libcppa 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.                                     *
 *                                                                            *
 * libcppa is distributed in the hope that it will be useful,                 *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                       *
 * See the GNU Lesser General Public License for more details.                *
 *                                                                            *
 * You should have received a copy of the GNU Lesser General Public License   *
 * along with libcppa. If not, see <http://www.gnu.org/licenses/>.            *
\******************************************************************************/

#include <atomic>
#include <iostream>

#include "cppa/any_tuple.hpp"
#include "cppa/local_actor.hpp"
#include "cppa/scheduler.hpp"
#include "cppa/exception.hpp"

#include "cppa/detail/actor_count.hpp"
#include "cppa/detail/empty_tuple.hpp"
#include "cppa/detail/group_manager.hpp"
#include "cppa/detail/actor_registry.hpp"
#include "cppa/detail/network_manager.hpp"
#include "cppa/detail/singleton_manager.hpp"
#include "cppa/detail/thread_pool_scheduler.hpp"
#include "cppa/detail/uniform_type_info_map.hpp"
#include "cppa/detail/converted_thread_context.hpp"

namespace {

using namespace cppa;
using namespace cppa::detail;

std::atomic<uniform_type_info_map*> s_uniform_type_info_map(nullptr);
std::atomic<network_manager*> s_network_manager(nullptr);
std::atomic<actor_registry*> s_actor_registry(nullptr);
std::atomic<group_manager*> s_group_manager(nullptr);
std::atomic<empty_tuple*> s_empty_tuple(nullptr);
std::atomic<scheduler*> s_scheduler(nullptr);

template<typename T>
void stop_and_kill(std::atomic<T*>& ptr)
{
    auto p = ptr.load();
    if (p)
    {
        if (ptr.compare_exchange_weak(p, nullptr))
        {
            p->stop();
            delete p;
        }
        else
        {
            stop_and_kill(ptr);
        }
    }
}

struct singleton_cleanup_helper
{
    ~singleton_cleanup_helper()
    {
        if (self.unchecked() != nullptr)
        {
            try { self.unchecked()->quit(exit_reason::normal); }
            catch (actor_exited&) { }
        }
        auto rptr = s_actor_registry.load();
        if (rptr)
        {
            rptr->await_running_count_equal(0);
        }
        delete s_actor_registry.load();
        // TODO: figure out why the ... Mac OS dies with a segfault here
//#       ifndef __APPLE__
        stop_and_kill(s_scheduler);
//#       endif
        stop_and_kill(s_network_manager);
        // it's safe now to delete all other singletons now
        delete s_group_manager.load();
        auto et = s_empty_tuple.load();
        if (et && !et->deref()) delete et;
        delete s_actor_registry.load();
        delete s_uniform_type_info_map.load();
    }
}
;//s_cleanup_helper;

template<typename T>
T* lazy_get(std::atomic<T*>& ptr)
{
    T* result = ptr.load();
    if (result == nullptr)
    {
        auto tmp = new T();
        if (ptr.compare_exchange_weak(result, tmp) == false)
        {
            delete tmp;
        }
        else
        {
            return tmp;
        }
    }
    return result;
}

} // namespace <anonymous>

namespace cppa { namespace detail {

actor_registry* singleton_manager::get_actor_registry()
{
    return lazy_get(s_actor_registry);
}

uniform_type_info_map* singleton_manager::get_uniform_type_info_map()
{
    return lazy_get(s_uniform_type_info_map);
}

group_manager* singleton_manager::get_group_manager()
{
    return lazy_get(s_group_manager);
}

scheduler* singleton_manager::get_scheduler()
{
    return s_scheduler.load();
}

bool singleton_manager::set_scheduler(scheduler* ptr)
{
    scheduler* expected = nullptr;
    if (s_scheduler.compare_exchange_weak(expected, ptr))
    {
        ptr->start();
        auto nm = network_manager::create_singleton();
        network_manager* nm_expected = nullptr;
        if (s_network_manager.compare_exchange_weak(nm_expected, nm))
        {
            nm->start();
        }
        else
        {
            delete nm;
        }
        return true;
    }
    else
    {
        delete ptr;
        return false;
    }
}

network_manager* singleton_manager::get_network_manager()
{
    network_manager* result = s_network_manager.load();
    if (result == nullptr)
    {
        scheduler* s = new thread_pool_scheduler;
        // set_scheduler sets s_network_manager
        set_scheduler(s);
        return get_network_manager();
    }
    return result;
}

empty_tuple* singleton_manager::get_empty_tuple()
{
    empty_tuple* result = s_empty_tuple.load();
    if (result == nullptr)
    {
        auto tmp = new empty_tuple;
        if (s_empty_tuple.compare_exchange_weak(result, tmp) == false)
        {
            delete tmp;
        }
        else
        {
            result = tmp;
            result->ref();
        }
    }
    return result;
}

} } // namespace cppa::detail
<commit_msg>use atexit() rather than a 'static destructor'<commit_after>/******************************************************************************\
 *           ___        __                                                    *
 *          /\_ \    __/\ \                                                   *
 *          \//\ \  /\_\ \ \____    ___   _____   _____      __               *
 *            \ \ \ \/\ \ \ '__`\  /'___\/\ '__`\/\ '__`\  /'__`\             *
 *             \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_           *
 *             /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\          *
 *             \/____/ \/_/\/___/  \/____/ \ \ \/  \ \ \/  \/__/\/_/          *
 *                                          \ \_\   \ \_\                     *
 *                                           \/_/    \/_/                     *
 *                                                                            *
 * Copyright (C) 2011, 2012                                                   *
 * Dominik Charousset <dominik.charousset@haw-hamburg.de>                     *
 *                                                                            *
 * This file is part of libcppa.                                              *
 * libcppa 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.                                     *
 *                                                                            *
 * libcppa is distributed in the hope that it will be useful,                 *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                       *
 * See the GNU Lesser General Public License for more details.                *
 *                                                                            *
 * You should have received a copy of the GNU Lesser General Public License   *
 * along with libcppa. If not, see <http://www.gnu.org/licenses/>.            *
\******************************************************************************/

#include <atomic>
#include <iostream>

#include "cppa/any_tuple.hpp"
#include "cppa/local_actor.hpp"
#include "cppa/scheduler.hpp"
#include "cppa/exception.hpp"

#include "cppa/detail/actor_count.hpp"
#include "cppa/detail/empty_tuple.hpp"
#include "cppa/detail/group_manager.hpp"
#include "cppa/detail/actor_registry.hpp"
#include "cppa/detail/network_manager.hpp"
#include "cppa/detail/singleton_manager.hpp"
#include "cppa/detail/thread_pool_scheduler.hpp"
#include "cppa/detail/uniform_type_info_map.hpp"
#include "cppa/detail/converted_thread_context.hpp"

namespace {

using namespace cppa;
using namespace cppa::detail;

std::atomic<uniform_type_info_map*> s_uniform_type_info_map(nullptr);
std::atomic<network_manager*> s_network_manager(nullptr);
std::atomic<actor_registry*> s_actor_registry(nullptr);
std::atomic<group_manager*> s_group_manager(nullptr);
std::atomic<empty_tuple*> s_empty_tuple(nullptr);
std::atomic<scheduler*> s_scheduler(nullptr);

template<typename T>
void stop_and_kill(std::atomic<T*>& ptr)
{
    auto p = ptr.load();
    if (p)
    {
        if (ptr.compare_exchange_weak(p, nullptr))
        {
            p->stop();
            delete p;
        }
        else
        {
            stop_and_kill(ptr);
        }
    }
}

void delete_singletons()
{
    if (self.unchecked() != nullptr)
    {
        try { self.unchecked()->quit(exit_reason::normal); }
        catch (actor_exited&) { }
    }
    auto rptr = s_actor_registry.load();
    if (rptr)
    {
        rptr->await_running_count_equal(0);
    }
    stop_and_kill(s_scheduler);
    stop_and_kill(s_network_manager);
    CPPA_MEMORY_BARRIER();
    // it's safe now to delete all other singletons now
    delete s_actor_registry.load();
    delete s_group_manager.load();
    auto et = s_empty_tuple.load();
    if (et && !et->deref()) delete et;
    delete s_uniform_type_info_map.load();
}

template<typename T>
T* lazy_get(std::atomic<T*>& ptr, bool register_atexit_fun = false)
{
    T* result = ptr.load();
    if (result == nullptr)
    {
        auto tmp = new T();
        if (ptr.compare_exchange_weak(result, tmp) == false)
        {
            delete tmp;
        }
        else
        {
            // ok, successfully created singleton, register exit fun?
            if (register_atexit_fun)
            {
//#               ifndef __APPLE__
                atexit(delete_singletons);
//#               endif
            }
            return tmp;
        }
    }
    return result;
}

} // namespace <anonymous>

namespace cppa { namespace detail {

actor_registry* singleton_manager::get_actor_registry()
{
    return lazy_get(s_actor_registry);
}

uniform_type_info_map* singleton_manager::get_uniform_type_info_map()
{
    return lazy_get(s_uniform_type_info_map, true);
}

group_manager* singleton_manager::get_group_manager()
{
    return lazy_get(s_group_manager);
}

scheduler* singleton_manager::get_scheduler()
{
    return s_scheduler.load();
}

bool singleton_manager::set_scheduler(scheduler* ptr)
{
    scheduler* expected = nullptr;
    if (s_scheduler.compare_exchange_weak(expected, ptr))
    {
        ptr->start();
        auto nm = network_manager::create_singleton();
        network_manager* nm_expected = nullptr;
        if (s_network_manager.compare_exchange_weak(nm_expected, nm))
        {
            nm->start();
        }
        else
        {
            delete nm;
        }
        return true;
    }
    else
    {
        delete ptr;
        return false;
    }
}

network_manager* singleton_manager::get_network_manager()
{
    network_manager* result = s_network_manager.load();
    if (result == nullptr)
    {
        scheduler* s = new thread_pool_scheduler;
        // set_scheduler sets s_network_manager
        set_scheduler(s);
        return get_network_manager();
    }
    return result;
}

empty_tuple* singleton_manager::get_empty_tuple()
{
    empty_tuple* result = s_empty_tuple.load();
    if (result == nullptr)
    {
        auto tmp = new empty_tuple;
        if (s_empty_tuple.compare_exchange_weak(result, tmp) == false)
        {
            delete tmp;
        }
        else
        {
            result = tmp;
            result->ref();
        }
    }
    return result;
}

} } // namespace cppa::detail
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_LOCALOPERATOR_INTERFACE_HH
#define DUNE_GDT_LOCALOPERATOR_INTERFACE_HH

#include <vector>

#include <dune/common/bartonnackmanifcheck.hh>
#include <dune/stuff/common/disable_warnings.hh>
#include <dune/common/dynmatrix.hh>
#include <dune/stuff/common/reenable_warnings.hh>

#include <dune/gdt/basefunctionset/interface.hh>

namespace Dune {
namespace GDT {
namespace LocalOperator {

template <class Traits>
class Codim0Interface
{
public:
  typedef typename Traits::derived_type derived_type;

  size_t numTmpObjectsRequired() const
  {
    CHECK_INTERFACE_IMPLEMENTATION(asImp().numTmpObjectsRequired());
    return asImp().numTmpObjectsRequired();
  }

  /**
   *  \brief      Applies the local operator.
   *  \tparam T       Traits of the test BaseFunctionSetInterface implementation
   *  \tparam A       Traits of the ansatz BaseFunctionSetInterface implementation
   *  \tparam D       DomainFieldType
   *  \tparam d       dimDomain
   *  \tparam R       RangeFieldType
   *  \tparam r{T,A}  dimRange of the of the {testBase,ansatzBase}
   *  \tparam rC{T,a} dimRangeCols of the {testBase,ansatzBase}
   */
  template <class T, class A, class D, int d, class R, int rT, int rCT, int rA, int rCA>
  void apply(const BaseFunctionSetInterface<T, D, d, R, rT, rCT>& testBase,
             const BaseFunctionSetInterface<A, D, d, R, rA, rCA>& ansatzBase, Dune::DynamicMatrix<R>& ret,
             std::vector<Dune::DynamicMatrix<R>>& tmpLocalMatrices) const
  {
    CHECK_AND_CALL_INTERFACE_IMPLEMENTATION(asImp().apply(testBase, ansatzBase, ret, tmpLocalMatrices));
  }

  derived_type& asImp()
  {
    return static_cast<derived_type&>(*this);
  }

  const derived_type& asImp() const
  {
    return static_cast<const derived_type&>(*this);
  }
}; // class Codim0Interface

template <class Traits>
class Codim1CouplingInterface
{
public:
  typedef typename Traits::derived_type derived_type;

  size_t numTmpObjectsRequired() const
  {
    CHECK_INTERFACE_IMPLEMENTATION(asImp().numTmpObjectsRequired());
    return asImp().numTmpObjectsRequired();
  }

  /**
   *  \brief Applies the local operator.
   *  \tparam TE      Traits of the entity test BaseFunctionSetInterface implementation
   *  \tparam AE      Traits of the entity ansatz BaseFunctionSetInterface implementation
   *  \tparam TN      Traits of the neighbor test BaseFunctionSetInterface implementation
   *  \tparam AN      Traits of the neighbor ansatz BaseFunctionSetInterface implementation
   *  \tparam IntersectionType
   *  \tparam D       DomainFieldType
   *  \tparam d       dimDomain
   *  \tparam R       RangeFieldType
   *  \tparam r{T,A}  dimRange of the of the {testBase*,ansatzBase*}
   *  \tparam rC{T,a} dimRangeCols of the {testBase*,ansatzBase*}
   */
  template <class TE, class AE, class TN, class AN, class IntersectionType, class D, int d, class R, int rT, int rCT,
            int rA, int rCA>
  void apply(const BaseFunctionSetInterface<TE, D, d, R, rT, rCT>& testBaseEntity,
             const BaseFunctionSetInterface<AE, D, d, R, rA, rCA>& ansatzBaseEntity,
             const BaseFunctionSetInterface<TN, D, d, R, rT, rCT>& testBaseNeighbor,
             const BaseFunctionSetInterface<AN, D, d, R, rA, rCA>& ansatzBaseNeighbor,
             const IntersectionType& intersection, Dune::DynamicMatrix<R>& entityEntityRet,
             Dune::DynamicMatrix<R>& neighborNeighborRet, Dune::DynamicMatrix<R>& entityNeighborRet,
             Dune::DynamicMatrix<R>& neighborEntityRet, std::vector<Dune::DynamicMatrix<R>>& tmpLocalMatrices) const
  {
    CHECK_AND_CALL_INTERFACE_IMPLEMENTATION(asImp().apply(testBaseEntity,
                                                          ansatzBaseEntity,
                                                          testBaseNeighbor,
                                                          ansatzBaseNeighbor,
                                                          intersection,
                                                          entityEntityRet,
                                                          neighborNeighborRet,
                                                          entityNeighborRet,
                                                          neighborEntityRet,
                                                          tmpLocalMatrices));
  }

  derived_type& asImp()
  {
    return static_cast<derived_type&>(*this);
  }

  const derived_type& asImp() const
  {
    return static_cast<const derived_type&>(*this);
  }
}; // class Codim1CouplingInterface

template <class Traits>
class Codim1BoundaryInterface
{
public:
  typedef typename Traits::derived_type derived_type;

  size_t numTmpObjectsRequired() const
  {
    CHECK_INTERFACE_IMPLEMENTATION(asImp().numTmpObjectsRequired());
    return asImp().numTmpObjectsRequired();
  }

  /**
   *  \brief Applies the local operator.
   *  \tparam T       Traits of the test BaseFunctionSetInterface implementation
   *  \tparam A       Traits of the ansatz BaseFunctionSetInterface implementation
   *  \tparam IntersectionType
   *  \tparam D       DomainFieldType
   *  \tparam d       dimDomain
   *  \tparam R       RangeFieldType
   *  \tparam r{T,A}  dimRange of the of the {testBase,ansatzBase}
   *  \tparam rC{T,a} dimRangeCols of the {testBase,ansatzBase}
   */
  template <class T, class A, class IntersectionType, class D, int d, class R, int rT, int rCT, int rA, int rCA>
  void apply(const BaseFunctionSetInterface<T, D, d, R, rT, rCT>& testBase,
             const BaseFunctionSetInterface<A, D, d, R, rA, rCA>& ansatzBase, const IntersectionType& intersection,
             Dune::DynamicMatrix<R>& ret, std::vector<Dune::DynamicMatrix<R>>& tmpLocalMatrices) const
  {
    CHECK_AND_CALL_INTERFACE_IMPLEMENTATION(asImp().apply(testBase, ansatzBase, intersection, ret, tmpLocalMatrices));
  }

  derived_type& asImp()
  {
    return static_cast<derived_type&>(*this);
  }

  const derived_type& asImp() const
  {
    return static_cast<const derived_type&>(*this);
  }
}; // class Codim1BoundaryInterface

} // namespace LocalOperator
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_LOCALOPERATOR_INTERFACE_HH
<commit_msg>[localoperator.interface] do not guard dune includes<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_LOCALOPERATOR_INTERFACE_HH
#define DUNE_GDT_LOCALOPERATOR_INTERFACE_HH

#include <vector>

#include <dune/common/dynmatrix.hh>

#include <dune/gdt/basefunctionset/interface.hh>

namespace Dune {
namespace GDT {
namespace LocalOperator {

template <class Traits>
class Codim0Interface
{
public:
  typedef typename Traits::derived_type derived_type;

  size_t numTmpObjectsRequired() const
  {
    CHECK_INTERFACE_IMPLEMENTATION(asImp().numTmpObjectsRequired());
    return asImp().numTmpObjectsRequired();
  }

  /**
   *  \brief      Applies the local operator.
   *  \tparam T       Traits of the test BaseFunctionSetInterface implementation
   *  \tparam A       Traits of the ansatz BaseFunctionSetInterface implementation
   *  \tparam D       DomainFieldType
   *  \tparam d       dimDomain
   *  \tparam R       RangeFieldType
   *  \tparam r{T,A}  dimRange of the of the {testBase,ansatzBase}
   *  \tparam rC{T,a} dimRangeCols of the {testBase,ansatzBase}
   */
  template <class T, class A, class D, int d, class R, int rT, int rCT, int rA, int rCA>
  void apply(const BaseFunctionSetInterface<T, D, d, R, rT, rCT>& testBase,
             const BaseFunctionSetInterface<A, D, d, R, rA, rCA>& ansatzBase, Dune::DynamicMatrix<R>& ret,
             std::vector<Dune::DynamicMatrix<R>>& tmpLocalMatrices) const
  {
    CHECK_AND_CALL_INTERFACE_IMPLEMENTATION(asImp().apply(testBase, ansatzBase, ret, tmpLocalMatrices));
  }

  derived_type& asImp()
  {
    return static_cast<derived_type&>(*this);
  }

  const derived_type& asImp() const
  {
    return static_cast<const derived_type&>(*this);
  }
}; // class Codim0Interface

template <class Traits>
class Codim1CouplingInterface
{
public:
  typedef typename Traits::derived_type derived_type;

  size_t numTmpObjectsRequired() const
  {
    CHECK_INTERFACE_IMPLEMENTATION(asImp().numTmpObjectsRequired());
    return asImp().numTmpObjectsRequired();
  }

  /**
   *  \brief Applies the local operator.
   *  \tparam TE      Traits of the entity test BaseFunctionSetInterface implementation
   *  \tparam AE      Traits of the entity ansatz BaseFunctionSetInterface implementation
   *  \tparam TN      Traits of the neighbor test BaseFunctionSetInterface implementation
   *  \tparam AN      Traits of the neighbor ansatz BaseFunctionSetInterface implementation
   *  \tparam IntersectionType
   *  \tparam D       DomainFieldType
   *  \tparam d       dimDomain
   *  \tparam R       RangeFieldType
   *  \tparam r{T,A}  dimRange of the of the {testBase*,ansatzBase*}
   *  \tparam rC{T,a} dimRangeCols of the {testBase*,ansatzBase*}
   */
  template <class TE, class AE, class TN, class AN, class IntersectionType, class D, int d, class R, int rT, int rCT,
            int rA, int rCA>
  void apply(const BaseFunctionSetInterface<TE, D, d, R, rT, rCT>& testBaseEntity,
             const BaseFunctionSetInterface<AE, D, d, R, rA, rCA>& ansatzBaseEntity,
             const BaseFunctionSetInterface<TN, D, d, R, rT, rCT>& testBaseNeighbor,
             const BaseFunctionSetInterface<AN, D, d, R, rA, rCA>& ansatzBaseNeighbor,
             const IntersectionType& intersection, Dune::DynamicMatrix<R>& entityEntityRet,
             Dune::DynamicMatrix<R>& neighborNeighborRet, Dune::DynamicMatrix<R>& entityNeighborRet,
             Dune::DynamicMatrix<R>& neighborEntityRet, std::vector<Dune::DynamicMatrix<R>>& tmpLocalMatrices) const
  {
    CHECK_AND_CALL_INTERFACE_IMPLEMENTATION(asImp().apply(testBaseEntity,
                                                          ansatzBaseEntity,
                                                          testBaseNeighbor,
                                                          ansatzBaseNeighbor,
                                                          intersection,
                                                          entityEntityRet,
                                                          neighborNeighborRet,
                                                          entityNeighborRet,
                                                          neighborEntityRet,
                                                          tmpLocalMatrices));
  }

  derived_type& asImp()
  {
    return static_cast<derived_type&>(*this);
  }

  const derived_type& asImp() const
  {
    return static_cast<const derived_type&>(*this);
  }
}; // class Codim1CouplingInterface

template <class Traits>
class Codim1BoundaryInterface
{
public:
  typedef typename Traits::derived_type derived_type;

  size_t numTmpObjectsRequired() const
  {
    CHECK_INTERFACE_IMPLEMENTATION(asImp().numTmpObjectsRequired());
    return asImp().numTmpObjectsRequired();
  }

  /**
   *  \brief Applies the local operator.
   *  \tparam T       Traits of the test BaseFunctionSetInterface implementation
   *  \tparam A       Traits of the ansatz BaseFunctionSetInterface implementation
   *  \tparam IntersectionType
   *  \tparam D       DomainFieldType
   *  \tparam d       dimDomain
   *  \tparam R       RangeFieldType
   *  \tparam r{T,A}  dimRange of the of the {testBase,ansatzBase}
   *  \tparam rC{T,a} dimRangeCols of the {testBase,ansatzBase}
   */
  template <class T, class A, class IntersectionType, class D, int d, class R, int rT, int rCT, int rA, int rCA>
  void apply(const BaseFunctionSetInterface<T, D, d, R, rT, rCT>& testBase,
             const BaseFunctionSetInterface<A, D, d, R, rA, rCA>& ansatzBase, const IntersectionType& intersection,
             Dune::DynamicMatrix<R>& ret, std::vector<Dune::DynamicMatrix<R>>& tmpLocalMatrices) const
  {
    CHECK_AND_CALL_INTERFACE_IMPLEMENTATION(asImp().apply(testBase, ansatzBase, intersection, ret, tmpLocalMatrices));
  }

  derived_type& asImp()
  {
    return static_cast<derived_type&>(*this);
  }

  const derived_type& asImp() const
  {
    return static_cast<const derived_type&>(*this);
  }
}; // class Codim1BoundaryInterface

} // namespace LocalOperator
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_LOCALOPERATOR_INTERFACE_HH
<|endoftext|>