<commit_before>#ifndef __MAPNIK_VECTOR_TILE_GEOMETRY_DECODER_H__
#define __MAPNIK_VECTOR_TILE_GEOMETRY_DECODER_H__

#include "vector_tile.pb.h"

namespace mapnik { namespace vector_tile_impl {

class Geometry {

public:
    inline explicit Geometry(vector_tile::Tile_Feature const& f,
                             double tile_x, double tile_y,
                             double scale_x, double scale_y);

    enum command : uint8_t {
        end = 0,
        move_to = 1,
        line_to = 2,
        close = 7
    };

    inline command next(double& rx, double& ry);

private:
    vector_tile::Tile_Feature const& f_;
    double scale_x_;
    double scale_y_;
    uint32_t k;
    uint32_t geoms_;
    uint8_t cmd;
    uint32_t length;
    double x, y;
    double ox, oy;
};

Geometry::Geometry(vector_tile::Tile_Feature const& f,
                   double tile_x, double tile_y,
                   double scale_x, double scale_y)
    : f_(f),
      scale_x_(scale_x),
      scale_y_(scale_y),
      k(0),
      geoms_(f_.geometry_size()),
      cmd(1),
      length(0),
      x(tile_x), y(tile_y),
      ox(0), oy(0) {}

Geometry::command Geometry::next(double& rx, double& ry) {
    if (k < geoms_) {
        if (length == 0) {
            uint32_t cmd_length = static_cast<uint32_t>(f_.geometry(k++));
            cmd = cmd_length & 0x7;
            length = cmd_length >> 3;
        }

        --length;

        if (cmd == move_to || cmd == line_to) {
            int32_t dx = f_.geometry(k++);
            int32_t dy = f_.geometry(k++);
            dx = ((dx >> 1) ^ (-(dx & 1)));
            dy = ((dy >> 1) ^ (-(dy & 1)));
            x += (static_cast<double>(dx) / scale_x_);
            y += (static_cast<double>(dy) / scale_y_);
            rx = x;
            ry = y;
            if (cmd == move_to) {
                ox = x;
                oy = y;
                return move_to;
            } else {
                return line_to;
            }
        } else if (cmd == close) {
            rx = ox;
            ry = oy;
            return close;
        } else {
            fprintf(stderr, "unknown command: %d\n", cmd);
            return end;
        }
    } else {
        return end;
    }
}

inline mapnik::geometry::geometry decode_geometry(vector_tile::Tile_Feature const& f,
                                           double tile_x, double tile_y,
                                           double scale_x, double scale_y)
{

    Geometry::command cmd;
    Geometry geoms(f,tile_x,tile_y,scale_x,scale_y);
    double x1, y1;
    switch (f.type())
    {
        case vector_tile::Tile_GeomType_POINT:
        {
            mapnik::geometry::multi_point mp;
            while ((cmd = geoms.next(x1, y1)) != Geometry::end) {
                mp.emplace_back(mapnik::geometry::point(x1,y1));
            }
            std::size_t num_points = mp.size();
            if (num_points == 1)
            {
                // return the single point
                return mapnik::geometry::geometry(std::move(mp[0]));;
            }
            else if (num_points > 1)
            {
                // return multipoint
                return mapnik::geometry::geometry(std::move(mp));;
            }
            break;
        }
        case vector_tile::Tile_GeomType_LINESTRING:
        {
            mapnik::geometry::multi_line_string mp;
            mp.emplace_back();
            bool first = true;
            while ((cmd = geoms.next(x1, y1)) != Geometry::end) {
                if (cmd == Geometry::move_to) {
                    if (first)
                    {
                        first = false;
                    }
                    else
                    {
                        mp.emplace_back();
                    }
                }
                mp.back().add_coord(x1,y1);
            }
            std::size_t num_lines = mp.size();
            if (num_lines == 1)
            {
                // return the single line
                return mapnik::geometry::geometry(std::move(mp[0]));;
            }
            else if (num_lines > 1)
            {
                // return multiline
                return mapnik::geometry::geometry(std::move(mp));;
            }
            break;
        }
        case vector_tile::Tile_GeomType_POLYGON:
        {
            // TODO - support for multipolygons
            //mapnik::geometry::multi_polygon;
            mapnik::geometry::polygon poly;
            std::vector<mapnik::geometry::linear_ring> rings;
            rings.emplace_back();
            double x2,y2;
            bool first = true;
            while ((cmd = geoms.next(x1, y1)) != Geometry::end) {
                if (cmd == Geometry::move_to)
                {
                    x2 = x1;
                    y2 = y1;
                    if (first)
                    {
                        first = false;
                    }
                    else
                    {
                        rings.emplace_back();
                    }
                }
                else if (cmd == Geometry::close)
                {
                    rings.back().add_coord(x2,y2);
                    continue;
                }
                rings.back().add_coord(x1,y1);
            }
            std::size_t num_rings = rings.size();
            if (num_rings == 1)
            {
                // return the single polygon
                mapnik::geometry::polygon poly;
                poly.set_exterior_ring(std::move(rings[0]));
                return mapnik::geometry::geometry(std::move(poly));
            }
            for (unsigned i = 0; i < num_rings;++i)
            {
                mapnik::geometry::polygon poly;
                if (i == 0)
                {
                    poly.set_exterior_ring(std::move(rings[i]));
                }
                else
                {
                    poly.add_hole(std::move(rings[i]));
                }
                return mapnik::geometry::geometry(std::move(poly));
            }
            return poly;
            break;
        }
        case vector_tile::Tile_GeomType_UNKNOWN:
        default:
        {
            throw std::runtime_error("unhandled geometry type during decoding");
            break;
        }
    }
    return mapnik::geometry::geometry();
}

}} // end ns

#endif // __MAPNIK_VECTOR_TILE_GEOMETRY_DECODER_H__
<commit_msg>fix polygon decoder to deal with multiple polygons encoded as multiple paths<commit_after>#ifndef __MAPNIK_VECTOR_TILE_GEOMETRY_DECODER_H__
#define __MAPNIK_VECTOR_TILE_GEOMETRY_DECODER_H__

#include "vector_tile.pb.h"

#include <mapnik/util/is_clockwise.hpp>

namespace mapnik { namespace vector_tile_impl {

class Geometry {

public:
    inline explicit Geometry(vector_tile::Tile_Feature const& f,
                             double tile_x, double tile_y,
                             double scale_x, double scale_y);

    enum command : uint8_t {
        end = 0,
        move_to = 1,
        line_to = 2,
        close = 7
    };

    inline command next(double& rx, double& ry);

private:
    vector_tile::Tile_Feature const& f_;
    double scale_x_;
    double scale_y_;
    uint32_t k;
    uint32_t geoms_;
    uint8_t cmd;
    uint32_t length;
    double x, y;
    double ox, oy;
};

Geometry::Geometry(vector_tile::Tile_Feature const& f,
                   double tile_x, double tile_y,
                   double scale_x, double scale_y)
    : f_(f),
      scale_x_(scale_x),
      scale_y_(scale_y),
      k(0),
      geoms_(f_.geometry_size()),
      cmd(1),
      length(0),
      x(tile_x), y(tile_y),
      ox(0), oy(0) {}

Geometry::command Geometry::next(double& rx, double& ry) {
    if (k < geoms_) {
        if (length == 0) {
            uint32_t cmd_length = static_cast<uint32_t>(f_.geometry(k++));
            cmd = cmd_length & 0x7;
            length = cmd_length >> 3;
        }

        --length;

        if (cmd == move_to || cmd == line_to) {
            int32_t dx = f_.geometry(k++);
            int32_t dy = f_.geometry(k++);
            dx = ((dx >> 1) ^ (-(dx & 1)));
            dy = ((dy >> 1) ^ (-(dy & 1)));
            x += (static_cast<double>(dx) / scale_x_);
            y += (static_cast<double>(dy) / scale_y_);
            rx = x;
            ry = y;
            if (cmd == move_to) {
                ox = x;
                oy = y;
                return move_to;
            } else {
                return line_to;
            }
        } else if (cmd == close) {
            rx = ox;
            ry = oy;
            return close;
        } else {
            fprintf(stderr, "unknown command: %d\n", cmd);
            return end;
        }
    } else {
        return end;
    }
}

inline mapnik::geometry::geometry decode_geometry(vector_tile::Tile_Feature const& f,
                                           double tile_x, double tile_y,
                                           double scale_x, double scale_y)
{

    Geometry::command cmd;
    Geometry geoms(f,tile_x,tile_y,scale_x,scale_y);
    double x1, y1;
    switch (f.type())
    {
        case vector_tile::Tile_GeomType_POINT:
        {
            mapnik::geometry::multi_point mp;
            while ((cmd = geoms.next(x1, y1)) != Geometry::end) {
                mp.emplace_back(mapnik::geometry::point(x1,y1));
            }
            std::size_t num_points = mp.size();
            if (num_points == 1)
            {
                // return the single point
                return mapnik::geometry::geometry(std::move(mp[0]));;
            }
            else if (num_points > 1)
            {
                // return multipoint
                return mapnik::geometry::geometry(std::move(mp));;
            }
            break;
        }
        case vector_tile::Tile_GeomType_LINESTRING:
        {
            mapnik::geometry::multi_line_string mp;
            mp.emplace_back();
            bool first = true;
            while ((cmd = geoms.next(x1, y1)) != Geometry::end) {
                if (cmd == Geometry::move_to) {
                    if (first)
                    {
                        first = false;
                    }
                    else
                    {
                        mp.emplace_back();
                    }
                }
                mp.back().add_coord(x1,y1);
            }
            std::size_t num_lines = mp.size();
            if (num_lines == 1)
            {
                // return the single line
                return mapnik::geometry::geometry(std::move(mp[0]));;
            }
            else if (num_lines > 1)
            {
                // return multiline
                return mapnik::geometry::geometry(std::move(mp));;
            }
            break;
        }
        case vector_tile::Tile_GeomType_POLYGON:
        {
            // TODO - support for multipolygons
            //mapnik::geometry::multi_polygon;
            mapnik::geometry::polygon poly;
            std::vector<mapnik::geometry::linear_ring> rings;
            rings.emplace_back();
            double x2,y2;
            bool first = true;
            while ((cmd = geoms.next(x1, y1)) != Geometry::end)
            {
                if (cmd == Geometry::move_to)
                {
                    x2 = x1;
                    y2 = y1;
                    if (first)
                    {
                        first = false;
                    }
                    else
                    {
                        rings.emplace_back();
                    }
                }
                else if (cmd == Geometry::close)
                {
                    rings.back().add_coord(x2,y2);
                    continue;
                }
                rings.back().add_coord(x1,y1);
            }

            auto rings_itr = std::make_move_iterator(rings.begin());
            auto rings_end = std::make_move_iterator(rings.end());
            std::size_t num_rings = rings.size();
            if (num_rings == 1)
            {
                // return the single polygon without interior rings
                mapnik::geometry::polygon poly;
                poly.set_exterior_ring(std::move(*rings_itr));
                return mapnik::geometry::geometry(std::move(poly));
            }

            mapnik::geometry::multi_polygon multi_poly;
            multi_poly.emplace_back();
            first = true;
            for (; rings_itr != rings_end; ++rings_itr)
            {
                if (first)
                {
                    // first ring always exterior
                    multi_poly.back().set_exterior_ring(std::move(*rings_itr));
                    first = false;
                }
                else if (!mapnik::util::is_clockwise(*rings_itr)) // no-move --> const&
                {
                    multi_poly.emplace_back(); // start new polygon
                    multi_poly.back().set_exterior_ring(std::move(*rings_itr));
                }
                else
                {
                    multi_poly.back().add_hole(std::move(*rings_itr));
                }
            }
            if (multi_poly.size() == 1)
            {
                auto itr = std::make_move_iterator(multi_poly.begin());
                return mapnik::geometry::geometry(std::move(*itr));
            }
            else
            {
                return mapnik::geometry::geometry(std::move(multi_poly));
            }
            break;
        }
        case vector_tile::Tile_GeomType_UNKNOWN:
        default:
        {
            throw std::runtime_error("unhandled geometry type during decoding");
            break;
        }
    }
    return mapnik::geometry::geometry();
}

}} // end ns

#endif // __MAPNIK_VECTOR_TILE_GEOMETRY_DECODER_H__
<|endoftext|>


<commit_before>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "Step8.h"

#include "QmitkStdMultiWidget.h"

#include "mitkGlobalInteraction.h"
#include "mitkRenderingManager.h"

#include <QHBoxLayout>
#include <QVBoxLayout>

//##Documentation
//## @brief As Step6, but with QmitkStdMultiWidget as widget
Step8::Step8(int argc, char* argv[], QWidget *parent) :
	Step6(argc, argv, parent)
{
}

void Step8::SetupWidgets()
{
	//*************************************************************************
	// Part I: Create windows and pass the tree to it
	//*************************************************************************

	// Create toplevel widget with vertical layout
	QVBoxLayout* vlayout = new QVBoxLayout(this);
	vlayout->setMargin(0);
	vlayout->setSpacing(2);

	// Create viewParent widget with horizontal layout
	QWidget* viewParent = new QWidget(this);
	vlayout->addWidget(viewParent);
	QHBoxLayout* hlayout = new QHBoxLayout(viewParent);
	hlayout->setMargin(0);

	//*************************************************************************
	// Part Ia: create and initialize QmitkStdMultiWidget
	//*************************************************************************
	QmitkStdMultiWidget* multiWidget = new QmitkStdMultiWidget(viewParent);

	hlayout->addWidget(multiWidget);

	// Tell the multiWidget which DataStorage to render
	multiWidget->SetDataStorage(m_DataStorage);

	// Initialize views as transversal, sagittal, coronar (from
	// top-left to bottom)
	mitk::TimeSlicedGeometry::Pointer geo = m_DataStorage->ComputeBoundingGeometry3D(
			m_DataStorage->GetAll());
	mitk::RenderingManager::GetInstance()->InitializeViews(geo);

	// Initialize bottom-right view as 3D view
	multiWidget->GetRenderWindow4()->GetRenderer()->SetMapperID(
			mitk::BaseRenderer::Standard3D);

	// Enable standard handler for levelwindow-slider
	multiWidget->EnableStandardLevelWindow();

	// Add the displayed views to the DataStorage to see their positions in 2D and 3D
	multiWidget->AddDisplayPlaneSubTree();
	multiWidget->AddPlanesToDataStorage();
	multiWidget->SetWidgetPlanesVisibility(true);

	//*************************************************************************
	// Part II: Setup standard interaction with the mouse
	//*************************************************************************

	// Moving the cut-planes to click-point
	multiWidget->EnableNavigationControllerEventListening();

	// Zooming and panning
	mitk::GlobalInteraction::GetInstance()->AddListener(
			multiWidget->GetMoveAndZoomInteractor());
}
/**
 \example Step8.cpp
 */
<commit_msg>Remove obsolete code<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "Step8.h"

#include "QmitkStdMultiWidget.h"

#include "mitkGlobalInteraction.h"
#include "mitkRenderingManager.h"

#include <QHBoxLayout>
#include <QVBoxLayout>

//##Documentation
//## @brief As Step6, but with QmitkStdMultiWidget as widget
Step8::Step8(int argc, char* argv[], QWidget *parent) :
	Step6(argc, argv, parent)
{
}

void Step8::SetupWidgets()
{
	//*************************************************************************
	// Part I: Create windows and pass the tree to it
	//*************************************************************************

	// Create toplevel widget with vertical layout
	QVBoxLayout* vlayout = new QVBoxLayout(this);
	vlayout->setMargin(0);
	vlayout->setSpacing(2);

	// Create viewParent widget with horizontal layout
	QWidget* viewParent = new QWidget(this);
	vlayout->addWidget(viewParent);
	QHBoxLayout* hlayout = new QHBoxLayout(viewParent);
	hlayout->setMargin(0);

	//*************************************************************************
	// Part Ia: create and initialize QmitkStdMultiWidget
	//*************************************************************************
	QmitkStdMultiWidget* multiWidget = new QmitkStdMultiWidget(viewParent);

	hlayout->addWidget(multiWidget);

	// Tell the multiWidget which DataStorage to render
	multiWidget->SetDataStorage(m_DataStorage);

	// Initialize views as transversal, sagittal, coronar (from
	// top-left to bottom)
	mitk::TimeSlicedGeometry::Pointer geo = m_DataStorage->ComputeBoundingGeometry3D(
			m_DataStorage->GetAll());
	mitk::RenderingManager::GetInstance()->InitializeViews(geo);

	// Initialize bottom-right view as 3D view
	multiWidget->GetRenderWindow4()->GetRenderer()->SetMapperID(
			mitk::BaseRenderer::Standard3D);

	// Enable standard handler for levelwindow-slider
	multiWidget->EnableStandardLevelWindow();

	// Add the displayed views to the DataStorage to see their positions in 2D and 3D
	multiWidget->AddDisplayPlaneSubTree();
	multiWidget->AddPlanesToDataStorage();
	multiWidget->SetWidgetPlanesVisibility(true);

	//*************************************************************************
	// Part II: Setup standard interaction with the mouse
	//*************************************************************************

	// Moving the cut-planes to click-point
	multiWidget->EnableNavigationControllerEventListening();
}
/**
 \example Step8.cpp
 */
<|endoftext|>


<commit_before>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2009 Scientific Computing and Imaging Institute,
   University of Utah.

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

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

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
   Author            : Moritz Dannhauer
   Last modification : March 16 2014 (ported from SCIRun4)
   TODO: Nrrd aoutput
*/

#include <Core/Algorithms/Legacy/Fields/Mapping/MapFieldDataFromElemToNode.h>
#include <Core/Datatypes/DenseMatrix.h>
#include <Core/Datatypes/Legacy/Field/FieldInformation.h>
#include <Core/Algorithms/Base/AlgorithmPreconditions.h>
#include <Core/Algorithms/Base/AlgorithmVariableNames.h>
#include <Core/GeometryPrimitives/Vector.h>
#include <Core/Datatypes/Legacy/Field/Field.h>
#include <Core/Datatypes/Legacy/Field/VField.h>
#include <Core/Datatypes/Legacy/Field/VMesh.h>

using namespace SCIRun::Core::Algorithms::Fields;
using namespace SCIRun::Core::Geometry;
using namespace SCIRun::Core::Datatypes;
using namespace SCIRun::Core::Utility;
using namespace SCIRun::Core::Algorithms;
using namespace SCIRun::Core::Logging;
using namespace SCIRun;

template <class DATA>
bool
MapFieldDataFromElemToNodeT(const MapFieldDataFromElemToNodeAlgo *algo,
			    FieldHandle& input,
                            FieldHandle& output);

template <class DATA>
bool
MapFieldDataFromElemToNodeT(const MapFieldDataFromElemToNodeAlgo *algo,
                            FieldHandle& input,
                            FieldHandle& output)
{

  std::string method = algo->get_option(MapFieldDataFromElemToNodeAlgo::Method);

  VField *ifield = input->vfield();
  VField *ofield = output->vfield();

  /// Make sure that the data vector has the same length
  ofield->resize_fdata();

  VMesh* mesh = input->vmesh();

  VMesh::Elem::array_type elems;
  VMesh::Node::iterator it, eit;
  VMesh::Node::size_type sz;

  mesh->synchronize(SCIRun::Mesh::NODE_NEIGHBORS_E);

  mesh->begin(it);
  mesh->end(eit);

  mesh->size(sz);

  index_type cnt = 0, c = 0;

  if (method == "Interpolation")
  {
    algo->remark("Interpolation of piecewise constant data is done by averaging adjoining values");
  }

  if ((method == "Interpolation")||(method == "Average"))
  {
   while (it != eit)
   {
    mesh->get_elems(elems, *(it));
    size_t nsize = elems.size();
    DATA val(0);
    DATA tval;
    for (size_t p = 0; p < nsize; p++)
    {
      ifield->get_value(tval,elems[p]);
      val += tval;
    }
    val = static_cast<DATA>(val*(1.0/static_cast<double>(nsize)));
    ofield->set_value(val,*(it));
    ++it;
    cnt++;
    if (cnt==1000)
    {
     cnt=0; c+=1000;
     algo->update_progress(c/sz);
    }
   }

  } else
  if (method == "Max")
  {
    while (it != eit)
    {
      mesh->get_elems(elems, *(it));
      size_t nsize = elems.size();
      DATA val(0);
      DATA tval(0);
      if (nsize > 0)
      {
       ifield->get_value(val,elems[0]);
       for (size_t p = 1; p < nsize; p++)
       {
        ifield->get_value(tval,elems[p]);
        if (tval > val) val = tval;
       }
      }
      ofield->set_value(val,*(it));
      ++it;
      cnt++;
      if (cnt==1000)
      {
        cnt=0; c+=1000;
        algo->update_progress(c/sz);
      }
    }
  } else
  if (method == "Min")
  {
    while (it != eit)
    {
     mesh->get_elems(elems, *it);
     size_t nsize = elems.size();
     DATA val(0);
     DATA tval(0);
     if (nsize > 0)
     {
      ifield->get_value(val,elems[0]);
      for (size_t p = 1; p < nsize; p++)
      {
       ifield->value(tval,elems[p]);
       if (tval < val) val = tval;
      }
     }
      ofield->set_value(val,*(it));
      ++it;
      cnt++;
      if (cnt==1000)
      {
        cnt=0; c+=1000;
        algo->update_progress(c/sz);
      }
    }
  } else
  if (method=="Sum")
  {
    while (it != eit)
    {
      mesh->get_elems(elems, *(it));
      size_t nsize = elems.size();
      DATA val(0);
      DATA tval(0);
      for (size_t p = 0; p < nsize; p++)
      {
        ifield->get_value(tval,elems[p]);
        val += tval;
      }
      ofield->set_value(val,*(it));
      ++it;
      cnt++;
      if (cnt==1000)
      {
        cnt=0; c+=1000;
        algo->update_progress(c/sz);
      }
    }
  } else
  if (method == "Median")
  {
    std::vector<DATA> valarray;
    while (it != eit)
    {
      mesh->get_elems(elems, *(it));
      size_t nsize = elems.size();
      valarray.resize(nsize);
      for (size_t p = 0; p < nsize; p++)
      {
        ifield->get_value(valarray[p],elems[p]);
      }
      sort(valarray.begin(),valarray.end());
      int idx = static_cast<int>((valarray.size()/2));
      ofield->set_value(valarray[idx],*(it));
      ++it;
      cnt++;
      if (cnt==1000)
      {
        cnt=0; c+=1000;
        algo->update_progress(c/sz);
      }
    }
  } else
  {
   algo->remark("Method is not implemented!");
   return false;
  }

  return true;
}

MapFieldDataFromElemToNodeAlgo::MapFieldDataFromElemToNodeAlgo()
{
  add_option(Method,"Interpolation","Interpolation|Average|Min|Max|Sum|Median|None");
}

AlgorithmParameterName MapFieldDataFromElemToNodeAlgo::Method("Method");

AlgorithmOutput MapFieldDataFromElemToNodeAlgo::run_generic(const AlgorithmInput& input) const
{
  auto input_field = input.get<Field>(Variables::InputField);

  FieldHandle output_field;
  output_field = run(input_field);

  AlgorithmOutput output;
  output[Variables::OutputField] = output_field;

  return output;
}

/// Function call to convert data from Field into Matrix data
FieldHandle MapFieldDataFromElemToNodeAlgo::run(FieldHandle input_field) const
{
   FieldHandle output;

   if (!input_field)
   {
     THROW_ALGORITHM_INPUT_ERROR("Input field is not allocated");
   }

   FieldInformation fi(input_field);
   FieldInformation fo(input_field);

   if (fi.is_lineardata())
   {
    THROW_ALGORITHM_INPUT_ERROR("Data is already located at nodes");
   }

   if (!(fi.is_constantdata()))
   {
    THROW_ALGORITHM_INPUT_ERROR("The input data needs to be located at the elements");
   }

   fo.make_lineardata();

   output = CreateField(fo,input_field->mesh());

   if (!output)
   {
     THROW_ALGORITHM_INPUT_ERROR("output field cannot be allocated");
   }

   if (input_field->vfield()->is_signed_integer())
    {
       if(!MapFieldDataFromElemToNodeT<int>(this,input_field,output))
          {
	    THROW_ALGORITHM_INPUT_ERROR("output int field cannot be allocated");
	  }
    } else

  if (input_field->vfield()->is_unsigned_integer())
   {
     if(!MapFieldDataFromElemToNodeT<unsigned int>(this,input_field,output))
     {
      THROW_ALGORITHM_INPUT_ERROR("output uint field cannot be allocated");
     }
   } else

  if (input_field->vfield()->is_scalar())
   {
     if (!MapFieldDataFromElemToNodeT<double>(this,input_field,output))
     {
      THROW_ALGORITHM_INPUT_ERROR("output scalar field cannot be allocated");
     }
   } else

  if (input_field->vfield()->is_vector())
  {
    if (!MapFieldDataFromElemToNodeT<Vector>(this,input_field,output))
    {
     THROW_ALGORITHM_INPUT_ERROR("output vector field cannot be allocated");
    }
  } else

  if (input_field->vfield()->is_tensor())
  {
    if (!MapFieldDataFromElemToNodeT<Tensor>(this,input_field,output))
    {
     THROW_ALGORITHM_INPUT_ERROR("output tensor field cannot be allocated");
    }
  } else
  {
    THROW_ALGORITHM_INPUT_ERROR(" Unknown field data type ");
  }

   return output;
}
<commit_msg>Reformat. Fixes #582<commit_after>/*
For more information, please see: http://software.sci.utah.edu

The MIT License

Copyright (c) 2009 Scientific Computing and Imaging Institute,
University of Utah.

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

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

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
Author            : Moritz Dannhauer
Last modification : March 16 2014 (ported from SCIRun4)
TODO: Nrrd aoutput
*/

#include <Core/Algorithms/Legacy/Fields/Mapping/MapFieldDataFromElemToNode.h>
#include <Core/Datatypes/DenseMatrix.h>
#include <Core/Datatypes/Legacy/Field/FieldInformation.h>
#include <Core/Algorithms/Base/AlgorithmPreconditions.h>
#include <Core/Algorithms/Base/AlgorithmVariableNames.h>
#include <Core/GeometryPrimitives/Vector.h>
#include <Core/Datatypes/Legacy/Field/Field.h>
#include <Core/Datatypes/Legacy/Field/VField.h>
#include <Core/Datatypes/Legacy/Field/VMesh.h>

using namespace SCIRun::Core::Algorithms::Fields;
using namespace SCIRun::Core::Geometry;
using namespace SCIRun::Core::Datatypes;
using namespace SCIRun::Core::Utility;
using namespace SCIRun::Core::Algorithms;
using namespace SCIRun::Core::Logging;
using namespace SCIRun;

template <class DATA>
bool
  MapFieldDataFromElemToNodeT(const MapFieldDataFromElemToNodeAlgo *algo,
  FieldHandle& input,
  FieldHandle& output);

template <class DATA>
bool
  MapFieldDataFromElemToNodeT(const MapFieldDataFromElemToNodeAlgo *algo,
  FieldHandle& input,
  FieldHandle& output)
{

  std::string method = algo->get_option(MapFieldDataFromElemToNodeAlgo::Method);

  VField *ifield = input->vfield();
  VField *ofield = output->vfield();

  /// Make sure that the data vector has the same length
  ofield->resize_fdata();

  VMesh* mesh = input->vmesh();

  VMesh::Elem::array_type elems;
  VMesh::Node::iterator it, eit;
  VMesh::Node::size_type sz;

  mesh->synchronize(SCIRun::Mesh::NODE_NEIGHBORS_E);

  mesh->begin(it);
  mesh->end(eit);

  mesh->size(sz);

  index_type cnt = 0, c = 0;

  if (method == "Interpolation")
  {
    algo->remark("Interpolation of piecewise constant data is done by averaging adjoining values");
  }

  if ((method == "Interpolation")||(method == "Average"))
  {
    while (it != eit)
    {
      mesh->get_elems(elems, *(it));
      size_t nsize = elems.size();
      DATA val(0);
      DATA tval;
      for (size_t p = 0; p < nsize; p++)
      {
        ifield->get_value(tval,elems[p]);
        val += tval;
      }
      val = static_cast<DATA>(val*(1.0/static_cast<double>(nsize)));
      ofield->set_value(val,*(it));
      ++it;
      cnt++;
      if (cnt==1000)
      {
        cnt=0; c+=1000;
        algo->update_progress(c/sz);
      }
    }

  } else
    if (method == "Max")
    {
      while (it != eit)
      {
        mesh->get_elems(elems, *(it));
        size_t nsize = elems.size();
        DATA val(0);
        DATA tval(0);
        if (nsize > 0)
        {
          ifield->get_value(val,elems[0]);
          for (size_t p = 1; p < nsize; p++)
          {
            ifield->get_value(tval,elems[p]);
            if (tval > val) val = tval;
          }
        }
        ofield->set_value(val,*(it));
        ++it;
        cnt++;
        if (cnt==1000)
        {
          cnt=0; c+=1000;
          algo->update_progress(c/sz);
        }
      }
    } else
      if (method == "Min")
      {
        while (it != eit)
        {
          mesh->get_elems(elems, *it);
          size_t nsize = elems.size();
          DATA val(0);
          DATA tval(0);
          if (nsize > 0)
          {
            ifield->get_value(val,elems[0]);
            for (size_t p = 1; p < nsize; p++)
            {
              ifield->value(tval,elems[p]);
              if (tval < val) val = tval;
            }
          }
          ofield->set_value(val,*(it));
          ++it;
          cnt++;
          if (cnt==1000)
          {
            cnt=0; c+=1000;
            algo->update_progress(c/sz);
          }
        }
      } else
        if (method=="Sum")
        {
          while (it != eit)
          {
            mesh->get_elems(elems, *(it));
            size_t nsize = elems.size();
            DATA val(0);
            DATA tval(0);
            for (size_t p = 0; p < nsize; p++)
            {
              ifield->get_value(tval,elems[p]);
              val += tval;
            }
            ofield->set_value(val,*(it));
            ++it;
            cnt++;
            if (cnt==1000)
            {
              cnt=0; c+=1000;
              algo->update_progress(c/sz);
            }
          }
        } else
          if (method == "Median")
          {
            std::vector<DATA> valarray;
            while (it != eit)
            {
              mesh->get_elems(elems, *(it));
              size_t nsize = elems.size();
              valarray.resize(nsize);
              for (size_t p = 0; p < nsize; p++)
              {
                ifield->get_value(valarray[p],elems[p]);
              }
              sort(valarray.begin(),valarray.end());
              int idx = static_cast<int>((valarray.size()/2));
              ofield->set_value(valarray[idx],*(it));
              ++it;
              cnt++;
              if (cnt==1000)
              {
                cnt=0; c+=1000;
                algo->update_progress(c/sz);
              }
            }
          } else
          {
            algo->remark("Method is not implemented!");
            return false;
          }

          return true;
}

MapFieldDataFromElemToNodeAlgo::MapFieldDataFromElemToNodeAlgo()
{
  add_option(Method,"Interpolation","Interpolation|Average|Min|Max|Sum|Median|None");
}

AlgorithmParameterName MapFieldDataFromElemToNodeAlgo::Method("Method");

AlgorithmOutput MapFieldDataFromElemToNodeAlgo::run_generic(const AlgorithmInput& input) const
{
  auto input_field = input.get<Field>(Variables::InputField);

  FieldHandle output_field;
  output_field = run(input_field);

  AlgorithmOutput output;
  output[Variables::OutputField] = output_field;

  return output;
}

/// Function call to convert data from Field into Matrix data
FieldHandle MapFieldDataFromElemToNodeAlgo::run(FieldHandle input_field) const
{
  FieldHandle output;

  if (!input_field)
  {
    THROW_ALGORITHM_INPUT_ERROR("Input field is not allocated");
  }

  FieldInformation fi(input_field);
  FieldInformation fo(input_field);

  if (fi.is_lineardata())
  {
    THROW_ALGORITHM_INPUT_ERROR("Data is already located at nodes");
  }

  if (!(fi.is_constantdata()))
  {
    THROW_ALGORITHM_INPUT_ERROR("The input data needs to be located at the elements");
  }

  fo.make_lineardata();

  output = CreateField(fo,input_field->mesh());

  if (!output)
  {
    THROW_ALGORITHM_INPUT_ERROR("output field cannot be allocated");
  }

  if (input_field->vfield()->is_signed_integer())
  {
    if(!MapFieldDataFromElemToNodeT<int>(this,input_field,output))
    {
      THROW_ALGORITHM_INPUT_ERROR("output int field cannot be allocated");
    }
  }
  else if (input_field->vfield()->is_unsigned_integer())
  {
    if(!MapFieldDataFromElemToNodeT<unsigned int>(this,input_field,output))
    {
      THROW_ALGORITHM_INPUT_ERROR("output uint field cannot be allocated");
    }
  } else if (input_field->vfield()->is_scalar())
  {
    if (!MapFieldDataFromElemToNodeT<double>(this,input_field,output))
    {
      THROW_ALGORITHM_INPUT_ERROR("output scalar field cannot be allocated");
    }
  } else if (input_field->vfield()->is_vector())
  {
    if (!MapFieldDataFromElemToNodeT<Vector>(this,input_field,output))
    {
      THROW_ALGORITHM_INPUT_ERROR("output vector field cannot be allocated");
    }
  } else if (input_field->vfield()->is_tensor())
  {
    if (!MapFieldDataFromElemToNodeT<Tensor>(this,input_field,output))
    {
      THROW_ALGORITHM_INPUT_ERROR("output tensor field cannot be allocated");
    }
  }
  else
  {
    THROW_ALGORITHM_INPUT_ERROR(" Unknown field data type ");
  }

  return output;
}
<|endoftext|>


<commit_before>#include "Archs/SuperH/CShInstruction.h"

#include "Archs/SuperH/SuperH.h"
#include "Archs/SuperH/ShOpcodes.h"
#include "Archs/SuperH/ShParser.h"
#include "Core/Common.h"
#include "Core/FileManager.h"
#include "Core/Misc.h"

CShInstruction::CShInstruction(ShOpcodeData& opcode, ShImmediateData& immediate, ShRegisterData& registers)
{
	this->opcodeData = opcode;
	this->immediateData = immediate;
	this->registerData = registers;
}

CShInstruction::~CShInstruction()
{

}

int getImmediateBits(ShImmediateType type)
{
	switch (type)
	{
	case ShImmediateType::Immediate4:
		return 4;
	case ShImmediateType::Immediate8:
		return 8;
	case ShImmediateType::Immediate12:
		return 12;
	default:
		return 0;
	}
}

bool CShInstruction::Validate(const ValidateState &state)
{
	//bool Result = false;

	//bool previousNop = addNop;
	//addNop = false;

	RamPos = g_fileManager->getVirtualAddress();
	if (RamPos % 2)
	{
		Logger::queueError(Logger::Error, "opcode not aligned to word boundary");
		return false;
	}

	// check immediates
	if (immediateData.primary.type != ShImmediateType::None)
	{
		if (immediateData.primary.expression.isLoaded())
		{
			if (!immediateData.primary.expression.evaluateInteger(immediateData.primary.value))
			{
				Logger::queueError(Logger::Error, "Invalid immediate expression");
				return false;
			}

			immediateData.primary.originalValue = immediateData.primary.value;
		}

		if (opcodeData.opcode.flags & SH_MUSTBEALIGNED)	// immediate must be aligned
		{
			if ((opcodeData.opcode.flags & SH_IMM16) && (immediateData.primary.value % 2))
			{
				Logger::queueError(Logger::Error, "Immediate must be 2-byte aligned");
				return false;
			}

			if ((opcodeData.opcode.flags & SH_IMM32) && (immediateData.primary.value % 4))
			{
				Logger::queueError(Logger::Error, "Immediate must be 4-byte aligned");
				return false;
			}
		}

		int immediateBits = getImmediateBits(immediateData.primary.type);
		int maxImmediate = ((1 << immediateBits) - 1);

		if (opcodeData.opcode.flags & SH_IMMREL)	// relative
		{
			int ldSize = (opcodeData.opcode.flags & SH_IMM32) ? 4 : 2;
			int rPos = (opcodeData.opcode.flags & SH_IMM32) ? ((RamPos+4) & 0xFFFFFFFFFFFFFFFC) : (RamPos+4);
			int range = maxImmediate*ldSize;
			int hiRange = (opcodeData.opcode.flags & SH_IMMSIGNED) ? (range/2) : range;
			int lowRange = (opcodeData.opcode.flags & SH_IMMSIGNED) ? -(range/2) : 0;

			int num = (int) (immediateData.primary.value-rPos);

			if (num > hiRange || num < lowRange)
			{
				Logger::queueError(Logger::Error, "Branch/move target %08X out of range", immediateData.primary.value);
				return false;
			}
			immediateData.primary.value = num;
		}

		if (opcodeData.opcode.flags & SH_IMM16)
			immediateData.primary.value = immediateData.primary.value >> 1;
		else if (opcodeData.opcode.flags & SH_IMM32)
			immediateData.primary.value = immediateData.primary.value >> 2;

		unsigned int mask = (0xFFFFFFFF << (32-immediateBits)) >> (32-immediateBits);
		int digits = (immediateBits+3) / 4;

		if ((unsigned int)std::abs(immediateData.primary.value) > mask)
		{
			Logger::queueError(Logger::Error, "Immediate value 0x%0*X out of range",digits,immediateData.primary.value);
			return false;
		}

		immediateData.primary.value &= mask;
	}

#if 0
	// check load delay
	if (Sh.hasLoadDelay() && Sh.GetLoadDelay() && !IgnoreLoadDelay)
	{
		bool fix = false;

		if (registerData.grd.num != -1 && registerData.grd.num == Sh.GetLoadDelayRegister())
		{
			Logger::queueError(Logger::Warning, "register %S may not be available due to load delay",registerData.grd.name);
			fix = true;
		} else if (registerData.grs.num != -1 && registerData.grs.num == Sh.GetLoadDelayRegister())
		{
			Logger::queueError(Logger::Warning, "register %S may not be available due to load delay",registerData.grs.name);
			fix = true;
		} else if (registerData.grt.num != -1 && registerData.grt.num == Sh.GetLoadDelayRegister()
			&& !(opcodeData.opcode.flags & MO_IGNORERTD))
		{
			Logger::queueError(Logger::Warning, "register %S may not be available due to load delay",registerData.grt.name);
			fix = true;
		}

		if (Sh.GetFixLoadDelay() && fix)
		{
			addNop = true;
			Logger::queueError(Logger::Notice, "added nop to ensure correct behavior");
		}
	}

	if ((opcodeData.opcode.flags & MO_NODELAYSLOT) && Sh.GetDelaySlot() && !IgnoreLoadDelay)
	{
		Logger::queueError(Logger::Error, "This instruction can't be in a delay slot");
	}

	Sh.SetDelaySlot((opcodeData.opcode.flags & MO_DELAY) != 0);

	// now check if this opcode causes a load delay
	if (Sh.hasLoadDelay())
		Sh.SetLoadDelay((opcodeData.opcode.flags & MO_DELAYRT) != 0,registerData.grt.num);

	if (previousNop != addNop)
		Result = true;
#endif

	g_fileManager->advanceMemory(2); //addNop ? 4 : 2
	return false;
}

void CShInstruction::Encode() const
{
	//if (addNop)
	//	g_fileManager->writeU32(0);

	uint16_t encoding = opcodeData.opcode.base;

	switch (opcodeData.opcode.format)
	{
	case SHFMT_0:     // xxxx xxxx xxxx xxxx
		break;
	case SHFMT_N:     // xxxx nnnn xxxx xxxx
		encoding |= (registerData.grt.num & 0xF) << 8;
		break;
	case SHFMT_M:     // xxxx mmmm xxxx xxxx
		encoding |= (registerData.grs.num & 0xF) << 8;
		break;
	case SHFMT_NM:    // xxxx nnnn mmmm xxxx
		encoding |= (registerData.grt.num & 0xF) << 8;
		encoding |= (registerData.grs.num & 0xF) << 4;
		break;
	case SHFMT_MD:    // xxxx xxxx mmmm dddd
		encoding |= (registerData.grs.num & 0xF) << 4;
		encoding |= immediateData.primary.value;
		break;
	case SHFMT_ND4:   // xxxx xxxx nnnn dddd
		encoding |= (registerData.grt.num & 0xF) << 4;
		encoding |= immediateData.primary.value;
		break;
	case SHFMT_NMD:   // xxxx nnnn mmmm dddd
		encoding |= (registerData.grt.num & 0xF) << 8;
		encoding |= (registerData.grs.num & 0xF) << 4;
		encoding |= immediateData.primary.value;
		break;
	case SHFMT_D:     // xxxx xxxx dddd dddd
	case SHFMT_D12:   // xxxx dddd dddd dddd
		encoding |= immediateData.primary.value;
		break;
	case SHFMT_ND8:   // xxxx nnnn dddd dddd
		encoding |= (registerData.grt.num & 0xF) << 8;
		encoding |= immediateData.primary.value;
		break;
	case SHFMT_I:     // xxxx xxxx iiii iiii
		encoding |= immediateData.primary.value;
		break;
	case SHFMT_NI:    // xxxx nnnn iiii iiii
		encoding |= (registerData.grt.num & 0xF) << 8;
		encoding |= immediateData.primary.value;
		break;
	}

	g_fileManager->writeU16((uint16_t)encoding);
}

void CShInstruction::writeTempData(TempData& tempData) const
{
	ShOpcodeFormatter formatter;
	tempData.writeLine(RamPos, formatter.formatOpcode(opcodeData,registerData,immediateData));
}
<commit_msg>Add a comment regarding delayed instructions in SuperH<commit_after>#include "Archs/SuperH/CShInstruction.h"

#include "Archs/SuperH/SuperH.h"
#include "Archs/SuperH/ShOpcodes.h"
#include "Archs/SuperH/ShParser.h"
#include "Core/Common.h"
#include "Core/FileManager.h"
#include "Core/Misc.h"

CShInstruction::CShInstruction(ShOpcodeData& opcode, ShImmediateData& immediate, ShRegisterData& registers)
{
	this->opcodeData = opcode;
	this->immediateData = immediate;
	this->registerData = registers;
}

CShInstruction::~CShInstruction()
{

}

int getImmediateBits(ShImmediateType type)
{
	switch (type)
	{
	case ShImmediateType::Immediate4:
		return 4;
	case ShImmediateType::Immediate8:
		return 8;
	case ShImmediateType::Immediate12:
		return 12;
	default:
		return 0;
	}
}

bool CShInstruction::Validate(const ValidateState &state)
{
	//bool Result = false;

	//bool previousNop = addNop;
	//addNop = false;

	RamPos = g_fileManager->getVirtualAddress();
	if (RamPos % 2)
	{
		Logger::queueError(Logger::Error, "opcode not aligned to word boundary");
		return false;
	}

	// check immediates
	if (immediateData.primary.type != ShImmediateType::None)
	{
		if (immediateData.primary.expression.isLoaded())
		{
			if (!immediateData.primary.expression.evaluateInteger(immediateData.primary.value))
			{
				Logger::queueError(Logger::Error, "Invalid immediate expression");
				return false;
			}

			immediateData.primary.originalValue = immediateData.primary.value;
		}

		if (opcodeData.opcode.flags & SH_MUSTBEALIGNED)	// immediate must be aligned
		{
			if ((opcodeData.opcode.flags & SH_IMM16) && (immediateData.primary.value % 2))
			{
				Logger::queueError(Logger::Error, "Immediate must be 2-byte aligned");
				return false;
			}

			if ((opcodeData.opcode.flags & SH_IMM32) && (immediateData.primary.value % 4))
			{
				Logger::queueError(Logger::Error, "Immediate must be 4-byte aligned");
				return false;
			}
		}

		int immediateBits = getImmediateBits(immediateData.primary.type);
		int maxImmediate = ((1 << immediateBits) - 1);

		if (opcodeData.opcode.flags & SH_IMMREL)	// relative
		{
			int ldSize = (opcodeData.opcode.flags & SH_IMM32) ? 4 : 2;
			int rPos = (opcodeData.opcode.flags & SH_IMM32) ? ((RamPos+4) & 0xFFFFFFFFFFFFFFFC) : (RamPos+4);
			int range = maxImmediate*ldSize;
			int hiRange = (opcodeData.opcode.flags & SH_IMMSIGNED) ? (range/2) : range;
			int lowRange = (opcodeData.opcode.flags & SH_IMMSIGNED) ? -(range/2) : 0;

			int num = (int) (immediateData.primary.value-rPos);

			if (num > hiRange || num < lowRange)
			{
				Logger::queueError(Logger::Error, "Branch/move target %08X out of range", immediateData.primary.value);
				return false;
			}
			immediateData.primary.value = num;
		}

		if (opcodeData.opcode.flags & SH_IMM16)
			immediateData.primary.value = immediateData.primary.value >> 1;
		else if (opcodeData.opcode.flags & SH_IMM32)
			immediateData.primary.value = immediateData.primary.value >> 2;

		unsigned int mask = (0xFFFFFFFF << (32-immediateBits)) >> (32-immediateBits);
		int digits = (immediateBits+3) / 4;

		if ((unsigned int)std::abs(immediateData.primary.value) > mask)
		{
			Logger::queueError(Logger::Error, "Immediate value 0x%0*X out of range",digits,immediateData.primary.value);
			return false;
		}

		immediateData.primary.value &= mask;
	}

    //
    // NOTE: SuperH *does* have delayed instructions, but
    //       I'm not entirely sure how they work exactly yet,
    //       so leaving this functionality off.
    //

#if 0
	// check load delay
	if (Sh.hasLoadDelay() && Sh.GetLoadDelay() && !IgnoreLoadDelay)
	{
		bool fix = false;

		if (registerData.grd.num != -1 && registerData.grd.num == Sh.GetLoadDelayRegister())
		{
			Logger::queueError(Logger::Warning, "register %S may not be available due to load delay",registerData.grd.name);
			fix = true;
		} else if (registerData.grs.num != -1 && registerData.grs.num == Sh.GetLoadDelayRegister())
		{
			Logger::queueError(Logger::Warning, "register %S may not be available due to load delay",registerData.grs.name);
			fix = true;
		} else if (registerData.grt.num != -1 && registerData.grt.num == Sh.GetLoadDelayRegister()
			&& !(opcodeData.opcode.flags & MO_IGNORERTD))
		{
			Logger::queueError(Logger::Warning, "register %S may not be available due to load delay",registerData.grt.name);
			fix = true;
		}

		if (Sh.GetFixLoadDelay() && fix)
		{
			addNop = true;
			Logger::queueError(Logger::Notice, "added nop to ensure correct behavior");
		}
	}

	if ((opcodeData.opcode.flags & MO_NODELAYSLOT) && Sh.GetDelaySlot() && !IgnoreLoadDelay)
	{
		Logger::queueError(Logger::Error, "This instruction can't be in a delay slot");
	}

	Sh.SetDelaySlot((opcodeData.opcode.flags & MO_DELAY) != 0);

	// now check if this opcode causes a load delay
	if (Sh.hasLoadDelay())
		Sh.SetLoadDelay((opcodeData.opcode.flags & MO_DELAYRT) != 0,registerData.grt.num);

	if (previousNop != addNop)
		Result = true;
#endif

	g_fileManager->advanceMemory(2); //addNop ? 4 : 2
	return false;
}

void CShInstruction::Encode() const
{
	//if (addNop)
	//	g_fileManager->writeU32(0);

	uint16_t encoding = opcodeData.opcode.base;

	switch (opcodeData.opcode.format)
	{
	case SHFMT_0:     // xxxx xxxx xxxx xxxx
		break;
	case SHFMT_N:     // xxxx nnnn xxxx xxxx
		encoding |= (registerData.grt.num & 0xF) << 8;
		break;
	case SHFMT_M:     // xxxx mmmm xxxx xxxx
		encoding |= (registerData.grs.num & 0xF) << 8;
		break;
	case SHFMT_NM:    // xxxx nnnn mmmm xxxx
		encoding |= (registerData.grt.num & 0xF) << 8;
		encoding |= (registerData.grs.num & 0xF) << 4;
		break;
	case SHFMT_MD:    // xxxx xxxx mmmm dddd
		encoding |= (registerData.grs.num & 0xF) << 4;
		encoding |= immediateData.primary.value;
		break;
	case SHFMT_ND4:   // xxxx xxxx nnnn dddd
		encoding |= (registerData.grt.num & 0xF) << 4;
		encoding |= immediateData.primary.value;
		break;
	case SHFMT_NMD:   // xxxx nnnn mmmm dddd
		encoding |= (registerData.grt.num & 0xF) << 8;
		encoding |= (registerData.grs.num & 0xF) << 4;
		encoding |= immediateData.primary.value;
		break;
	case SHFMT_D:     // xxxx xxxx dddd dddd
	case SHFMT_D12:   // xxxx dddd dddd dddd
		encoding |= immediateData.primary.value;
		break;
	case SHFMT_ND8:   // xxxx nnnn dddd dddd
		encoding |= (registerData.grt.num & 0xF) << 8;
		encoding |= immediateData.primary.value;
		break;
	case SHFMT_I:     // xxxx xxxx iiii iiii
		encoding |= immediateData.primary.value;
		break;
	case SHFMT_NI:    // xxxx nnnn iiii iiii
		encoding |= (registerData.grt.num & 0xF) << 8;
		encoding |= immediateData.primary.value;
		break;
	}

	g_fileManager->writeU16((uint16_t)encoding);
}

void CShInstruction::writeTempData(TempData& tempData) const
{
	ShOpcodeFormatter formatter;
	tempData.writeLine(RamPos, formatter.formatOpcode(opcodeData,registerData,immediateData));
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2009-2018, Intel Corporation
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
    * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// written by Roman Dementiev
//            Austen Ott
//            Jim Harris (FreeBSD)

#include <sys/types.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifndef _MSC_VER
#include <unistd.h>
#endif
#include "types.h"
#include "msr.h"
#include <assert.h>

#ifdef _MSC_VER

#include <windows.h>
#include "utils.h"
#include "Winmsrdriver\win7\msrstruct.h"
#include "winring0/OlsApiInitExt.h"

#endif

#if defined(__FreeBSD__) || defined(__DragonFly__)
#include <sys/ioccom.h>
#include <sys/cpuctl.h>
#endif

#include <mutex>

namespace pcm {

#ifdef _MSC_VER

extern HMODULE hOpenLibSys;

// here comes an implementatation for Windows
MsrHandle::MsrHandle(uint32 cpu) : cpu_id(cpu)
{
    hDriver = CreateFile(L"\\\\.\\RDMSR", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

    if (hDriver == INVALID_HANDLE_VALUE && hOpenLibSys == NULL)
        throw std::exception();
}

MsrHandle::~MsrHandle()
{
    if (hDriver != INVALID_HANDLE_VALUE) CloseHandle(hDriver);
}

int32 MsrHandle::write(uint64 msr_number, uint64 value)
{
    if (hDriver != INVALID_HANDLE_VALUE)
    {
        MSR_Request req;
        ULONG64 result;
        DWORD reslength = 0;
        req.core_id = cpu_id;
        req.msr_address = msr_number;
        req.write_value = value;
        BOOL status = DeviceIoControl(hDriver, IO_CTL_MSR_WRITE, &req, sizeof(MSR_Request), &result, sizeof(uint64), &reslength, NULL);
        assert(status && "Error in DeviceIoControl");
        return status ? sizeof(uint64) : 0;
    }

    cvt_ds cvt;
    cvt.ui64 = value;

    ThreadGroupTempAffinity affinity(cpu_id);
    DWORD status = Wrmsr((DWORD)msr_number, cvt.ui32.low, cvt.ui32.high);

    return status ? sizeof(uint64) : 0;
}

int32 MsrHandle::read(uint64 msr_number, uint64 * value)
{
    if (hDriver != INVALID_HANDLE_VALUE)
    {
        MSR_Request req;
        // ULONG64 result;
        DWORD reslength = 0;
        req.core_id = cpu_id;
        req.msr_address = msr_number;
        BOOL status = DeviceIoControl(hDriver, IO_CTL_MSR_READ, &req, sizeof(MSR_Request), value, sizeof(uint64), &reslength, NULL);
        assert(status && "Error in DeviceIoControl");
        return (int32)reslength;
    }

    cvt_ds cvt;
    cvt.ui64 = 0;

    ThreadGroupTempAffinity affinity(cpu_id);
    DWORD status = Rdmsr((DWORD)msr_number, &(cvt.ui32.low), &(cvt.ui32.high));

    if (status) *value = cvt.ui64;

    return status ? sizeof(uint64) : 0;
}

#elif __APPLE__
// OSX Version

MSRAccessor * MsrHandle::driver = NULL;
int MsrHandle::num_handles = 0;

MsrHandle::MsrHandle(uint32 cpu)
{
    cpu_id = cpu;
    if (!driver)
    {
        driver = new MSRAccessor();
        MsrHandle::num_handles = 1;
    }
    else
    {
        MsrHandle::num_handles++;
    }
}

MsrHandle::~MsrHandle()
{
    MsrHandle::num_handles--;
    if (MsrHandle::num_handles == 0)
    {
        delete driver;
        driver = NULL;
    }
}

int32 MsrHandle::write(uint64 msr_number, uint64 value)
{
    return driver->write(cpu_id, msr_number, value);
}

int32 MsrHandle::read(uint64 msr_number, uint64 * value)
{
    return driver->read(cpu_id, msr_number, value);
}

int32 MsrHandle::buildTopology(uint32 num_cores, void * ptr)
{
    return driver->buildTopology(num_cores, ptr);
}

uint32 MsrHandle::getNumInstances()
{
    return driver->getNumInstances();
}

uint32 MsrHandle::incrementNumInstances()
{
    return driver->incrementNumInstances();
}

uint32 MsrHandle::decrementNumInstances()
{
    return driver->decrementNumInstances();
}

#elif defined(__FreeBSD__) || defined(__DragonFly__)

MsrHandle::MsrHandle(uint32 cpu) : fd(-1), cpu_id(cpu)
{
    char path[200];
    snprintf(path, 200, "/dev/cpuctl%d", cpu);
    int handle = ::open(path, O_RDWR);
    if (handle < 0) throw std::exception();
    fd = handle;
}

MsrHandle::~MsrHandle()
{
    if (fd >= 0) ::close(fd);
}

int32 MsrHandle::write(uint64 msr_number, uint64 value)
{
    cpuctl_msr_args_t args;
    int ret;

    args.msr = msr_number;
    args.data = value;
    ret = ::ioctl(fd, CPUCTL_WRMSR, &args);
    if (ret) return ret;
    return sizeof(value);
}

int32 MsrHandle::read(uint64 msr_number, uint64 * value)
{
    cpuctl_msr_args_t args;
    int32 ret;

    args.msr = msr_number;
    ret = ::ioctl(fd, CPUCTL_RDMSR, &args);
    if (ret) return ret;
    *value = args.data;
    return sizeof(*value);
}

#else
// here comes a Linux version
MsrHandle::MsrHandle(uint32 cpu) : fd(-1), cpu_id(cpu)
{
    char * path = new char[200];
    snprintf(path, 200, "/dev/cpu/%d/msr", cpu);
    int handle = ::open(path, O_RDWR);
    if (handle < 0)
    {   // try Android msr device path
        snprintf(path, 200, "/dev/msr%d", cpu);
        handle = ::open(path, O_RDWR);
    }
    delete[] path;
    if (handle < 0)
    {
         std::cerr << "PCM Error: can't open MSR handle for core " << cpu << "\n";
         throw std::exception();
    }
    fd = handle;
}

MsrHandle::~MsrHandle()
{
    if (fd >= 0) ::close(fd);
}

int32 MsrHandle::write(uint64 msr_number, uint64 value)
{
#if 0
    static std::mutex m;
    std::lock_guard<std::mutex> g(m);
    std::cout << "DEBUG: writing MSR 0x" << std::hex << msr_number << " value 0x" << value << " on cpu " << std::dec << cpu_id << std::endl;
#endif
    return ::pwrite(fd, (const void *)&value, sizeof(uint64), msr_number);
}

int32 MsrHandle::read(uint64 msr_number, uint64 * value)
{
    return ::pread(fd, (void *)value, sizeof(uint64), msr_number);
}

#endif

} // namespace pcm
<commit_msg>allow writes for Linux MSR driver<commit_after>/*
Copyright (c) 2009-2018, Intel Corporation
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
    * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// written by Roman Dementiev
//            Austen Ott
//            Jim Harris (FreeBSD)

#include <sys/types.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifndef _MSC_VER
#include <unistd.h>
#endif
#include "types.h"
#include "msr.h"
#include "utils.h"
#include <assert.h>

#ifdef _MSC_VER

#include <windows.h>
#include "utils.h"
#include "Winmsrdriver\win7\msrstruct.h"
#include "winring0/OlsApiInitExt.h"

#endif

#if defined(__FreeBSD__) || defined(__DragonFly__)
#include <sys/ioccom.h>
#include <sys/cpuctl.h>
#endif

#include <mutex>

namespace pcm {

#ifdef _MSC_VER

extern HMODULE hOpenLibSys;

// here comes an implementatation for Windows
MsrHandle::MsrHandle(uint32 cpu) : cpu_id(cpu)
{
    hDriver = CreateFile(L"\\\\.\\RDMSR", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

    if (hDriver == INVALID_HANDLE_VALUE && hOpenLibSys == NULL)
        throw std::exception();
}

MsrHandle::~MsrHandle()
{
    if (hDriver != INVALID_HANDLE_VALUE) CloseHandle(hDriver);
}

int32 MsrHandle::write(uint64 msr_number, uint64 value)
{
    if (hDriver != INVALID_HANDLE_VALUE)
    {
        MSR_Request req;
        ULONG64 result;
        DWORD reslength = 0;
        req.core_id = cpu_id;
        req.msr_address = msr_number;
        req.write_value = value;
        BOOL status = DeviceIoControl(hDriver, IO_CTL_MSR_WRITE, &req, sizeof(MSR_Request), &result, sizeof(uint64), &reslength, NULL);
        assert(status && "Error in DeviceIoControl");
        return status ? sizeof(uint64) : 0;
    }

    cvt_ds cvt;
    cvt.ui64 = value;

    ThreadGroupTempAffinity affinity(cpu_id);
    DWORD status = Wrmsr((DWORD)msr_number, cvt.ui32.low, cvt.ui32.high);

    return status ? sizeof(uint64) : 0;
}

int32 MsrHandle::read(uint64 msr_number, uint64 * value)
{
    if (hDriver != INVALID_HANDLE_VALUE)
    {
        MSR_Request req;
        // ULONG64 result;
        DWORD reslength = 0;
        req.core_id = cpu_id;
        req.msr_address = msr_number;
        BOOL status = DeviceIoControl(hDriver, IO_CTL_MSR_READ, &req, sizeof(MSR_Request), value, sizeof(uint64), &reslength, NULL);
        assert(status && "Error in DeviceIoControl");
        return (int32)reslength;
    }

    cvt_ds cvt;
    cvt.ui64 = 0;

    ThreadGroupTempAffinity affinity(cpu_id);
    DWORD status = Rdmsr((DWORD)msr_number, &(cvt.ui32.low), &(cvt.ui32.high));

    if (status) *value = cvt.ui64;

    return status ? sizeof(uint64) : 0;
}

#elif __APPLE__
// OSX Version

MSRAccessor * MsrHandle::driver = NULL;
int MsrHandle::num_handles = 0;

MsrHandle::MsrHandle(uint32 cpu)
{
    cpu_id = cpu;
    if (!driver)
    {
        driver = new MSRAccessor();
        MsrHandle::num_handles = 1;
    }
    else
    {
        MsrHandle::num_handles++;
    }
}

MsrHandle::~MsrHandle()
{
    MsrHandle::num_handles--;
    if (MsrHandle::num_handles == 0)
    {
        delete driver;
        driver = NULL;
    }
}

int32 MsrHandle::write(uint64 msr_number, uint64 value)
{
    return driver->write(cpu_id, msr_number, value);
}

int32 MsrHandle::read(uint64 msr_number, uint64 * value)
{
    return driver->read(cpu_id, msr_number, value);
}

int32 MsrHandle::buildTopology(uint32 num_cores, void * ptr)
{
    return driver->buildTopology(num_cores, ptr);
}

uint32 MsrHandle::getNumInstances()
{
    return driver->getNumInstances();
}

uint32 MsrHandle::incrementNumInstances()
{
    return driver->incrementNumInstances();
}

uint32 MsrHandle::decrementNumInstances()
{
    return driver->decrementNumInstances();
}

#elif defined(__FreeBSD__) || defined(__DragonFly__)

MsrHandle::MsrHandle(uint32 cpu) : fd(-1), cpu_id(cpu)
{
    char path[200];
    snprintf(path, 200, "/dev/cpuctl%d", cpu);
    int handle = ::open(path, O_RDWR);
    if (handle < 0) throw std::exception();
    fd = handle;
}

MsrHandle::~MsrHandle()
{
    if (fd >= 0) ::close(fd);
}

int32 MsrHandle::write(uint64 msr_number, uint64 value)
{
    cpuctl_msr_args_t args;
    int ret;

    args.msr = msr_number;
    args.data = value;
    ret = ::ioctl(fd, CPUCTL_WRMSR, &args);
    if (ret) return ret;
    return sizeof(value);
}

int32 MsrHandle::read(uint64 msr_number, uint64 * value)
{
    cpuctl_msr_args_t args;
    int32 ret;

    args.msr = msr_number;
    ret = ::ioctl(fd, CPUCTL_RDMSR, &args);
    if (ret) return ret;
    *value = args.data;
    return sizeof(*value);
}

#else
// here comes a Linux version
MsrHandle::MsrHandle(uint32 cpu) : fd(-1), cpu_id(cpu)
{
    constexpr auto allowWritesPath = "/sys/module/msr/parameters/allow_writes";
    static bool writesEnabled = false;
    if (writesEnabled == false)
    {
        if (readSysFS(allowWritesPath, true).length() > 0)
        {
            writeSysFS(allowWritesPath, "on", false);
        }
        writesEnabled = true;
    }
    char * path = new char[200];
    snprintf(path, 200, "/dev/cpu/%d/msr", cpu);
    int handle = ::open(path, O_RDWR);
    if (handle < 0)
    {   // try Android msr device path
        snprintf(path, 200, "/dev/msr%d", cpu);
        handle = ::open(path, O_RDWR);
    }
    delete[] path;
    if (handle < 0)
    {
         std::cerr << "PCM Error: can't open MSR handle for core " << cpu << "\n";
         throw std::exception();
    }
    fd = handle;
}

MsrHandle::~MsrHandle()
{
    if (fd >= 0) ::close(fd);
}

int32 MsrHandle::write(uint64 msr_number, uint64 value)
{
#if 0
    static std::mutex m;
    std::lock_guard<std::mutex> g(m);
    std::cout << "DEBUG: writing MSR 0x" << std::hex << msr_number << " value 0x" << value << " on cpu " << std::dec << cpu_id << std::endl;
#endif
    return ::pwrite(fd, (const void *)&value, sizeof(uint64), msr_number);
}

int32 MsrHandle::read(uint64 msr_number, uint64 * value)
{
    return ::pread(fd, (void *)value, sizeof(uint64), msr_number);
}

#endif

} // namespace pcm
<|endoftext|>


<commit_before>#include <cstdio>
#include <cstring>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <map>
#include <iomanip>
#include <algorithm>
#include <assert.h>

#include "lieonn.hh"
typedef myfloat num_t;

#if ! defined(_FLOAT_BITS_)
#define _FLOAT_BITS_ 63
#endif
#include <cmath>

int main(int argc, char* argv[]) {
  SimpleMatrix<num_t> A(8 + 1, 6);
  SimpleVector<num_t> left(A.rows());
  SimpleVector<num_t> right(A.rows());
  for(int j = 0; j < 8; j ++) {
    SimpleVector<num_t> work(4);
    work[0]  = num_t(j & 1 ? 1 : 2) / num_t(2);
    work[1]  = num_t((j >> 1) & 1 ? 1 : 2) / num_t(2);
    work[2]  = num_t((j >> 2) & 1 ? 1 : 2) / num_t(2);
    work[3]  = num_t(!((j & 1) && ((j >> 1) & 1)) && ((j >> 2) & 1) ? 2 : 1) / num_t(2);
    A.row(j) = makeProgramInvariant<num_t>(work).first;
    assert(A.cols() == A.row(j).size());
    left[j]  = - (right[j] = sqrt(A.epsilon));
  }
  for(int j = 0; j < A.cols(); j ++)
    A(8, j) = num_t(4 == j ? 1 : 0);
  left[8]  = sqrt(sqrt(A.epsilon));
  right[8] = num_t(1) / sqrt(sqrt(A.epsilon));
  const auto in(A.inner(left, right));
  std::cout << A * in << std::endl;
  return 0;
}

<commit_msg>fix last.<commit_after>#include <cstdio>
#include <cstring>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <map>
#include <iomanip>
#include <algorithm>
#include <assert.h>

#include "lieonn.hh"
typedef myfloat num_t;

#if ! defined(_FLOAT_BITS_)
#define _FLOAT_BITS_ 63
#endif
#include <cmath>

int main(int argc, char* argv[]) {
  SimpleMatrix<num_t> A(8 + 1, 6);
  SimpleVector<num_t> left(A.rows());
  SimpleVector<num_t> right(A.rows());
  for(int j = 0; j < 8; j ++) {
    SimpleVector<num_t> work(4);
    work[0]  = num_t(j & 1 ? 1 : 2) / num_t(2);
    work[1]  = num_t((j >> 1) & 1 ? 1 : 2) / num_t(2);
    work[2]  = num_t((j >> 2) & 1 ? 1 : 2) / num_t(2);
    work[3]  = num_t(!((j & 1) && ((j >> 1) & 1)) && ((j >> 2) & 1) ? 2 : 1) / num_t(2);
    A.row(j) = makeProgramInvariant<num_t>(work).first;
    assert(A.cols() == A.row(j).size());
    left[j]  = - (right[j] = sqrt(A.epsilon));
  }
  for(int j = 0; j < A.cols(); j ++)
    A(8, j) = num_t(3 == j ? 1 : 0);
  left[8]  = sqrt(sqrt(A.epsilon));
  right[8] = num_t(1) / sqrt(sqrt(A.epsilon));
  const auto in(A.inner(left, right));
  std::cout << A * in << std::endl;
  return 0;
}

<|endoftext|>


<commit_before>#include <test/unit/math/test_ad.hpp>
#include <cmath>
#include <complex>
#include <vector>
#include <type_traits>

TEST(mixFun, abs) {
  auto f = [](const auto& x) {
    using std::abs;
    return abs(x);
  };
  stan::test::expect_common_nonzero_unary(f);
  stan::test::expect_value(f, 0);
  stan::test::expect_value(f, 0.0);

  stan::test::expect_ad(f, -3);
  stan::test::expect_ad(f, -2);
  stan::test::expect_ad(f, 2);

  stan::test::expect_ad(f, -17.3);
  stan::test::expect_ad(f, -0.68);
  stan::test::expect_ad(f, 0.68);
  stan::test::expect_ad(f, 2.0);
  stan::test::expect_ad(f, 4.0);

  // not differentiable at zero
  for (double re : std::vector<double>{-4, -2.5, -1.5, -0.3, 1.3, 2.1, 3.9}) {
    for (double im : std::vector<double>{-4, -2.5, -1.5, -0.3, 1.3, 2.1, 3.9}) {
      stan::test::expect_ad(f, std::complex<double>(re, im));
    }
  }
}
TEST(mixFun, absReturnType) {
  // validate return types not overpromoted to complex by assignability
  std::complex<stan::math::var> a = 3;
  stan::math::var b = abs(a);

  std::complex<stan::math::fvar<double>> c = 3;
  stan::math::fvar<double> d = abs(c);
  SUCCEED();
}

TEST(mathMixMatFun, abs_varmat) {
  using stan::math::vec_concat;
  using stan::test::expect_ad_vector_matvar;
  using stan::test::internal::common_nonzero_args;
  auto f = [](const auto& x1) {
    using stan::math::abs;
    return abs(x1);
  };
  std::vector<double> com_args = common_nonzero_args();
  std::vector<double> args{0, -3, -2, 2, -17.3, -0.68, 2, 4};
  auto all_args = vec_concat(com_args, args);
  Eigen::VectorXd A(all_args.size());
  for (int i = 0; i < all_args.size(); ++i) {
    A(i) = all_args[i];
  }
  expect_ad_vector_matvar(f, A);
}
<commit_msg>Don't test abs gradients at 0 cause they don't exist (Issue #2101)<commit_after>#include <test/unit/math/test_ad.hpp>
#include <cmath>
#include <complex>
#include <vector>
#include <type_traits>

TEST(mixFun, abs) {
  auto f = [](const auto& x) {
    using std::abs;
    return abs(x);
  };
  stan::test::expect_common_nonzero_unary(f);
  stan::test::expect_value(f, 0);
  stan::test::expect_value(f, 0.0);

  stan::test::expect_ad(f, -3);
  stan::test::expect_ad(f, -2);
  stan::test::expect_ad(f, 2);

  stan::test::expect_ad(f, -17.3);
  stan::test::expect_ad(f, -0.68);
  stan::test::expect_ad(f, 0.68);
  stan::test::expect_ad(f, 2.0);
  stan::test::expect_ad(f, 4.0);

  // not differentiable at zero
  for (double re : std::vector<double>{-4, -2.5, -1.5, -0.3, 1.3, 2.1, 3.9}) {
    for (double im : std::vector<double>{-4, -2.5, -1.5, -0.3, 1.3, 2.1, 3.9}) {
      stan::test::expect_ad(f, std::complex<double>(re, im));
    }
  }
}
TEST(mixFun, absReturnType) {
  // validate return types not overpromoted to complex by assignability
  std::complex<stan::math::var> a = 3;
  stan::math::var b = abs(a);

  std::complex<stan::math::fvar<double>> c = 3;
  stan::math::fvar<double> d = abs(c);
  SUCCEED();
}

TEST(mathMixMatFun, abs_varmat) {
  using stan::math::vec_concat;
  using stan::test::expect_ad_vector_matvar;
  using stan::test::internal::common_nonzero_args;
  auto f = [](const auto& x1) {
    using stan::math::abs;
    return abs(x1);
  };
  std::vector<double> com_args = common_nonzero_args();
  std::vector<double> args{-3, 2, -0.68, 1};
  auto all_args = vec_concat(com_args, args);
  Eigen::VectorXd A(all_args.size());
  for (int i = 0; i < all_args.size(); ++i) {
    A(i) = all_args[i];
  }
  expect_ad_vector_matvar(f, A);
}
<|endoftext|>


<commit_before><commit_msg>Use valueChanged not sliderMoved<commit_after><|endoftext|>


<commit_before><commit_msg>fix: add missing include file<commit_after><|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_ERR_IS_MAT_FINITE_HPP
#define STAN_MATH_PRIM_ERR_IS_MAT_FINITE_HPP

#include <stan/math/prim/fun/Eigen.hpp>
#include <stan/math/prim/meta.hpp>

namespace stan {
namespace math {

/**
 * Return true is the specified matrix is finite.
 * @tparam T Scalar type of the matrix, requires class method
 * .allFinite()
 * @tparam EigMat A type derived from `EigenBase`
 * @param y Matrix to test
 * @return true if the matrix is finite
 **/
template <typename EigMat, require_eigen_t<EigMat>* = nullptr>
inline bool is_mat_finite(const EigMat& y) {
  return y.allFinite();
}

}  // namespace math
}  // namespace stan
#endif
<commit_msg>add to_ref for is_mat_finite<commit_after>#ifndef STAN_MATH_PRIM_ERR_IS_MAT_FINITE_HPP
#define STAN_MATH_PRIM_ERR_IS_MAT_FINITE_HPP

#include <stan/math/prim/fun/Eigen.hpp>
#include <stan/math/prim/fun/to_ref.hpp>
#include <stan/math/prim/meta.hpp>

namespace stan {
namespace math {

/**
 * Return true is the specified matrix is finite.
 * @tparam T Scalar type of the matrix, requires class method
 * .allFinite()
 * @tparam EigMat A type derived from `EigenBase`
 * @param y Matrix to test
 * @return true if the matrix is finite
 **/
template <typename EigMat, require_eigen_t<EigMat>* = nullptr>
inline bool is_mat_finite(const EigMat& y) {
  return to_ref(y).allFinite();
}

}  // namespace math
}  // namespace stan
#endif
<|endoftext|>


<commit_before><commit_msg>Keep Gups from sending unnecessary completions<commit_after><|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_FUN_LUB_CONSTRAIN_HPP
#define STAN_MATH_PRIM_FUN_LUB_CONSTRAIN_HPP

#include <stan/math/prim/fun/Eigen.hpp>
#include <stan/math/prim/meta.hpp>
#include <stan/math/prim/err.hpp>
#include <stan/math/prim/fun/add.hpp>
#include <stan/math/prim/fun/exp.hpp>
#include <stan/math/prim/fun/elt_multiply.hpp>
#include <stan/math/prim/fun/inv_logit.hpp>
#include <stan/math/prim/fun/log.hpp>
#include <stan/math/prim/fun/log1p.hpp>
#include <stan/math/prim/fun/multiply.hpp>
#include <stan/math/prim/fun/subtract.hpp>
#include <stan/math/prim/fun/sum.hpp>
#include <cmath>

namespace stan {
namespace math {

/**
 * Return the lower- and upper-bounded scalar derived by
 * transforming the specified free scalar given the specified
 * lower and upper bounds.
 *
 *
The transform is the transformed and scaled inverse logit,
 *
 *
\f$f(x) = L + (U - L) \mbox{logit}^{-1}(x)\f$
 *
 * @tparam T Type of scalar.
 * @tparam L Type of lower bound.
 * @tparam U Type of upper bound.
 * @param[in] x Free scalar to transform.
 * @param[in] lb Lower bound.
 * @param[in] ub Upper bound.
 * @return Lower- and upper-bounded scalar derived from transforming
 *   the free scalar.
 * @throw std::domain_error if ub <= lb
 */
template <typename T, typename L, typename U>
inline auto lub_constrain(const T& x, const L& lb, const U& ub) {
  const auto& x_ref = to_ref(x);
  const auto& lb_ref = to_ref(lb);
  const auto& ub_ref = to_ref(ub);

  check_less("lub_constrain", "lb", value_of(lb_ref), value_of(ub_ref));
  check_finite("lub_constrain", "lb", value_of(lb_ref));
  check_finite("lub_constrain", "ub", value_of(ub_ref));

  return eval(
      add(elt_multiply(subtract(ub_ref, lb_ref), inv_logit(x_ref)), lb_ref));
}

/**
 * Return the lower- and upper-bounded scalar derived by
 * transforming the specified free scalar given the specified
 * lower and upper bounds and increment the specified log
 * density with the log absolute Jacobian determinant.
 *
 *
The transform is as defined in
 * lub_constrain(T, double, double).  The log absolute
 * Jacobian determinant is given by
 *
 *
\f$\log \left| \frac{d}{dx} \left(
 *                L + (U-L) \mbox{logit}^{-1}(x) \right)
 *            \right|\f$
 *
 *
\f$ {} = \log |
 *         (U-L)
 *         \, (\mbox{logit}^{-1}(x))
 *         \, (1 - \mbox{logit}^{-1}(x)) |\f$
 *
 *
\f$ {} = \log (U - L) + \log (\mbox{logit}^{-1}(x))
 *                          + \log (1 - \mbox{logit}^{-1}(x))\f$
 *
 * @tparam T Type of scalar.
 * @tparam L Type of lower bound.
 * @tparam U Type of upper bound.
 * @param[in] x Free scalar to transform.
 * @param[in] lb Lower bound.
 * @param[in] ub Upper bound.
 * @param[in,out] lp Log probability scalar reference.
 * @return Lower- and upper-bounded scalar derived from transforming
 *   the free scalar.
 * @throw std::domain_error if ub <= lb
 */
template <typename T, typename L, typename U>
inline auto lub_constrain(const T& x, const L& lb, const U& ub,
                          return_type_t<T, L, U>& lp) {
  const auto& x_ref = to_ref(x);
  const auto& lb_ref = to_ref(lb);
  const auto& ub_ref = to_ref(ub);

  check_less("lub_constrain", "lb", value_of(lb_ref), value_of(ub_ref));
  check_finite("lub_constrain", "lb", value_of(lb_ref));
  check_finite("lub_constrain", "ub", value_of(ub_ref));

  const auto& diff = to_ref(subtract(ub_ref, lb_ref));

  lp += sum(add(log(diff),
                subtract(-abs(x_ref), multiply(2, log1p_exp(-abs(x_ref))))));
  return eval(add(elt_multiply(diff, inv_logit(x_ref)), lb_ref));
}

}  // namespace math
}  // namespace stan
#endif
<commit_msg>[Jenkins] auto-formatting by clang-format version 6.0.0-1ubuntu2~16.04.1 (tags/RELEASE_600/final)<commit_after>#ifndef STAN_MATH_PRIM_FUN_LUB_CONSTRAIN_HPP
#define STAN_MATH_PRIM_FUN_LUB_CONSTRAIN_HPP

#include <stan/math/prim/fun/Eigen.hpp>
#include <stan/math/prim/meta.hpp>
#include <stan/math/prim/err.hpp>
#include <stan/math/prim/fun/add.hpp>
#include <stan/math/prim/fun/exp.hpp>
#include <stan/math/prim/fun/elt_multiply.hpp>
#include <stan/math/prim/fun/inv_logit.hpp>
#include <stan/math/prim/fun/log.hpp>
#include <stan/math/prim/fun/log1p.hpp>
#include <stan/math/prim/fun/multiply.hpp>
#include <stan/math/prim/fun/subtract.hpp>
#include <stan/math/prim/fun/sum.hpp>
#include <cmath>

namespace stan {
namespace math {

/**
 * Return the lower- and upper-bounded scalar derived by
 * transforming the specified free scalar given the specified
 * lower and upper bounds.
 *
 *
The transform is the transformed and scaled inverse logit,
 *
 *
\f$f(x) = L + (U - L) \mbox{logit}^{-1}(x)\f$
 *
 * @tparam T Type of scalar.
 * @tparam L Type of lower bound.
 * @tparam U Type of upper bound.
 * @param[in] x Free scalar to transform.
 * @param[in] lb Lower bound.
 * @param[in] ub Upper bound.
 * @return Lower- and upper-bounded scalar derived from transforming
 *   the free scalar.
 * @throw std::domain_error if ub <= lb
 */
template <typename T, typename L, typename U>
inline auto lub_constrain(const T& x, const L& lb, const U& ub) {
  const auto& x_ref = to_ref(x);
  const auto& lb_ref = to_ref(lb);
  const auto& ub_ref = to_ref(ub);

  check_less("lub_constrain", "lb", value_of(lb_ref), value_of(ub_ref));
  check_finite("lub_constrain", "lb", value_of(lb_ref));
  check_finite("lub_constrain", "ub", value_of(ub_ref));

  return eval(
      add(elt_multiply(subtract(ub_ref, lb_ref), inv_logit(x_ref)), lb_ref));
}

/**
 * Return the lower- and upper-bounded scalar derived by
 * transforming the specified free scalar given the specified
 * lower and upper bounds and increment the specified log
 * density with the log absolute Jacobian determinant.
 *
 *
The transform is as defined in
 * lub_constrain(T, double, double).  The log absolute
 * Jacobian determinant is given by
 *
 *
\f$\log \left| \frac{d}{dx} \left(
 *                L + (U-L) \mbox{logit}^{-1}(x) \right)
 *            \right|\f$
 *
 *
\f$ {} = \log |
 *         (U-L)
 *         \, (\mbox{logit}^{-1}(x))
 *         \, (1 - \mbox{logit}^{-1}(x)) |\f$
 *
 *
\f$ {} = \log (U - L) + \log (\mbox{logit}^{-1}(x))
 *                          + \log (1 - \mbox{logit}^{-1}(x))\f$
 *
 * @tparam T Type of scalar.
 * @tparam L Type of lower bound.
 * @tparam U Type of upper bound.
 * @param[in] x Free scalar to transform.
 * @param[in] lb Lower bound.
 * @param[in] ub Upper bound.
 * @param[in,out] lp Log probability scalar reference.
 * @return Lower- and upper-bounded scalar derived from transforming
 *   the free scalar.
 * @throw std::domain_error if ub <= lb
 */
template <typename T, typename L, typename U>
inline auto lub_constrain(const T& x, const L& lb, const U& ub,
                          return_type_t<T, L, U>& lp) {
  const auto& x_ref = to_ref(x);
  const auto& lb_ref = to_ref(lb);
  const auto& ub_ref = to_ref(ub);

  check_less("lub_constrain", "lb", value_of(lb_ref), value_of(ub_ref));
  check_finite("lub_constrain", "lb", value_of(lb_ref));
  check_finite("lub_constrain", "ub", value_of(ub_ref));

  const auto& diff = to_ref(subtract(ub_ref, lb_ref));

  lp += sum(add(log(diff),
                subtract(-abs(x_ref), multiply(2, log1p_exp(-abs(x_ref))))));
  return eval(add(elt_multiply(diff, inv_logit(x_ref)), lb_ref));
}

}  // namespace math
}  // namespace stan
#endif
<|endoftext|>


<commit_before>/** @file
    @brief Implementation

    @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

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

// Internal Includes
#include "DeviceWrapper.h"

// Library/third-party includes
// - none

// Standard includes
// - none

namespace osvr {
namespace common {

    DeviceWrapper::DeviceWrapper(std::string const &name,
                                 vrpn_ConnectionPtr const &conn, bool client)
        : vrpn_BaseClass(name.c_str(), conn.get()), m_conn(conn),
          m_client(client) {
        vrpn_BaseClass::init();
        m_setup(conn, common::RawSenderType(d_sender_id));

        // Clients: don't print "haven't heard from server" messages.
        if (client) {
            shutup = true;
        }
    }

    DeviceWrapper::~DeviceWrapper() {}

    void DeviceWrapper::mainloop() { update(); }

    void DeviceWrapper::m_update() {
        if (m_client) {
            client_mainloop();
            m_getConnection()->mainloop();
        } else {
            server_mainloop();
        }
    }

    int DeviceWrapper::register_types() {
        return 0; // success
    }
} // namespace common
} // namespace osvr
<commit_msg>Mainloop connection first in client devices.<commit_after>/** @file
    @brief Implementation

    @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

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

// Internal Includes
#include "DeviceWrapper.h"

// Library/third-party includes
// - none

// Standard includes
// - none

namespace osvr {
namespace common {

    DeviceWrapper::DeviceWrapper(std::string const &name,
                                 vrpn_ConnectionPtr const &conn, bool client)
        : vrpn_BaseClass(name.c_str(), conn.get()), m_conn(conn),
          m_client(client) {
        vrpn_BaseClass::init();
        m_setup(conn, common::RawSenderType(d_sender_id));

        // Clients: don't print "haven't heard from server" messages.
        if (client) {
            shutup = true;
        }
    }

    DeviceWrapper::~DeviceWrapper() {}

    void DeviceWrapper::mainloop() { update(); }

    void DeviceWrapper::m_update() {
        if (m_client) {
            m_getConnection()->mainloop();
            client_mainloop();
        } else {
            server_mainloop();
        }
    }

    int DeviceWrapper::register_types() {
        return 0; // success
    }
} // namespace common
} // namespace osvr
<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include "6502.h"

// For testing purposes
#include "opcodes.h"

static bool
LoadProgram(ram_t *Ram, const char *Filename)
{
    FILE *File = fopen(Filename, "rb");
    bool Result = false;
    if (File) {
        Result = true;
        fseek(File, 0, SEEK_END);
        u16 ProgramSize = ftell(File);
        fseek(File, 0, SEEK_SET);
        u8 *Program = (u8 *)calloc(ProgramSize, 1);
        fread(Program, 1, ProgramSize, File);
        fclose(File);
        free(Program);

        LoadProgram(Ram, Program, ProgramSize);
    }
    return Result;
}

static void
MemoryDump(ram_t *Ram, u16 StartAddress, u16 Length, u16 ColumnWidth, u16 MarkAddress = 0)
{
    for (u16 Address = StartAddress;
        Address < StartAddress + Length;
        )
    {
        printf("%4x  ", Address);
        for (u16 Offset = 0; Offset < ColumnWidth; ++Offset) {
            bool MarkThisOne = (MarkAddress > 0 && MarkAddress == Address);
            if (MarkThisOne) {
                printf("[");
            }
            printf("%-2x", Ram->Data[Address++]);
            if (MarkThisOne) {
                printf("]");
            } else {
                printf("  ");
            }
        }
        printf("\n");
    }
}

static void
Monitor(cpu_t *Cpu, ram_t *Ram)
{
    const char *StatusFlags = "\nNOIBDIZC      A  X  Y  PC SP    Memory snapshot (%04x - %04x)\n%s      %-2x %-2x %-2x %-2x %-2x    ";
    const char *Menu = "[s]ingle-step [r]estart [g]oto [+/-] PC [m]emory s[t]ack [q]uit >";
    bool Running = true;
    u16 MemoryDumpStart = 0;
    u8 MemoryDumpCount = 20;
    while (Running) {
        char Input[128] = {0};
        printf(StatusFlags, MemoryDumpStart, MemoryDumpStart + MemoryDumpCount, GetStatusRegisters(Cpu->SR), Cpu->A, Cpu->X, Cpu->Y, Cpu->PC, Cpu->SP);
        // Print memory footprint
        for (u16 MemoryAddress = MemoryDumpStart;
             MemoryAddress < MemoryDumpStart + MemoryDumpCount;
             ++MemoryAddress)
        {
            printf("%2x ", Ram->Data[MemoryAddress]);
        }
        printf("\n");
        opcode_e OpCode = (opcode_e)Ram->Data[Cpu->PC];
        instruction_t Instruction = DecodeOpCode(OpCode);
        char *OpCodeName = "(not impl)";
        if (Instruction.Func) {
            OpCodeName = Instruction.OpCodeName;
        }
        printf("%2X: %9s (%2x) ", Cpu->PC, OpCodeName, OpCode);

        printf(Menu);
        scanf("%127s", Input);

        if (Input) {
            for (char *CurrentInput = Input; *CurrentInput; ++CurrentInput) {
                switch (*CurrentInput) {
                    case 'r':
                        memset(Cpu, 0, sizeof(cpu_t));
                        break;

                    case 'q':
                        Running = false;
                        break;

                    case 's':
                        SingleStepProgram(Cpu, Ram);
                        break;

                    case 't':
                        MemoryDump(Ram, STACK_ADDR(0), 0xFF, 0xF, STACK_ADDR(Cpu->SP));
                        break;

                    case 'g':
                        {
                            printf("Enter new PC: ");
                            scanf("%d", &Cpu->PC);
                            break;
                        }

                    case '+':
                        Cpu->PC++;
                        break;

                    case '-':
                        Cpu->PC--;
                        break;

                    case 'm':
                        MemoryDump(Ram, MemoryDumpStart, 128, 16, MemoryDumpStart);
                        break;

                }
            }
        }
    }
}

int
main(int argc, char *argv[])
{
    cpu_t Cpu = {0};
    ram_t Ram = {0};

    //*
    u8 Program[] = {
        ASL_zpg, 0, PHP
    };
    Ram.Data[0] = 0xAA;
    u8 ProgramCount = sizeof(Program) / sizeof(Program[0]);
    LoadProgram(&Ram, Program, ProgramCount, 0x10);
    //*/
    //LoadProgram(&Ram, "rom/atari2600/Vid_olym.bin");
    // SingleStepProgram(&Cpu, &Ram);
    Monitor(&Cpu, &Ram);

    printf("Program ran for %i cycles.\n", Cpu.CycleCount);

    return 0;
}
<commit_msg>Pretty print opname(opcode) additionalbytes<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include "6502.h"

// For testing purposes
#include "opcodes.h"

static bool
LoadProgram(ram_t *Ram, const char *Filename)
{
    FILE *File = fopen(Filename, "rb");
    bool Result = false;
    if (File) {
        Result = true;
        fseek(File, 0, SEEK_END);
        u16 ProgramSize = ftell(File);
        fseek(File, 0, SEEK_SET);
        u8 *Program = (u8 *)calloc(ProgramSize, 1);
        fread(Program, 1, ProgramSize, File);
        fclose(File);
        free(Program);

        LoadProgram(Ram, Program, ProgramSize);
    }
    return Result;
}

static void
MemoryDump(ram_t *Ram, u16 StartAddress, u16 Length, u16 ColumnWidth, u16 MarkAddress = 0)
{
    for (u16 Address = StartAddress;
        Address < StartAddress + Length;
        )
    {
        printf("%4x  ", Address);
        for (u16 Offset = 0; Offset < ColumnWidth; ++Offset) {
            bool MarkThisOne = (MarkAddress > 0 && MarkAddress == Address);
            if (MarkThisOne) {
                printf("[");
            }
            printf("%-2x", Ram->Data[Address++]);
            if (MarkThisOne) {
                printf("]");
            } else {
                printf("  ");
            }
        }
        printf("\n");
    }
}

static void
Monitor(cpu_t *Cpu, ram_t *Ram)
{
    const char *StatusFlags = "\nNOIBDIZC      A  X  Y  PC SP    Memory snapshot (%04x - %04x)\n%s      %-2x %-2x %-2x %-2x %-2x    ";
    const char *Menu = "[s]ingle-step [r]estart [g]oto [+/-] PC [m]emory s[t]ack [q]uit >";
    bool Running = true;
    u16 MemoryDumpStart = 0;
    u8 MemoryDumpCount = 20;
    while (Running) {
        char Input[128] = {0};
        printf(StatusFlags, MemoryDumpStart, MemoryDumpStart + MemoryDumpCount, GetStatusRegisters(Cpu->SR), Cpu->A, Cpu->X, Cpu->Y, Cpu->PC, Cpu->SP);
        // Print memory footprint
        for (u16 MemoryAddress = MemoryDumpStart;
             MemoryAddress < MemoryDumpStart + MemoryDumpCount;
             ++MemoryAddress)
        {
            printf("%2x ", Ram->Data[MemoryAddress]);
        }
        printf("\n");
        opcode_e OpCode = (opcode_e)Ram->Data[Cpu->PC];
        instruction_t Instruction = DecodeOpCode(OpCode);
        char *OpCodeName = "(not impl)";
        if (Instruction.Func) {
            OpCodeName = Instruction.OpCodeName;
        }
        //printf("%2X: %9s (%2x) ", Cpu->PC, OpCodeName, OpCode);
        printf("%s(%02x)", OpCodeName, OpCode);
        for (u8 i = 0; i < Instruction.Bytes; ++i) {
            printf(" %2x", Ram->Data[Cpu->PC + i + 1]);
        }
        printf("       ");

        printf(Menu);
        scanf("%127s", Input);

        if (Input) {
            for (char *CurrentInput = Input; *CurrentInput; ++CurrentInput) {
                switch (*CurrentInput) {
                    case 'r':
                        memset(Cpu, 0, sizeof(cpu_t));
                        break;

                    case 'q':
                        Running = false;
                        break;

                    case 's':
                        SingleStepProgram(Cpu, Ram);
                        break;

                    case 't':
                        MemoryDump(Ram, STACK_ADDR(0), 0xFF, 0xF, STACK_ADDR(Cpu->SP));
                        break;

                    case 'g':
                        {
                            printf("Enter new PC: ");
                            scanf("%d", &Cpu->PC);
                            break;
                        }

                    case '+':
                        Cpu->PC++;
                        break;

                    case '-':
                        Cpu->PC--;
                        break;

                    case 'm':
                        MemoryDump(Ram, MemoryDumpStart, 128, 16, MemoryDumpStart);
                        break;

                }
            }
        }
    }
}

int
main(int argc, char *argv[])
{
    cpu_t Cpu = {0};
    ram_t Ram = {0};

    //*
    u8 Program[] = {
        ASL_zpg, 0, PHP
    };
    Ram.Data[0] = 0xAA;
    u8 ProgramCount = sizeof(Program) / sizeof(Program[0]);
    LoadProgram(&Ram, Program, ProgramCount, 0x10);
    //*/
    //LoadProgram(&Ram, "rom/atari2600/Vid_olym.bin");
    // SingleStepProgram(&Cpu, &Ram);
    Monitor(&Cpu, &Ram);

    printf("Program ran for %i cycles.\n", Cpu.CycleCount);

    return 0;
}
<|endoftext|>