<commit_before>#include "bots/constant/bot.h"

#include <cstring>
#include <limits>

#include "game/physics_params.h"
#include "gflags/gflags.h"

using game::Position;
using game::CarTracker;
using game::Race;
using game::Command;
using game::Switch;
using game::PhysicsParams;

DEFINE_double(constant_throttle, 0.5, "Throttle to use in constant bot");
DECLARE_bool(always_switch);

namespace bots {
namespace constant {

Bot::Bot() {
  srand(time(0));
}

Bot::~Bot() {
}

game::Command Bot::ComputeMove(const Position& position, int game_tick) {
  if (FLAGS_always_switch) {
    int r = rand() % 100;
    if (r == 0) return Command(game::Switch::kSwitchLeft);
    if (r == 1) return Command(game::Switch::kSwitchRight);
  }
  return Command(FLAGS_constant_throttle);
}

game::Command Bot::GetMove(
    const std::map<std::string, Position>& positions, int game_tick)  {
  const auto& my_position = positions.find(color_)->second;
  car_tracker_->Record(my_position);

  Command command = ComputeMove(my_position, game_tick);

  car_tracker_->RecordCommand(command);
  return Command(command);
}

void Bot::GameStarted() {
  car_tracker_->Reset();
}

void Bot::YourCar(const std::string& color) {
  color_ = color;
}

void Bot::NewRace(const Race& race) {
  race_ = race;
  car_tracker_.reset(new CarTracker(&race_, PhysicsParams::Load()));
}

void Bot::CarCrashed(const std::string& color)  {
  crash_ = true;
  car_tracker_->RecordCarCrash();
}

void Bot::OnTurbo(const game::Turbo& turbo) {
  turbo_ = true;
  car_tracker_->RecordTurboAvailable(turbo);
}

}  // namespace bots
}  // namespace constant
<commit_msg>Add constant seed to slowbots<commit_after>#include "bots/constant/bot.h"

#include <cstring>
#include <limits>

#include "game/physics_params.h"
#include "gflags/gflags.h"

using game::Position;
using game::CarTracker;
using game::Race;
using game::Command;
using game::Switch;
using game::PhysicsParams;

DEFINE_double(constant_throttle, 0.5, "Throttle to use in constant bot");
DECLARE_bool(always_switch);

namespace bots {
namespace constant {

Bot::Bot() {
  srand(7353521);
}

Bot::~Bot() {
}

game::Command Bot::ComputeMove(const Position& position, int game_tick) {
  if (FLAGS_always_switch) {
    int r = rand() % 100;
    if (r == 0) return Command(game::Switch::kSwitchLeft);
    if (r == 1) return Command(game::Switch::kSwitchRight);
  }
  return Command(FLAGS_constant_throttle);
}

game::Command Bot::GetMove(
    const std::map<std::string, Position>& positions, int game_tick)  {
  const auto& my_position = positions.find(color_)->second;
  car_tracker_->Record(my_position);

  Command command = ComputeMove(my_position, game_tick);

  car_tracker_->RecordCommand(command);
  return Command(command);
}

void Bot::GameStarted() {
  car_tracker_->Reset();
}

void Bot::YourCar(const std::string& color) {
  color_ = color;
}

void Bot::NewRace(const Race& race) {
  race_ = race;
  car_tracker_.reset(new CarTracker(&race_, PhysicsParams::Load()));
}

void Bot::CarCrashed(const std::string& color)  {
  crash_ = true;
  car_tracker_->RecordCarCrash();
}

void Bot::OnTurbo(const game::Turbo& turbo) {
  turbo_ = true;
  car_tracker_->RecordTurboAvailable(turbo);
}

}  // namespace bots
}  // namespace constant
<|endoftext|>


<commit_before>// Parse test application
// Based upon: parsetest.cpp from xmlpp

// needed includes
#include <fstream>
#include <iostream>
#include <ctime>
#include <cppdom/cppdom.h>

// namespace includes
using namespace cppdom;
using namespace std;

// dumps the node
void dump_node( xmlnode &node, int level = 0 )
{
   xmlstring name = node.getName();
   xmlnodetype type = node.getType();
   xmlstring c_data;

   for(int i=0;i<level;i++) cout << " ";

   char c = ' ';
   switch(type)
   {
   case xml_nt_node:
      c = '+';
      break;
   case xml_nt_leaf:
      c = '-';
      break;
   case xml_nt_document:
      c = '\\';
      break;
   case xml_nt_cdata:
      c = '#';
      c_data = node.get_cdata();
      break;
   }

   if(type == xml_nt_cdata)
      cout << c << name.c_str() << "[" << c_data << "]" << endl;
   else
      cout << c << name.c_str() << endl;

   xmlattributes attr = node.get_attrmap();

   // guru: added output of attributes
   for (xmlattributes::iterator j = attr.begin(); j!=attr.end(); j++)
   {
      for (int i=0; i<level; i++)
         cout << " ";
      cout << "   ";
      cout << j->first << ": " << j->second << endl;
   }

   xmlnodelist& nlist = node.getChildren();

   xmlnodelist::const_iterator iter, stop;
   iter = nlist.begin();
   stop = nlist.end();

   while (iter != stop)
   {
      xmlnodeptr node = *iter;

      dump_node ( *node, level+1 );

      ++iter;
   }
};

void process_xml( std::string filename )
{
   cout << "processing [" << filename << "] ..." << endl;

   xmlcontextptr context( new xmlcontext );
   xmldocument node( context );
   ifstream istr( filename.c_str() );

   // Verify that file opened
   if(!istr)
   {
      std::cerr << "Bad file: " << filename << std::endl;
      return;
   }

   try
   {
      clock_t tstart = ::clock();

      node.load( istr, context );

      clock_t tstop = ::clock();
      cout << " needed " <<
         (tstop-tstart)/static_cast<float>(CLOCKS_PER_SEC)
         << " seconds." << endl;

      dump_node( node );

      ofstream ostr( "parsetest.xml" );
      node.save( ostr );
      ostr.close();

   }
   catch (xmlerror e)
   {
      xmllocation where( context->get_location() );
      xmlstring errmsg;
      e.get_strerror(errmsg);

      // print out where the error occured
      cout << filename << ":" << where.get_line() << " ";
      cout << "at position " << where.get_pos();
      cout << ": error: " << errmsg.c_str();
      cout << endl;

      // print out line where the error occured
      ifstream errfile( filename.c_str() );
      if(!errfile)
      {
         std::cerr << "Can't open file [" << filename << "] to output error" << std::endl;
      }

      int linenr = where.get_line();
      char linebuffer[1024];
      for(int i=0; i<linenr && !errfile.eof(); i++)
         errfile.getline(linebuffer,1024);

      int pos = where.get_pos();
      if (pos>=80)
         pos %= 80;

      std::string err_line( linebuffer + (where.get_pos()-pos) );
      if (err_line.length()>=79)
         err_line.erase(79);
      cout << err_line << std::flush;
      cout << err_line.c_str() << std::endl;
      cout << linebuffer << std::endl;
      for(int j=2;j<pos;j++)
         std::cout << " ";
      cout << '^' << endl;
   }
}

int main(int argc, char* argv[])
{
   for(int i=1;i<argc;i++)
   {
      process_xml( std::string(argv[i]) );
   }

   return 0;
}
<commit_msg>updated to recent cppdom API changes<commit_after>// Parse test application
// Based upon: parsetest.cpp from xmlpp

// needed includes
#include <fstream>
#include <iostream>
#include <ctime>
#include <cppdom/cppdom.h>

// namespace includes
using namespace cppdom;
using namespace std;

// dumps the node
void dump_node( XMLNode &node, int level = 0 )
{
   XMLString name = node.getName();
   XMLNodeType type = node.getType();
   XMLString c_data;

   for(int i=0;i<level;i++) cout << " ";

   char c = ' ';
   switch(type)
   {
   case xml_nt_node:
      c = '+';
      break;
   case xml_nt_leaf:
      c = '-';
      break;
   case xml_nt_document:
      c = '\\';
      break;
   case xml_nt_cdata:
      c = '#';
      c_data = node.getCdata();
      break;
   }

   if(type == xml_nt_cdata)
      cout << c << name.c_str() << "[" << c_data << "]" << endl;
   else
      cout << c << name.c_str() << endl;

   XMLAttributes attr = node.getAttrmap();

   // guru: added output of attributes
   for (XMLAttributes::iterator j = attr.begin(); j!=attr.end(); j++)
   {
      for (int i=0; i<level; i++)
         cout << " ";
      cout << "   ";
      cout << j->first << ": " << j->second << endl;
   }

   XMLNodeList& nlist = node.getChildren();

   XMLNodeList::const_iterator iter, stop;
   iter = nlist.begin();
   stop = nlist.end();

   while (iter != stop)
   {
      XMLNodePtr node = *iter;

      dump_node ( *node, level+1 );

      ++iter;
   }
};

void process_xml( std::string filename )
{
   cout << "processing [" << filename << "] ..." << endl;

   XMLContextPtr context( new XMLContext );
   XMLDocument node( context );
   ifstream istr( filename.c_str() );

   // Verify that file opened
   if(!istr)
   {
      std::cerr << "Bad file: " << filename << std::endl;
      return;
   }

   try
   {
      clock_t tstart = ::clock();

      node.load( istr, context );

      clock_t tstop = ::clock();
      cout << " needed " <<
         (tstop-tstart)/static_cast<float>(CLOCKS_PER_SEC)
         << " seconds." << endl;

      dump_node( node );

      ofstream ostr( "parsetest.xml" );
      node.save( ostr );
      ostr.close();

   }
   catch (xmlerror e)
   {
      XMLLocation where( context->get_location() );
      XMLString errmsg;
      e.getStrError(errmsg);

      // print out where the error occured
      cout << filename << ":" << where.getLine() << " ";
      cout << "at position " << where.getPos();
      cout << ": error: " << errmsg.c_str();
      cout << endl;

      // print out line where the error occured
      ifstream errfile( filename.c_str() );
      if(!errfile)
      {
         std::cerr << "Can't open file [" << filename << "] to output error" << std::endl;
      }

      int linenr = where.get_line();
      char linebuffer[1024];
      for(int i=0; i<linenr && !errfile.eof(); i++)
         errfile.getline(linebuffer,1024);

      int pos = where.get_pos();
      if (pos>=80)
         pos %= 80;

      std::string err_line( linebuffer + (where.get_pos()-pos) );
      if (err_line.length()>=79)
         err_line.erase(79);
      cout << err_line << std::flush;
      cout << err_line.c_str() << std::endl;
      cout << linebuffer << std::endl;
      for(int j=2;j<pos;j++)
         std::cout << " ";
      cout << '^' << endl;
   }
}

int main(int argc, char* argv[])
{
   for(int i=1;i<argc;i++)
   {
      process_xml( std::string(argv[i]) );
   }

   return 0;
}
<|endoftext|>


<commit_before>#include "ImageImporter2D.hpp"
#include <QImage>
#include "DataTypes.hpp"
#include "DeviceManager.hpp"
#include "Exception.hpp"
using namespace fast;

void ImageImporter2D::execute() {
    // TODO check that all parameters needed are present

    // Load image from disk using Qt
    QImage image;
    std::cout << "Trying to load image..." << std::endl;
    if(!image.load(mFilename.c_str())) {
        throw FileNotFoundException(mFilename);
    }
    std::cout << "Loaded image with size " << image.width() << " "  << image.height() << std::endl;

    // Convert image to make sure color tables are not used
    QImage convertedImage = image.convertToFormat(QImage::Format_RGB32);

    // Get pixel data
    const unsigned char * pixelData = convertedImage.constBits();
    // The pixel data array should contain one uchar value for the
    // R, G, B, A components for each pixel

    // TODO: do some conversion to requested output format, also color vs. no color
    float * convertedPixelData = new float[image.width()*image.height()];
    for(int i = 0; i < image.width()*image.height(); i++) {
        // Converted to grayscale
        convertedPixelData[i] = (1.0f/255.0f)*(float)(pixelData[i*4]+pixelData[i*4+1]+pixelData[i*4+2])/3.0f;
    }

    // Transfer to texture(if OpenCL) or copy raw pixel data (if host)
    if(mDevice->isHost()) {
        mOutput2.lock()->createImage(image.width(), image.height(), convertedPixelData);
    } else {
        OpenCLDevice::pointer device = boost::static_pointer_cast<OpenCLDevice>(mDevice);
        cl::Image2D* clImage = new cl::Image2D(
                device->getContext(),
                CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR,
                cl::ImageFormat(CL_R, CL_FLOAT),
                image.width(), image.height(),
                0,
                convertedPixelData
        );
        delete[] convertedPixelData;
        mOutput2.lock()->createImage(clImage, device);
    }
}

ImageImporter2D::ImageImporter2D() {
    mOutput = Image2D::New();
    mOutput2 = mOutput;
    mDevice = DeviceManager::getInstance().getDefaultComputationDevice();
}

Image2D::pointer ImageImporter2D::getOutput() {
    if(mOutput.isValid()) {
        mOutput->addParent(mPtr.lock());

        Image2D::pointer newSmartPtr;
        newSmartPtr.swap(mOutput);

        return newSmartPtr;
    } else {
        return mOutput2.lock();
    }
}

void ImageImporter2D::setFilename(std::string filename) {
    mFilename = filename;
    mIsModified = true;
}

void ImageImporter2D::setDevice(ExecutionDevice::pointer device) {
    mDevice = device;
    mIsModified = true;
}
<commit_msg>Added a filename check to the ImageImporter2D<commit_after>#include "ImageImporter2D.hpp"
#include <QImage>
#include "DataTypes.hpp"
#include "DeviceManager.hpp"
#include "Exception.hpp"
using namespace fast;

void ImageImporter2D::execute() {
    if(mFilename == "")
        throw Exception("No filename was supplied to the ImageImporter2D");

    // Load image from disk using Qt
    QImage image;
    std::cout << "Trying to load image..." << std::endl;
    if(!image.load(mFilename.c_str())) {
        throw FileNotFoundException(mFilename);
    }
    std::cout << "Loaded image with size " << image.width() << " "  << image.height() << std::endl;

    // Convert image to make sure color tables are not used
    QImage convertedImage = image.convertToFormat(QImage::Format_RGB32);

    // Get pixel data
    const unsigned char * pixelData = convertedImage.constBits();
    // The pixel data array should contain one uchar value for the
    // R, G, B, A components for each pixel

    // TODO: do some conversion to requested output format, also color vs. no color
    float * convertedPixelData = new float[image.width()*image.height()];
    for(int i = 0; i < image.width()*image.height(); i++) {
        // Converted to grayscale
        convertedPixelData[i] = (1.0f/255.0f)*(float)(pixelData[i*4]+pixelData[i*4+1]+pixelData[i*4+2])/3.0f;
    }

    // Transfer to texture(if OpenCL) or copy raw pixel data (if host)
    if(mDevice->isHost()) {
        mOutput2.lock()->createImage(image.width(), image.height(), convertedPixelData);
    } else {
        OpenCLDevice::pointer device = boost::static_pointer_cast<OpenCLDevice>(mDevice);
        cl::Image2D* clImage = new cl::Image2D(
                device->getContext(),
                CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR,
                cl::ImageFormat(CL_R, CL_FLOAT),
                image.width(), image.height(),
                0,
                convertedPixelData
        );
        delete[] convertedPixelData;
        mOutput2.lock()->createImage(clImage, device);
    }
}

ImageImporter2D::ImageImporter2D() {
    mOutput = Image2D::New();
    mOutput2 = mOutput;
    mDevice = DeviceManager::getInstance().getDefaultComputationDevice();
}

Image2D::pointer ImageImporter2D::getOutput() {
    if(mOutput.isValid()) {
        mOutput->addParent(mPtr.lock());

        Image2D::pointer newSmartPtr;
        newSmartPtr.swap(mOutput);

        return newSmartPtr;
    } else {
        return mOutput2.lock();
    }
}

void ImageImporter2D::setFilename(std::string filename) {
    mFilename = filename;
    mIsModified = true;
}

void ImageImporter2D::setDevice(ExecutionDevice::pointer device) {
    mDevice = device;
    mIsModified = true;
}
<|endoftext|>


<commit_before>/*
  Copyright (c) 2014, J.D. Koftinoff Software, Ltd.
  All rights reserved.

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

   1. Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

   2. 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.

   3. Neither the name of J.D. Koftinoff Software, Ltd. 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.
*/
#pragma once

#include "JDKSAvdeccWorld.hpp"
#include "JDKSAvdeccNetIO.hpp"
#include "JDKSAvdeccFrame.hpp"
#include "JDKSAvdeccHandler.hpp"
#include "JDKSAvdeccControlValueHolder.hpp"
#include "JDKSAvdeccHelpers.hpp"

namespace JDKSAvdecc {

template <size_t MaxDescriptors>
class ControlReceiver : public Handler {
public:
    /// Construct the ControlReceiver object
    ControlReceiver(NetIO &net,
               jdksavdecc_eui64 const &entity_id,
               uint16_t descriptor_index_offset=0 )
    : m_net( net )
    , m_entity_id( entity_id )
    , m_descriptor_index_offset( descriptor_index_offset )
    , m_num_descriptors(0)
    , m_last_sequence_id(0xffff) {}

    /// Register the ControlValueHolder to relate to the next descriptor_index in line
    void AddDescriptor(ControlValueHolder *v ) {
        m_values[ m_num_descriptors++ ] = v;
    }

    virtual bool ReceivedGetControlCommand(
            jdksavdecc_aecpdu_aem const &aem,
            FrameBase &pdu ) {
        bool r=false;
        // yes, get the descriptor index
        uint16_t descriptor_index = jdksavdecc_aem_command_set_control_get_descriptor_index(pdu.GetBuf(),pdu.GetPos());
        // is it a descriptor index that we care about?
        if( (descriptor_index>=m_descriptor_index_offset)
           && (descriptor_index < (m_descriptor_index_offset+m_num_descriptors)) ) {
            // yes, it is in range, extract the data value

            // TODO Add GetValue method in ControlValueHolder.
//            m_values[descriptor_index-m_descriptor_index_offset]->SetValue(
//                                                                           &buf[pos+JDKSAVDECC_AEM_COMMAND_SET_CONTROL_COMMAND_OFFSET_VALUES] );
            // TODO: Set control_data_length appropriately.

            r=true;
        }
        return r;
    }

    virtual bool ReceivedSetControlCommand(
            jdksavdecc_aecpdu_aem const &aem,
            FrameBase &pdu ) {
        bool r=false;
        // yes, get the descriptor index
        uint16_t descriptor_index = jdksavdecc_aem_command_set_control_get_descriptor_index(pdu.GetBuf(),pdu.GetPos());
        // is it a descriptor index that we care about?
        if( (descriptor_index>=m_descriptor_index_offset)
           && (descriptor_index < (m_descriptor_index_offset+m_num_descriptors)) ) {
            // yes, it is in range, extract the data value

            m_values[descriptor_index-m_descriptor_index_offset]->SetValue(
                                                                           pdu.GetBuf() + pdu.GetPos() +JDKSAVDECC_AEM_COMMAND_SET_CONTROL_COMMAND_OFFSET_VALUES
                                                                           );

            r=true;
        }
        return r;
    }

    virtual bool ReceivedReadDescriptorCommand(
            jdksavdecc_aecpdu_aem const &aem,
            FrameBase &pdu ) {
        bool r=false;
        return r;

    }

    /// Handle incoming PDU
    virtual bool ReceivedPDU( jdksavdecc_timestamp_in_milliseconds time_in_millis, uint8_t *buf, uint16_t len ) {
        bool r=false;
        // we already know the message is AVTP ethertype and is either directly
        // targetting my MAC address or is a multicast message

        FrameBase pdu(time_in_millis,buf,len);

        // Try see if it is an AEM message
        jdksavdecc_aecpdu_aem aem;
        if( ParseAEM(&aem,pdu)) {
            // Yes, Is it a command for me?
            if( IsAEMForTarget(aem,m_entity_id)) {
                // Yes. Is the sequence_id ok?
                if( aem.aecpdu_header.sequence_id != m_last_sequence_id )
                {
                    // Yes, it is different.
                    m_last_sequence_id = aem.aecpdu_header.sequence_id;
                    if( aem.command_type == JDKSAVDECC_AEM_COMMAND_GET_CONTROL ) {
                        // Handle GET_CONTROL commands
                        r=ReceivedGetControlCommand( aem, pdu );
                    } else if( aem.command_type == JDKSAVDECC_AEM_COMMAND_SET_CONTROL ) {
                        // Handle SET_CONTROL commands
                        r=ReceivedSetControlCommand( aem, pdu );
                    } else if( aem.command_type == JDKSAVDECC_AEM_COMMAND_READ_DESCRIPTOR ) {
                        // Handle READ_DESCRIPTOR commands
                        r=ReceivedReadDescriptorCommand( aem, pdu );
                    }
                }
            }
        }
        if( r ) {
            // TODO: change message type to AEM_RESPONSE and send it back to sender
        }
        return r;
    }

    /// Get the enitity ID that we are handling
    jdksavdecc_eui64 const &GetEntityID() const { return m_entity_id; }

protected:
    NetIO &m_net;
    jdksavdecc_eui64 const &m_entity_id;
    uint16_t m_descriptor_index_offset;
    uint16_t m_num_descriptors;
    ControlValueHolder *m_values[MaxDescriptors];
    uint16_t m_last_sequence_id;
};

}
<commit_msg>Clean up warnings<commit_after>/*
  Copyright (c) 2014, J.D. Koftinoff Software, Ltd.
  All rights reserved.

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

   1. Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

   2. 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.

   3. Neither the name of J.D. Koftinoff Software, Ltd. 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.
*/
#pragma once

#include "JDKSAvdeccWorld.hpp"
#include "JDKSAvdeccNetIO.hpp"
#include "JDKSAvdeccFrame.hpp"
#include "JDKSAvdeccHandler.hpp"
#include "JDKSAvdeccControlValueHolder.hpp"
#include "JDKSAvdeccHelpers.hpp"

namespace JDKSAvdecc {

template <size_t MaxDescriptors>
class ControlReceiver : public Handler {
public:
    /// Construct the ControlReceiver object
    ControlReceiver(NetIO &net,
               jdksavdecc_eui64 const &entity_id,
               uint16_t descriptor_index_offset=0 )
    : m_net( net )
    , m_entity_id( entity_id )
    , m_descriptor_index_offset( descriptor_index_offset )
    , m_num_descriptors(0)
    , m_last_sequence_id(0xffff) {}

    /// Register the ControlValueHolder to relate to the next descriptor_index in line
    void AddDescriptor(ControlValueHolder *v ) {
        m_values[ m_num_descriptors++ ] = v;
    }

    virtual bool ReceivedGetControlCommand(
            jdksavdecc_aecpdu_aem const &aem,
            FrameBase &pdu ) {
        bool r=false;
        // yes, get the descriptor index
        uint16_t descriptor_index = jdksavdecc_aem_command_set_control_get_descriptor_index(pdu.GetBuf(),pdu.GetPos());
        (void)aem;
        // is it a descriptor index that we care about?
        if( (descriptor_index>=m_descriptor_index_offset)
           && (descriptor_index < (m_descriptor_index_offset+m_num_descriptors)) ) {
            // yes, it is in range, extract the data value

            // TODO Add GetValue method in ControlValueHolder.
//            m_values[descriptor_index-m_descriptor_index_offset]->SetValue(
//                                                                           &buf[pos+JDKSAVDECC_AEM_COMMAND_SET_CONTROL_COMMAND_OFFSET_VALUES] );
            // TODO: Set control_data_length appropriately.

            r=true;
        }
        return r;
    }

    virtual bool ReceivedSetControlCommand(
            jdksavdecc_aecpdu_aem const &aem,
            FrameBase &pdu ) {
        bool r=false;
        // yes, get the descriptor index
        uint16_t descriptor_index = jdksavdecc_aem_command_set_control_get_descriptor_index(pdu.GetBuf(),pdu.GetPos());
        (void)aem;
        // is it a descriptor index that we care about?
        if( (descriptor_index>=m_descriptor_index_offset)
           && (descriptor_index < (m_descriptor_index_offset+m_num_descriptors)) ) {
            // yes, it is in range, extract the data value

            m_values[descriptor_index-m_descriptor_index_offset]->SetValue(
                                                                           pdu.GetBuf() + pdu.GetPos() +JDKSAVDECC_AEM_COMMAND_SET_CONTROL_COMMAND_OFFSET_VALUES
                                                                           );

            r=true;
        }
        return r;
    }

    virtual bool ReceivedReadDescriptorCommand(
            jdksavdecc_aecpdu_aem const &aem,
            FrameBase &pdu ) {
        bool r=false;
        (void)aem;
        (void)pdu;
        return r;
    }

    /// Handle incoming PDU
    virtual bool ReceivedPDU( jdksavdecc_timestamp_in_milliseconds time_in_millis, uint8_t *buf, uint16_t len ) {
        bool r=false;
        // we already know the message is AVTP ethertype and is either directly
        // targetting my MAC address or is a multicast message

        FrameBase pdu(time_in_millis,buf,len);

        // Try see if it is an AEM message
        jdksavdecc_aecpdu_aem aem;
        if( ParseAEM(&aem,pdu)) {
            // Yes, Is it a command for me?
            if( IsAEMForTarget(aem,m_entity_id)) {
                // Yes. Is the sequence_id ok?
                if( aem.aecpdu_header.sequence_id != m_last_sequence_id )
                {
                    // Yes, it is different.
                    m_last_sequence_id = aem.aecpdu_header.sequence_id;
                    if( aem.command_type == JDKSAVDECC_AEM_COMMAND_GET_CONTROL ) {
                        // Handle GET_CONTROL commands
                        r=ReceivedGetControlCommand( aem, pdu );
                    } else if( aem.command_type == JDKSAVDECC_AEM_COMMAND_SET_CONTROL ) {
                        // Handle SET_CONTROL commands
                        r=ReceivedSetControlCommand( aem, pdu );
                    } else if( aem.command_type == JDKSAVDECC_AEM_COMMAND_READ_DESCRIPTOR ) {
                        // Handle READ_DESCRIPTOR commands
                        r=ReceivedReadDescriptorCommand( aem, pdu );
                    }
                }
            }
        }
        if( r ) {
            // TODO: change message type to AEM_RESPONSE and send it back to sender
        }
        return r;
    }

    /// Get the enitity ID that we are handling
    jdksavdecc_eui64 const &GetEntityID() const { return m_entity_id; }

protected:
    NetIO &m_net;
    jdksavdecc_eui64 const &m_entity_id;
    uint16_t m_descriptor_index_offset;
    uint16_t m_num_descriptors;
    ControlValueHolder *m_values[MaxDescriptors];
    uint16_t m_last_sequence_id;
};

}
<|endoftext|>


<commit_before>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE JPetTaskIOTest
#include <boost/test/unit_test.hpp>
#include "../JPetCmdParser/JPetCmdParser.h"
#include "../JPetTaskIO/JPetTaskIO.h"

//#include "TaskA.h"
//#include "TaskB.h"
//#include "TaskC1.h"
//#include "TaskC2.h"
//#include "TaskC3.h"
//#include "TaskD.h"
//#include "TaskE.h"

// methods
//virtual void init(const JPetTaskInterface::Options& opts);
//virtual void exec();
//virtual void terminate();
//virtual ~JPetTaskIO();
//virtual void addSubTask(JPetTaskInterface* subtask);
//void manageProgressBar(long long done, long long end);
//float setProgressBar(int currentEventNumber, int numberOfEvents);

///protected:
//virtual void createInputObjects(const char* inputFilename);
//virtual void createOutputObjects(const char* outputFilename);
//void setUserLimits(const JPetOptions& opts, long long& firstEvent, long long& lastEvent) const;

//using Options = std::map<std::string, std::string>;

BOOST_AUTO_TEST_SUITE(FirstSuite)

char* convertStringToCharP(const std::string& s)
{
  char* pc = new char[s.size() + 1];
  std::strcpy(pc, s.c_str());
  return pc;
}

std::vector<char*> createArgs(const std::string& commandLine)
{
  std::istringstream iss(commandLine);
  std::vector<std::string> args {std::istream_iterator<std::string>{iss},
                                 std::istream_iterator<std::string>{}
                                };
  std::vector<char*> args_char;
  std::transform(args.begin(), args.end(), std::back_inserter(args_char), convertStringToCharP);
  return args_char;
}

BOOST_AUTO_TEST_CASE(progressBarTest)
{
    JPetTaskIO taskIO;
    BOOST_REQUIRE_EQUAL(taskIO.setProgressBar(5, 100), 5);
    taskIO.manageProgressBar(5, 100);
}
//ToDo: remake this tests without calling private methods
/*
BOOST_AUTO_TEST_CASE( setUserLimits)
{
  auto commandLine = "./main.x -t root -f unitTestData/JPetTaskIOTest/cosm_barrel.hld.root -i 26 -r 1000 1001";
  auto args_char = createArgs(commandLine);
  auto argc = args_char.size();
  auto argv = args_char.data();

  JPetCmdParser parser;
  auto options = parser.parseAndGenerateOptions(argc, const_cast<const char**>(argv));
  auto first = 0ll;
  auto last = 0ll;
  auto opt = options.front().getOptions();
  JPetOptions optObject(opt);
  JPetTaskIO task;
  task.setUserLimits(optObject,10000, first,last);
  BOOST_REQUIRE_EQUAL(first, 1000);
  BOOST_REQUIRE_EQUAL(last, 1001);
}

BOOST_AUTO_TEST_CASE( setUserLimits2 )
{
  auto commandLine = "./main.x -t root -f unitTestData/JPetTaskIOTest/cosm_barrel.hld.root -i 26 -r 1000 1001";
  auto args_char = createArgs(commandLine);
  auto argc = args_char.size();
  auto argv = args_char.data();

  JPetCmdParser parser;
  auto options = parser.parseAndGenerateOptions(argc, const_cast<const char**>(argv));
  auto first = 0ll;
  auto last = 0ll;
  auto opt = options.front().getOptions();
  JPetOptions optObject(opt);
  JPetTaskIO task;
  task.setUserLimits(optObject,1, first,last);
  BOOST_REQUIRE_EQUAL(first, 0);
  BOOST_REQUIRE_EQUAL(last, 0);
}

BOOST_AUTO_TEST_CASE( my_testA )
{
  //Options options = {
    //{"inputFile", "data_files/cosm_barrel.hld.root"},
    //{"inputFileType", "hld"},
    //{"outputFile", "data_files/cosm_barrel.tslot.raw.out.root"},
    //{"outputFileType", "tslot.raw"},
    //{"firstEvent", "1"},
    //{"lastEvent", "10"},
    //{"progressBar", "false"}
  //};
  //JPetParamManager myParamManager("../DBConfig/configDB.cfg.koza");
  ////JPetParamManager myParamManager;
  //myParamManager.getParametersFromDatabase(26);
  //JPetTaskIO task;
  //task.setParamManager(&myParamManager);
  //auto myTask = new TaskA();
  //myTask->setParamManager(&myParamManager);
  //task.addSubTask(myTask);
  //task.init(options);
  //task.exec();
  //task.terminate();

  //BOOST_REQUIRE(1 == 0);
//}

//BOOST_AUTO_TEST_CASE( my_testB )
//{
  //Options options = {
    //{"inputFile", "data_files/cosm_barrel.tslot.raw.root"},
    //{"inputFileType", "tslot.raw"},
    //{"outputFile", "data_files/cosm_barrel.tslot.cal.out.root"},
    //{"outputFileType", "tslot.cal"},
    //{"firstEvent", "1"},
    //{"lastEvent", "10"},
    //{"progressBar", "false"}
  //};
  ////JPetParamManager myParamManager("../DBConfig/configDB.cfg.koza");
  //JPetParamManager myParamManager;
  ////myParamManager.getParametersFromDatabase(26);
  //JPetTaskIO task;
  //task.setParamManager(&myParamManager);
  //auto myTask = new TaskB();
  //myTask->setParamManager(&myParamManager);
  //task.addSubTask(myTask);
  //task.init(options);
  //task.exec();
  //task.terminate();

  //BOOST_REQUIRE(1 == 0);
//}

//BOOST_AUTO_TEST_CASE( my_testC1 )
//{
  //Options options = {
    //{"inputFile", "data_files/cosm_barrel.tslot.cal.root"},
    //{"inputFileType", "tslot.cal"},
    //{"outputFile", "data_files/cosm_barrel.raw.sig.out.root"},
    //{"outputFileType", "raw.sig"},
    //{"firstEvent", "1"},
    //{"lastEvent", "10"},
    //{"progressBar", "false"}
  //};
  ////JPetParamManager myParamManager("../DBConfig/configDB.cfg.koza");
  //JPetParamManager myParamManager;
  ////myParamManager.getParametersFromDatabase(26);
  //JPetTaskIO task;
  //task.setParamManager(&myParamManager);
  //auto myTask = new TaskC1();
  //myTask->setParamManager(&myParamManager);
  //task.addSubTask(myTask);
  //task.init(options);
  //task.exec();
  //task.terminate();

  //BOOST_REQUIRE(1 == 0);
//}

//BOOST_AUTO_TEST_CASE( my_testC2 )
//{
  //Options options = {
    //{"inputFile", "data_files/cosm_barrel.raw.sig.root"},
    //{"inputFileType", "raw.sig"},
    //{"outputFile", "data_files/cosm_barrel.reco.sig.out.root"},
    //{"outputFileType", "reco.sig"},
    //{"firstEvent", "1"},
    //{"lastEvent", "10"},
    //{"progressBar", "false"}
  //};
  ////JPetParamManager myParamManager("../DBConfig/configDB.cfg.koza");
  //JPetParamManager myParamManager;
  ////myParamManager.getParametersFromDatabase(26);
  //auto myTask = new TaskC2();
  //JPetTaskIO task;
  //task.addSubTask(myTask);
  //task.setParamManager(&myParamManager);
  //task.init(options);
  //task.exec();
  //task.terminate();

  //BOOST_REQUIRE(1 == 0);
//}

//BOOST_AUTO_TEST_CASE( my_testC3 )
//{
  //Options options = {
    //{"inputFile", "data_files/cosm_barrel.reco.sig.root"},
    //{"inputFileType", "reco.sig"},
    //{"outputFile", "data_files/cosm_barrel.phys.sig.out.root"},
    //{"outputFileType", "phys.sig"},
    //{"firstEvent", "1"},
    //{"lastEvent", "10"},
    //{"progressBar", "false"}
  //};
  ////JPetParamManager myParamManager("../DBConfig/configDB.cfg.koza");
  //JPetParamManager myParamManager;
  ////myParamManager.getParametersFromDatabase(26);
  //auto myTask = new TaskC3();
  //JPetTaskIO task;
  //task.addSubTask(myTask);
  //task.setParamManager(&myParamManager);
  //task.init(options);
  //task.exec();
  //task.terminate();

  //BOOST_REQUIRE(1 == 0);
//}

//BOOST_AUTO_TEST_CASE( my_test1 )
//{
  //Options options = {
    //{"inputFile", "data_files/cosm_barrel.phys.sig.root"},
    //{"inputFileType", "phys.sig"},
    //{"outputFile", "data_files/cosm_barrel.phys.hit.out.root"},
    //{"outputFileType", "phys.hit"},
    //{"firstEvent", "1"},
    //{"lastEvent", "10"},
    //{"progressBar", "false"}
  //};
  ////JPetParamManager myParamManager("../DBConfig/configDB.cfg.koza");
  //JPetParamManager myParamManager;
  ////myParamManager.getParametersFromDatabase(26);
  //auto myTask = new TaskD();
  //JPetTaskIO task;
  //task.addSubTask(myTask);
  //task.setParamManager(&myParamManager);
  //task.init(options);
  //task.exec();
  //task.terminate();

  //BOOST_REQUIRE(1 == 0);
//}
//BOOST_AUTO_TEST_CASE( my_test2 )
//{
  //Options options = {
    //{"inputFile", "data_files/cosm_barrel.phys.hit.root"},
    //{"inputFileType", "phys.hit"},
    //{"outputFile", "data_files/cosm_barrel.phys.eve.out.root"},
    //{"outputFileType", "phys.eve"},
    //{"firstEvent", "1"},
    //{"lastEvent", "10"},
    //{"progressBar", "false"}
  //};
  ////JPetParamManager myParamManager("../DBConfig/configDB.cfg.koza");
  ////myParamManager.getParametersFromDatabase(26);
  //JPetParamManager myParamManager;
  //auto myTask = new TaskE();
  //JPetTaskIO task;
  //task.addSubTask(myTask);
  //task.setParamManager(&myParamManager);
  //task.init(options);
  //task.exec();
  //task.terminate();

  //BOOST_REQUIRE(1 == 0);
}
*/
BOOST_AUTO_TEST_SUITE_END()
<commit_msg>JPetTaskIO/JPetTaskIOTest.cpp unnecessary comments removed<commit_after>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE JPetTaskIOTest
#include <boost/test/unit_test.hpp>
#include "../JPetCmdParser/JPetCmdParser.h"
#include "../JPetTaskIO/JPetTaskIO.h"

BOOST_AUTO_TEST_SUITE(FirstSuite)

char* convertStringToCharP(const std::string& s)
{
  char* pc = new char[s.size() + 1];
  std::strcpy(pc, s.c_str());
  return pc;
}

std::vector<char*> createArgs(const std::string& commandLine)
{
  std::istringstream iss(commandLine);
  std::vector<std::string> args {std::istream_iterator<std::string>{iss},
                                 std::istream_iterator<std::string>{}
                                };
  std::vector<char*> args_char;
  std::transform(args.begin(), args.end(), std::back_inserter(args_char), convertStringToCharP);
  return args_char;
}

BOOST_AUTO_TEST_CASE(progressBarTest)
{
    JPetTaskIO taskIO;
    BOOST_REQUIRE_EQUAL(taskIO.setProgressBar(5, 100), 5);
    taskIO.manageProgressBar(5, 100);
}
//ToDo: remake this tests without calling private methods
/*
BOOST_AUTO_TEST_CASE( setUserLimits)
{
  auto commandLine = "./main.x -t root -f unitTestData/JPetTaskIOTest/cosm_barrel.hld.root -i 26 -r 1000 1001";
  auto args_char = createArgs(commandLine);
  auto argc = args_char.size();
  auto argv = args_char.data();

  JPetCmdParser parser;
  auto options = parser.parseAndGenerateOptions(argc, const_cast<const char**>(argv));
  auto first = 0ll;
  auto last = 0ll;
  auto opt = options.front().getOptions();
  JPetOptions optObject(opt);
  JPetTaskIO task;
  task.setUserLimits(optObject,10000, first,last);
  BOOST_REQUIRE_EQUAL(first, 1000);
  BOOST_REQUIRE_EQUAL(last, 1001);
}

BOOST_AUTO_TEST_CASE( setUserLimits2 )
{
  auto commandLine = "./main.x -t root -f unitTestData/JPetTaskIOTest/cosm_barrel.hld.root -i 26 -r 1000 1001";
  auto args_char = createArgs(commandLine);
  auto argc = args_char.size();
  auto argv = args_char.data();

  JPetCmdParser parser;
  auto options = parser.parseAndGenerateOptions(argc, const_cast<const char**>(argv));
  auto first = 0ll;
  auto last = 0ll;
  auto opt = options.front().getOptions();
  JPetOptions optObject(opt);
  JPetTaskIO task;
  task.setUserLimits(optObject,1, first,last);
  BOOST_REQUIRE_EQUAL(first, 0);
  BOOST_REQUIRE_EQUAL(last, 0);
}

BOOST_AUTO_TEST_CASE( my_testA )
{
  //Options options = {
    //{"inputFile", "data_files/cosm_barrel.hld.root"},
    //{"inputFileType", "hld"},
    //{"outputFile", "data_files/cosm_barrel.tslot.raw.out.root"},
    //{"outputFileType", "tslot.raw"},
    //{"firstEvent", "1"},
    //{"lastEvent", "10"},
    //{"progressBar", "false"}
  //};
  //JPetParamManager myParamManager("../DBConfig/configDB.cfg.koza");
  ////JPetParamManager myParamManager;
  //myParamManager.getParametersFromDatabase(26);
  //JPetTaskIO task;
  //task.setParamManager(&myParamManager);
  //auto myTask = new TaskA();
  //myTask->setParamManager(&myParamManager);
  //task.addSubTask(myTask);
  //task.init(options);
  //task.exec();
  //task.terminate();

  //BOOST_REQUIRE(1 == 0);
//}

//BOOST_AUTO_TEST_CASE( my_testB )
//{
  //Options options = {
    //{"inputFile", "data_files/cosm_barrel.tslot.raw.root"},
    //{"inputFileType", "tslot.raw"},
    //{"outputFile", "data_files/cosm_barrel.tslot.cal.out.root"},
    //{"outputFileType", "tslot.cal"},
    //{"firstEvent", "1"},
    //{"lastEvent", "10"},
    //{"progressBar", "false"}
  //};
  ////JPetParamManager myParamManager("../DBConfig/configDB.cfg.koza");
  //JPetParamManager myParamManager;
  ////myParamManager.getParametersFromDatabase(26);
  //JPetTaskIO task;
  //task.setParamManager(&myParamManager);
  //auto myTask = new TaskB();
  //myTask->setParamManager(&myParamManager);
  //task.addSubTask(myTask);
  //task.init(options);
  //task.exec();
  //task.terminate();

  //BOOST_REQUIRE(1 == 0);
//}

//BOOST_AUTO_TEST_CASE( my_testC1 )
//{
  //Options options = {
    //{"inputFile", "data_files/cosm_barrel.tslot.cal.root"},
    //{"inputFileType", "tslot.cal"},
    //{"outputFile", "data_files/cosm_barrel.raw.sig.out.root"},
    //{"outputFileType", "raw.sig"},
    //{"firstEvent", "1"},
    //{"lastEvent", "10"},
    //{"progressBar", "false"}
  //};
  ////JPetParamManager myParamManager("../DBConfig/configDB.cfg.koza");
  //JPetParamManager myParamManager;
  ////myParamManager.getParametersFromDatabase(26);
  //JPetTaskIO task;
  //task.setParamManager(&myParamManager);
  //auto myTask = new TaskC1();
  //myTask->setParamManager(&myParamManager);
  //task.addSubTask(myTask);
  //task.init(options);
  //task.exec();
  //task.terminate();

  //BOOST_REQUIRE(1 == 0);
//}

//BOOST_AUTO_TEST_CASE( my_testC2 )
//{
  //Options options = {
    //{"inputFile", "data_files/cosm_barrel.raw.sig.root"},
    //{"inputFileType", "raw.sig"},
    //{"outputFile", "data_files/cosm_barrel.reco.sig.out.root"},
    //{"outputFileType", "reco.sig"},
    //{"firstEvent", "1"},
    //{"lastEvent", "10"},
    //{"progressBar", "false"}
  //};
  ////JPetParamManager myParamManager("../DBConfig/configDB.cfg.koza");
  //JPetParamManager myParamManager;
  ////myParamManager.getParametersFromDatabase(26);
  //auto myTask = new TaskC2();
  //JPetTaskIO task;
  //task.addSubTask(myTask);
  //task.setParamManager(&myParamManager);
  //task.init(options);
  //task.exec();
  //task.terminate();

  //BOOST_REQUIRE(1 == 0);
//}

//BOOST_AUTO_TEST_CASE( my_testC3 )
//{
  //Options options = {
    //{"inputFile", "data_files/cosm_barrel.reco.sig.root"},
    //{"inputFileType", "reco.sig"},
    //{"outputFile", "data_files/cosm_barrel.phys.sig.out.root"},
    //{"outputFileType", "phys.sig"},
    //{"firstEvent", "1"},
    //{"lastEvent", "10"},
    //{"progressBar", "false"}
  //};
  ////JPetParamManager myParamManager("../DBConfig/configDB.cfg.koza");
  //JPetParamManager myParamManager;
  ////myParamManager.getParametersFromDatabase(26);
  //auto myTask = new TaskC3();
  //JPetTaskIO task;
  //task.addSubTask(myTask);
  //task.setParamManager(&myParamManager);
  //task.init(options);
  //task.exec();
  //task.terminate();

  //BOOST_REQUIRE(1 == 0);
//}

//BOOST_AUTO_TEST_CASE( my_test1 )
//{
  //Options options = {
    //{"inputFile", "data_files/cosm_barrel.phys.sig.root"},
    //{"inputFileType", "phys.sig"},
    //{"outputFile", "data_files/cosm_barrel.phys.hit.out.root"},
    //{"outputFileType", "phys.hit"},
    //{"firstEvent", "1"},
    //{"lastEvent", "10"},
    //{"progressBar", "false"}
  //};
  ////JPetParamManager myParamManager("../DBConfig/configDB.cfg.koza");
  //JPetParamManager myParamManager;
  ////myParamManager.getParametersFromDatabase(26);
  //auto myTask = new TaskD();
  //JPetTaskIO task;
  //task.addSubTask(myTask);
  //task.setParamManager(&myParamManager);
  //task.init(options);
  //task.exec();
  //task.terminate();

  //BOOST_REQUIRE(1 == 0);
//}
//BOOST_AUTO_TEST_CASE( my_test2 )
//{
  //Options options = {
    //{"inputFile", "data_files/cosm_barrel.phys.hit.root"},
    //{"inputFileType", "phys.hit"},
    //{"outputFile", "data_files/cosm_barrel.phys.eve.out.root"},
    //{"outputFileType", "phys.eve"},
    //{"firstEvent", "1"},
    //{"lastEvent", "10"},
    //{"progressBar", "false"}
  //};
  ////JPetParamManager myParamManager("../DBConfig/configDB.cfg.koza");
  ////myParamManager.getParametersFromDatabase(26);
  //JPetParamManager myParamManager;
  //auto myTask = new TaskE();
  //JPetTaskIO task;
  //task.addSubTask(myTask);
  //task.setParamManager(&myParamManager);
  //task.init(options);
  //task.exec();
  //task.terminate();

  //BOOST_REQUIRE(1 == 0);
}
*/
BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>#include "../test_math.hpp"
#include "nnlib/math/math.hpp"
#include "nnlib/math/random.hpp"
using namespace nnlib;
using namespace nnlib::math;
using T = NN_REAL_T;

NNTestClassImpl(Math)
{
    NNTestMethod(min)
    {
        NNTestParams(const Tensor &)
        {
            Tensor<T> x({ 8, -6, 7, 5, 3, 0, 9, 3.14159 });
            NNTestAlmostEquals(min(x), -6, 1e-12);
        }
    }

    NNTestMethod(max)
    {
        NNTestParams(const Tensor &)
        {
            Tensor<T> x({ 8, -6, 7, 5, 3, 0, 9, 3.14159 });
            NNTestAlmostEquals(max(x), 9, 1e-12);
        }
    }

    NNTestMethod(sum)
    {
        NNTestParams(const Tensor &)
        {
            Tensor<T> x({ 8, -6, 7, 5, 3, 0, 9, 3.14159 });
            NNTestAlmostEquals(sum(x), 29.14159, 1e-12);
        }
    }

    NNTestMethod(mean)
    {
        NNTestParams(const Tensor &)
        {
            Tensor<T> x({ 8, -6, 7, 5, 3, 0, 9, 3.14159 });
            NNTestAlmostEquals(mean(x), 3.64269875, 1e-12);
        }
    }

    NNTestMethod(variance)
    {
        NNTestParams(const Tensor &)
        {
            Tensor<T> x({ 8, -6, 7, 5, 3, 0, 9, 3.14159 });
            NNTestAlmostEquals(variance(x), 20.964444282761, 1e-12);
        }

        NNTestParams(const Tensor &, bool)
        {
            Tensor<T> x({ 8, -6, 7, 5, 3, 0, 9, 3.14159 });
            NNTestAlmostEquals(variance(x, true), 23.959364894584, 1e-12);
        }
    }

    NNTestMethod(normalize)
    {
        NNTestParams(Tensor &, T, T)
        {
            Tensor<T> x({ -2, 0, 8, 3 });
            normalize(x, -1, 4);
            NNTestAlmostEquals(x(0), -1, 1e-12);
            NNTestAlmostEquals(x(1), 0, 1e-12);
            NNTestAlmostEquals(x(2), 4, 1e-12);
            NNTestAlmostEquals(x(3), 1.5, 1e-12);
        }

        NNTestParams(Tensor &&, T, T)
        {
            Tensor<T> x = normalize(Tensor<T>({ -2, 0, 8, 3 }), -1, 4);
            NNTestAlmostEquals(x(0), -1, 1e-12);
            NNTestAlmostEquals(x(1), 0, 1e-12);
            NNTestAlmostEquals(x(2), 4, 1e-12);
            NNTestAlmostEquals(x(3), 1.5, 1e-12);
        }
    }

    NNTestMethod(clip)
    {
        NNTestParams(Tensor &, T, T)
        {
            Tensor<T> x({ -2, 0, 8, 3 });
            clip(x, -1, 4);
            NNTestAlmostEquals(x(0), -1, 1e-12);
            NNTestAlmostEquals(x(1), 0, 1e-12);
            NNTestAlmostEquals(x(2), 4, 1e-12);
            NNTestAlmostEquals(x(3), 3, 1e-12);
        }

        NNTestParams(Tensor &&, T, T)
        {
            Tensor<T> x = clip(Tensor<T>({ -2, 0, 8, 3 }), -1, 4);
            NNTestAlmostEquals(x(0), -1, 1e-12);
            NNTestAlmostEquals(x(1), 0, 1e-12);
            NNTestAlmostEquals(x(2), 4, 1e-12);
            NNTestAlmostEquals(x(3), 3, 1e-12);
        }
    }

    NNTestMethod(square)
    {
        NNTestParams(Tensor &)
        {
            Tensor<T> x({ -2, 0, 1, 6 });
            square(x);
            NNTestAlmostEquals(x(0), 4, 1e-12);
            NNTestAlmostEquals(x(1), 0, 1e-12);
            NNTestAlmostEquals(x(2), 1, 1e-12);
            NNTestAlmostEquals(x(3), 36, 1e-12);
        }

        NNTestParams(Tensor &&)
        {
            Tensor<T> x = square(Tensor<T>({ -2, 0, 1, 6 }));
            NNTestAlmostEquals(x(0), 4, 1e-12);
            NNTestAlmostEquals(x(1), 0, 1e-12);
            NNTestAlmostEquals(x(2), 1, 1e-12);
            NNTestAlmostEquals(x(3), 36, 1e-12);
        }
    }

    NNTestMethod(rand)
    {
        NNTestParams(Tensor &, T, T)
        {
            RandomEngine::sharedEngine().seed(0);
            Tensor<T> x(1000);
            rand(x, -1, 1);
            NNTestAlmostEquals(mean(x), 0, 0.5);
            NNTestAlmostEquals(variance(x), 0.3333, 0.5);
        }

        NNTestParams(Tensor &&, T, T)
        {
            RandomEngine::sharedEngine().seed(0);
            Tensor<T> x = rand(Tensor<T>(1000), -1, 1);
            NNTestAlmostEquals(mean(x), 0, 0.5);
            NNTestAlmostEquals(variance(x), 0.3333, 0.5);
        }
    }

    NNTestMethod(randn)
    {
        NNTestParams(Tensor &, T, T)
        {
            RandomEngine::sharedEngine().seed(0);
            Tensor<T> x(1000);
            randn(x, -1, 3.14);
            NNTestAlmostEquals(mean(x), -1, 0.5);
            NNTestAlmostEquals(variance(x), 9.8596, 0.5);
        }

        NNTestParams(Tensor &&, T, T)
        {
            RandomEngine::sharedEngine().seed(0);
            Tensor<T> x = randn(Tensor<T>(1000), -1, 3.14);
            NNTestAlmostEquals(mean(x), -1, 0.5);
            NNTestAlmostEquals(variance(x), 9.8596, 0.5);
        }

        NNTestParams(Tensor &, T, T, T)
        {
            RandomEngine::sharedEngine().seed(0);
            Tensor<T> x(1000);
            randn(x, -1, 3.14, 3);
            NNTestAlmostEquals(mean(x), -1, 0.5);
            NNTestGreaterThanOrEquals(min(x), -4);
            NNTestLessThanOrEquals(max(x), 2);
        }

        NNTestParams(Tensor &&, T, T, T)
        {
            RandomEngine::sharedEngine().seed(0);
            Tensor<T> x = randn(Tensor<T>(1000), -1, 3.14, 3);
            NNTestAlmostEquals(mean(x), -1, 0.5);
            NNTestGreaterThanOrEquals(min(x), -4);
            NNTestLessThanOrEquals(max(x), 2);
        }
    }

    NNTestMethod(bernoulli)
    {
        NNTestParams(Tensor &, T)
        {
            RandomEngine::sharedEngine().seed(0);
            Tensor<T> x(1000);
            bernoulli(x, 0.25);
            size_t n = 0;
            forEach([&](T x)
            {
                if(x > 0.5)
                    ++n;
            }, x);
            NNTestAlmostEquals(n, 0.25 * x.size(), 50);
        }

        NNTestParams(Tensor &&, T)
        {
            RandomEngine::sharedEngine().seed(0);
            Tensor<T> x = bernoulli(Tensor<T>(1000), 0.25);
            size_t n = 0;
            forEach([&](T x)
            {
                if(x > 0.5)
                    ++n;
            }, x);
            NNTestAlmostEquals(n, 0.25 * x.size(), 50);
        }
    }

    NNTestMethod(sum)
    {
        NNTestParams(const Tensor &, Tensor &, size_t)
        {
            Tensor<T> x = Tensor<T>({ 1, 2, 3, 4, 5, 6 }).resize(2, 3);
            Tensor<T> y = Tensor<T>({ 5, 7, 9 });
            Tensor<T> z(3);
            sum(x, z, 0);
            forEach([&](T y, T z)
            {
                NNTestAlmostEquals(y, z, 1e-12);
            }, y, z);
            y = Tensor<T>({ 6, 15 });
            z.resize(2);
            sum(x, z, 1);
            forEach([&](T y, T z)
            {
                NNTestAlmostEquals(y, z, 1e-12);
            }, y, z);
        }

        NNTestParams(const Tensor &, Tensor &&, size_t)
        {
            Tensor<T> x = Tensor<T>({ 1, 2, 3, 4, 5, 6 }).resize(2, 3);
            Tensor<T> y = Tensor<T>({ 5, 7, 9 });
            Tensor<T> z = sum(x, Tensor<T>(3), 0);
            forEach([&](T y, T z)
            {
                NNTestAlmostEquals(y, z, 1e-12);
            }, y, z);
        }
    }

    NNTestMethod(pointwiseProduct)
    {
        NNTestParams(const Tensor &, const Tensor &, Tensor &)
        {
            Tensor<T> x = Tensor<T>({ 1, 2, 3 });
            Tensor<T> y = Tensor<T>({ 4, 5, 6 });
            Tensor<T> z(3);
            pointwiseProduct(x, y, z);
            NNTestAlmostEquals(z(0), 4, 1e-12);
            NNTestAlmostEquals(z(1), 10, 1e-12);
            NNTestAlmostEquals(z(2), 18, 1e-12);
        }

        NNTestParams(const Tensor &, const Tensor &, Tensor &&)
        {
            Tensor<T> x = Tensor<T>({ 1, 2, 3 });
            Tensor<T> y = Tensor<T>({ 4, 5, 6 });
            Tensor<T> z = pointwiseProduct(x, y, Tensor<T>(3));
            NNTestAlmostEquals(z(0), 4, 1e-12);
            NNTestAlmostEquals(z(1), 10, 1e-12);
            NNTestAlmostEquals(z(2), 18, 1e-12);
        }
    }
}
<commit_msg>Added missing math unit test.<commit_after>#include "../test_math.hpp"
#include "nnlib/math/math.hpp"
#include "nnlib/math/random.hpp"
using namespace nnlib;
using namespace nnlib::math;
using T = NN_REAL_T;

NNTestClassImpl(Math)
{
    NNTestMethod(min)
    {
        NNTestParams(const Tensor &)
        {
            Tensor<T> x({ 8, -6, 7, 5, 3, 0, 9, 3.14159 });
            NNTestAlmostEquals(min(x), -6, 1e-12);
        }
    }

    NNTestMethod(max)
    {
        NNTestParams(const Tensor &)
        {
            Tensor<T> x({ 8, -6, 7, 5, 3, 0, 9, 3.14159 });
            NNTestAlmostEquals(max(x), 9, 1e-12);
        }
    }

    NNTestMethod(sum)
    {
        NNTestParams(const Tensor &)
        {
            Tensor<T> x({ 8, -6, 7, 5, 3, 0, 9, 3.14159 });
            NNTestAlmostEquals(sum(x), 29.14159, 1e-12);
        }
    }

    NNTestMethod(mean)
    {
        NNTestParams(const Tensor &)
        {
            Tensor<T> x({ 8, -6, 7, 5, 3, 0, 9, 3.14159 });
            NNTestAlmostEquals(mean(x), 3.64269875, 1e-12);
        }
    }

    NNTestMethod(variance)
    {
        NNTestParams(const Tensor &)
        {
            Tensor<T> x({ 8, -6, 7, 5, 3, 0, 9, 3.14159 });
            NNTestAlmostEquals(variance(x), 20.964444282761, 1e-12);
        }

        NNTestParams(const Tensor &, bool)
        {
            Tensor<T> x({ 8, -6, 7, 5, 3, 0, 9, 3.14159 });
            NNTestAlmostEquals(variance(x, true), 23.959364894584, 1e-12);
        }
    }

    NNTestMethod(normalize)
    {
        NNTestParams(Tensor &, T, T)
        {
            Tensor<T> x({ -2, 0, 8, 3 });
            normalize(x, -1, 4);
            NNTestAlmostEquals(x(0), -1, 1e-12);
            NNTestAlmostEquals(x(1), 0, 1e-12);
            NNTestAlmostEquals(x(2), 4, 1e-12);
            NNTestAlmostEquals(x(3), 1.5, 1e-12);
        }

        NNTestParams(Tensor &&, T, T)
        {
            Tensor<T> x = normalize(Tensor<T>({ -2, 0, 8, 3 }), -1, 4);
            NNTestAlmostEquals(x(0), -1, 1e-12);
            NNTestAlmostEquals(x(1), 0, 1e-12);
            NNTestAlmostEquals(x(2), 4, 1e-12);
            NNTestAlmostEquals(x(3), 1.5, 1e-12);
        }
    }

    NNTestMethod(clip)
    {
        NNTestParams(Tensor &, T, T)
        {
            Tensor<T> x({ -2, 0, 8, 3 });
            clip(x, -1, 4);
            NNTestAlmostEquals(x(0), -1, 1e-12);
            NNTestAlmostEquals(x(1), 0, 1e-12);
            NNTestAlmostEquals(x(2), 4, 1e-12);
            NNTestAlmostEquals(x(3), 3, 1e-12);
        }

        NNTestParams(Tensor &&, T, T)
        {
            Tensor<T> x = clip(Tensor<T>({ -2, 0, 8, 3 }), -1, 4);
            NNTestAlmostEquals(x(0), -1, 1e-12);
            NNTestAlmostEquals(x(1), 0, 1e-12);
            NNTestAlmostEquals(x(2), 4, 1e-12);
            NNTestAlmostEquals(x(3), 3, 1e-12);
        }
    }

    NNTestMethod(square)
    {
        NNTestParams(Tensor &)
        {
            Tensor<T> x({ -2, 0, 1, 6 });
            square(x);
            NNTestAlmostEquals(x(0), 4, 1e-12);
            NNTestAlmostEquals(x(1), 0, 1e-12);
            NNTestAlmostEquals(x(2), 1, 1e-12);
            NNTestAlmostEquals(x(3), 36, 1e-12);
        }

        NNTestParams(Tensor &&)
        {
            Tensor<T> x = square(Tensor<T>({ -2, 0, 1, 6 }));
            NNTestAlmostEquals(x(0), 4, 1e-12);
            NNTestAlmostEquals(x(1), 0, 1e-12);
            NNTestAlmostEquals(x(2), 1, 1e-12);
            NNTestAlmostEquals(x(3), 36, 1e-12);
        }
    }

    NNTestMethod(rand)
    {
        NNTestParams(Tensor &, T, T)
        {
            RandomEngine::sharedEngine().seed(0);
            Tensor<T> x(1000);
            rand(x, -1, 1);
            NNTestAlmostEquals(mean(x), 0, 0.5);
            NNTestAlmostEquals(variance(x), 0.3333, 0.5);
        }

        NNTestParams(Tensor &&, T, T)
        {
            RandomEngine::sharedEngine().seed(0);
            Tensor<T> x = rand(Tensor<T>(1000), -1, 1);
            NNTestAlmostEquals(mean(x), 0, 0.5);
            NNTestAlmostEquals(variance(x), 0.3333, 0.5);
        }
    }

    NNTestMethod(randn)
    {
        NNTestParams(Tensor &, T, T)
        {
            RandomEngine::sharedEngine().seed(0);
            Tensor<T> x(1000);
            randn(x, -1, 3.14);
            NNTestAlmostEquals(mean(x), -1, 0.5);
            NNTestAlmostEquals(variance(x), 9.8596, 0.5);
        }

        NNTestParams(Tensor &&, T, T)
        {
            RandomEngine::sharedEngine().seed(0);
            Tensor<T> x = randn(Tensor<T>(1000), -1, 3.14);
            NNTestAlmostEquals(mean(x), -1, 0.5);
            NNTestAlmostEquals(variance(x), 9.8596, 0.5);
        }

        NNTestParams(Tensor &, T, T, T)
        {
            RandomEngine::sharedEngine().seed(0);
            Tensor<T> x(1000);
            randn(x, -1, 3.14, 3);
            NNTestAlmostEquals(mean(x), -1, 0.5);
            NNTestGreaterThanOrEquals(min(x), -4);
            NNTestLessThanOrEquals(max(x), 2);
        }

        NNTestParams(Tensor &&, T, T, T)
        {
            RandomEngine::sharedEngine().seed(0);
            Tensor<T> x = randn(Tensor<T>(1000), -1, 3.14, 3);
            NNTestAlmostEquals(mean(x), -1, 0.5);
            NNTestGreaterThanOrEquals(min(x), -4);
            NNTestLessThanOrEquals(max(x), 2);
        }
    }

    NNTestMethod(bernoulli)
    {
        NNTestParams(Tensor &, T)
        {
            RandomEngine::sharedEngine().seed(0);
            Tensor<T> x(1000);
            bernoulli(x, 0.25);
            size_t n = 0;
            forEach([&](T x)
            {
                if(x > 0.5)
                    ++n;
            }, x);
            NNTestAlmostEquals(n, 0.25 * x.size(), 50);
        }

        NNTestParams(Tensor &&, T)
        {
            RandomEngine::sharedEngine().seed(0);
            Tensor<T> x = bernoulli(Tensor<T>(1000), 0.25);
            size_t n = 0;
            forEach([&](T x)
            {
                if(x > 0.5)
                    ++n;
            }, x);
            NNTestAlmostEquals(n, 0.25 * x.size(), 50);
        }
    }

    NNTestMethod(sum)
    {
        NNTestParams(const Tensor &, Tensor &, size_t)
        {
            Tensor<T> x = Tensor<T>({ 1, 2, 3, 4, 5, 6 }).resize(2, 3);
            Tensor<T> y = Tensor<T>({ 5, 7, 9 });
            Tensor<T> z(3);
            sum(x, z, 0);
            forEach([&](T y, T z)
            {
                NNTestAlmostEquals(y, z, 1e-12);
            }, y, z);
            y = Tensor<T>({ 6, 15 });
            z.resize(2);
            sum(x, z, 1);
            forEach([&](T y, T z)
            {
                NNTestAlmostEquals(y, z, 1e-12);
            }, y, z);
        }

        NNTestParams(const Tensor &, Tensor &&, size_t)
        {
            Tensor<T> x = Tensor<T>({ 1, 2, 3, 4, 5, 6 }).resize(2, 3);
            Tensor<T> y = Tensor<T>({ 5, 7, 9 });
            Tensor<T> z = sum(x, Tensor<T>(3), 0);
            forEach([&](T y, T z)
            {
                NNTestAlmostEquals(y, z, 1e-12);
            }, y, z);
        }
    }

    NNTestMethod(pointwiseProduct)
    {
        NNTestParams(const Tensor &, Tensor &)
        {
            Tensor<T> x = Tensor<T>({ 1, 2, 3 });
            Tensor<T> y = Tensor<T>({ 4, 5, 6 });
            pointwiseProduct(x, y);
            NNTestAlmostEquals(y(0), 4, 1e-12);
            NNTestAlmostEquals(y(1), 10, 1e-12);
            NNTestAlmostEquals(y(2), 18, 1e-12);
        }

        NNTestParams(const Tensor &, Tensor &&)
        {
            Tensor<T> x = Tensor<T>({ 1, 2, 3 });
            Tensor<T> y = pointwiseProduct(x, Tensor<T>({ 4, 5, 6 }));
            NNTestAlmostEquals(y(0), 4, 1e-12);
            NNTestAlmostEquals(y(1), 10, 1e-12);
            NNTestAlmostEquals(y(2), 18, 1e-12);
        }

        NNTestParams(const Tensor &, const Tensor &, Tensor &)
        {
            Tensor<T> x = Tensor<T>({ 1, 2, 3 });
            Tensor<T> y = Tensor<T>({ 4, 5, 6 });
            Tensor<T> z(3);
            pointwiseProduct(x, y, z);
            NNTestAlmostEquals(z(0), 4, 1e-12);
            NNTestAlmostEquals(z(1), 10, 1e-12);
            NNTestAlmostEquals(z(2), 18, 1e-12);
        }

        NNTestParams(const Tensor &, const Tensor &, Tensor &&)
        {
            Tensor<T> x = Tensor<T>({ 1, 2, 3 });
            Tensor<T> y = Tensor<T>({ 4, 5, 6 });
            Tensor<T> z = pointwiseProduct(x, y, Tensor<T>(3));
            NNTestAlmostEquals(z(0), 4, 1e-12);
            NNTestAlmostEquals(z(1), 10, 1e-12);
            NNTestAlmostEquals(z(2), 18, 1e-12);
        }
    }
}
<|endoftext|>


<commit_before>#include "Halide.h"

using namespace Halide;
using namespace Halide::Internal;

class ValidateInterleavedPipeline: public IRMutator {
protected:
//
// This is roughly the structure that we are trying to validate in this custom pass:
//
// parallel<Renderscript> (result$2.s0.y$2.__block_id_y, 0, result$2.extent.1) {
//   parallel<Renderscript> (result$2.s0.x$2.__block_id_x, 0, result$2.extent.0) {
//     ...
//     parallel<Renderscript> (.__thread_id_x, 0, 1) {
//       for<Renderscript> (result$2.s0.c$2, 0, 4) {
//         image_store("result$2",
//                     result$2.buffer,
//                     (result$2.s0.x$2.__block_id_x + result$2.min.0),
//                     (result$2.s0.y$2.__block_id_y + result$2.min.1),
//                     result$2.s0.c$2,
//                     image_load("input",
//                                input.buffer,
//                                ((result$2.s0.x$2.__block_id_x + result$2.min.0) - input.min.0),
//                                input.extent.0,
//                                ((result$2.s0.y$2.__block_id_y + result$2.min.1) - input.min.1),
//                                input.extent.1,
//                                result$2.s0.c$2,
//                                4))
//       }
//     }
//     ...
//   }
// }
//
    using IRMutator::visit;

    virtual void visit(const Call *call) {
        if (in_pipeline && call->is_intrinsic(Call::image_store)) {
            assert(for_nest_level == 4);

            std::map<std::string, Expr> matches;

            assert(expr_match(
                StringImm::make("result"),
                call->args[0],
                matches));
            assert(expr_match(
                Variable::make(Handle(1), "result.buffer"),
                call->args[1],
                matches));
            assert(expr_match(
                Variable::make(Int(32), "result.s0.x.__block_id_x") + Variable::make(Int(32), "result.min.0"),
                call->args[2],
                matches));
            assert(expr_match(
                Variable::make(Int(32), "result.s0.y.__block_id_y") + Variable::make(Int(32), "result.min.1"),
                call->args[3],
                matches));
            assert(expr_match(
                Variable::make(Int(32), "result.s0.c"),
                call->args[4],
                matches));
            assert(expr_match(
                Call::make(
                    UInt(8),
                    Call::image_load,
                    {
                        StringImm::make("input"),
                        Variable::make(Handle(1), "input.buffer"),
                        (Variable::make(Int(32), "result.s0.x.__block_id_x") +
                         Variable::make(Int(32), "result.min.0")) -
                         Variable::make(Int(32), "input.min.0"),
                        Variable::make(Int(32), "input.extent.0"),
                        (Variable::make(Int(32), "result.s0.y.__block_id_y") +
                         Variable::make(Int(32), "result.min.1")) -
                         Variable::make(Int(32), "input.min.1"),
                        Variable::make(Int(32), "input.extent.1"),
                        Variable::make(Int(32), "result.s0.c"),
                        channels
                    },
                    Call::CallType::PureIntrinsic),
                call->args[5],
                matches));
        }
        IRMutator::visit(call);
    }

    void visit(const For *op) {
        if (in_pipeline) {
            assert(for_nest_level >= 0); // For-loop should show up in Pipeline.
            for_nest_level++;
            if (for_nest_level <= 3) {
                assert(op->for_type == ForType::Parallel);
            }
            assert(op->device_api == DeviceAPI::Renderscript);
        }
        IRMutator::visit(op);
    }

    void visit(const ProducerConsumer *op) {
        assert(!in_pipeline); // There should be only one pipeline in the test.
        for_nest_level = 0;
        in_pipeline = true;

        assert(op->produce.defined());
        assert(!op->update.defined());
        assert(op->consume.defined());

        IRMutator::visit(op);
        stmt = Stmt();
    }

    int for_nest_level = -1;
    bool in_pipeline = false;
    int channels;

public:
    ValidateInterleavedPipeline(int _channels) : channels(_channels) {}
};

class ValidateInterleavedVectorizedPipeline: public ValidateInterleavedPipeline {
    using IRMutator::visit;
    using ValidateInterleavedPipeline::visit;

    virtual void visit(const Call *call) {
        if (in_pipeline && call->is_intrinsic(Call::image_store)) {
            assert(for_nest_level == 3); // Should be three nested for-loops before we get to the first call.

            std::map<std::string, Expr> matches;

            assert(expr_match(
                Broadcast::make(StringImm::make("result"), channels),
                call->args[0],
                matches));
            assert(expr_match(
                Broadcast::make(Variable::make(Handle(1), "result.buffer"), channels),
                call->args[1],
                matches));
            assert(expr_match(
                Broadcast::make(Variable::make(Int(32), "result.s0.x.__block_id_x") + Variable::make(Int(32), "result.min.0"), channels),
                call->args[2],
                matches));
            assert(expr_match(
                Broadcast::make(Variable::make(Int(32), "result.s0.y.__block_id_y") + Variable::make(Int(32), "result.min.1"), channels),
                call->args[3],
                matches));
            assert(expr_match(
                Ramp::make(0, 1, channels), call->args[4], matches));
            assert(expr_match(
                Call::make(
                    UInt(8, channels),
                    Call::image_load,
                    {
                        Broadcast::make(StringImm::make("input"), channels),
                        Broadcast::make(Variable::make(Handle(1), "input.buffer"), channels),
                        Broadcast::make(
                            Add::make(
                                Variable::make(Int(32), "result.s0.x.__block_id_x"),
                                Variable::make(Int(32), "result.min.0")) -
                            Variable::make(Int(32), "input.min.0"),
                            channels),
                        Broadcast::make(Variable::make(Int(32), "input.extent.0"), channels),
                        Broadcast::make(
                            Add::make(
                                Variable::make(Int(32), "result.s0.y.__block_id_y"),
                                Variable::make(Int(32), "result.min.1")) -
                            Variable::make(Int(32), "input.min.1"),
                            channels),
                        Broadcast::make(Variable::make(Int(32), "input.extent.1"), channels),
                        Ramp::make(0, 1, channels),
                        Broadcast::make(channels, channels)
                    },
                    Call::CallType::PureIntrinsic),
                call->args[5],
                matches));
        }
        IRMutator::visit(call);
    }
public:
    ValidateInterleavedVectorizedPipeline(int _channels) : ValidateInterleavedPipeline(_channels) {}
};

Image<uint8_t> make_interleaved_image(uint8_t *host, int W, int H, int channels) {
    buffer_t buf = { 0 };
    buf.host = host;
    buf.extent[0] = W;
    buf.stride[0] = channels;
    buf.extent[1] = H;
    buf.stride[1] = buf.stride[0] * buf.extent[0];
    buf.extent[2] = channels;
    buf.stride[2] = 1;
    buf.elem_size = 1;
    return Image<uint8_t>(&buf);
}

void copy_interleaved(bool vectorized = false, int channels = 4) {
    ImageParam input8(UInt(8), 3, "input");
    input8.set_stride(0, channels)
        .set_stride(1, Halide::Expr())
        .set_stride(2, 1)
        .set_bounds(2, 0, channels);  // expecting interleaved image
    uint8_t *in_buf = new uint8_t[128 * 128 * channels];
    Image<uint8_t> in = make_interleaved_image(in_buf, 128, 128, channels);
    input8.set(in);

    Var x, y, c;
    Func result("result");
    result(x, y, c) = input8(x, y, c);
    result.output_buffer()
        .set_stride(0, channels)
        .set_stride(1, Halide::Expr())
        .set_stride(2, 1)
        .set_bounds(2, 0, channels);  // expecting interleaved image

    result.bound(c, 0, channels);
    result.shader(x, y, c, DeviceAPI::Renderscript);
    if (vectorized) result.vectorize(c);

    result.add_custom_lowering_pass(
        vectorized?
            new ValidateInterleavedVectorizedPipeline(channels):
            new ValidateInterleavedPipeline(channels));

    result.compile_jit();

    delete[] in_buf;
}

int main(int argc, char **argv) {
    copy_interleaved(true, 4);
    copy_interleaved(false, 4);
    copy_interleaved(true, 3);
    copy_interleaved(false, 3);

    std::cout << "Done!" << std::endl;
    return 0;
}
<commit_msg>Fix renderscript test<commit_after>#include "Halide.h"

using namespace Halide;
using namespace Halide::Internal;

class ValidateInterleavedPipeline: public IRMutator {
protected:
//
// This is roughly the structure that we are trying to validate in this custom pass:
//
// parallel<Renderscript> (result$2.s0.y$2.__block_id_y, 0, result$2.extent.1) {
//   parallel<Renderscript> (result$2.s0.x$2.__block_id_x, 0, result$2.extent.0) {
//     ...
//     parallel<Renderscript> (.__thread_id_x, 0, 1) {
//       for<Renderscript> (result$2.s0.c$2, 0, 4) {
//         image_store("result$2",
//                     result$2.buffer,
//                     (result$2.s0.x$2.__block_id_x + result$2.min.0),
//                     (result$2.s0.y$2.__block_id_y + result$2.min.1),
//                     result$2.s0.c$2,
//                     image_load("input",
//                                input.buffer,
//                                ((result$2.s0.x$2.__block_id_x + result$2.min.0) - input.min.0),
//                                input.extent.0,
//                                ((result$2.s0.y$2.__block_id_y + result$2.min.1) - input.min.1),
//                                input.extent.1,
//                                result$2.s0.c$2,
//                                4))
//       }
//     }
//     ...
//   }
// }
//
    using IRMutator::visit;

    virtual void visit(const Call *call) {
        if (in_pipeline && call->is_intrinsic(Call::image_store)) {
            assert(for_nest_level == 4);

            std::map<std::string, Expr> matches;

            assert(expr_match(
                StringImm::make("result"),
                call->args[0],
                matches));
            assert(expr_match(
                Variable::make(Handle(1), "result.buffer"),
                call->args[1],
                matches));
            assert(expr_match(
                Variable::make(Int(32), "result.s0.x.__block_id_x") + Variable::make(Int(32), "result.min.0"),
                call->args[2],
                matches));
            assert(expr_match(
                Variable::make(Int(32), "result.s0.y.__block_id_y") + Variable::make(Int(32), "result.min.1"),
                call->args[3],
                matches));
            assert(expr_match(
                Variable::make(Int(32), "result.s0.c"),
                call->args[4],
                matches));
            assert(expr_match(
                Call::make(
                    UInt(8),
                    Call::image_load,
                    {
                        StringImm::make("input"),
                        Variable::make(Handle(1), "input.buffer"),
                        (Variable::make(Int(32), "result.s0.x.__block_id_x") +
                         Variable::make(Int(32), "result.min.0")) -
                         Variable::make(Int(32), "input.min.0"),
                        Variable::make(Int(32), "input.extent.0"),
                        (Variable::make(Int(32), "result.s0.y.__block_id_y") +
                         Variable::make(Int(32), "result.min.1")) -
                         Variable::make(Int(32), "input.min.1"),
                        Variable::make(Int(32), "input.extent.1"),
                        Variable::make(Int(32), "result.s0.c"),
                        channels
                    },
                    Call::CallType::PureIntrinsic),
                call->args[5],
                matches));
        }
        IRMutator::visit(call);
    }

    void visit(const For *op) {
        if (in_pipeline) {
            assert(for_nest_level >= 0); // For-loop should show up in Pipeline.
            for_nest_level++;
            if (for_nest_level <= 3) {
                assert(op->for_type == ForType::Parallel);
                assert(op->device_api == DeviceAPI::Renderscript);
            }
        }
        IRMutator::visit(op);
    }

    void visit(const ProducerConsumer *op) {
        assert(!in_pipeline); // There should be only one pipeline in the test.
        for_nest_level = 0;
        in_pipeline = true;

        assert(op->produce.defined());
        assert(!op->update.defined());
        assert(op->consume.defined());

        IRMutator::visit(op);
        stmt = Stmt();
    }

    int for_nest_level = -1;
    bool in_pipeline = false;
    int channels;

public:
    ValidateInterleavedPipeline(int _channels) : channels(_channels) {}
};

class ValidateInterleavedVectorizedPipeline: public ValidateInterleavedPipeline {
    using IRMutator::visit;
    using ValidateInterleavedPipeline::visit;

    virtual void visit(const Call *call) {
        if (in_pipeline && call->is_intrinsic(Call::image_store)) {
            assert(for_nest_level == 3); // Should be three nested for-loops before we get to the first call.

            std::map<std::string, Expr> matches;

            assert(expr_match(
                Broadcast::make(StringImm::make("result"), channels),
                call->args[0],
                matches));
            assert(expr_match(
                Broadcast::make(Variable::make(Handle(1), "result.buffer"), channels),
                call->args[1],
                matches));
            assert(expr_match(
                Broadcast::make(Variable::make(Int(32), "result.s0.x.__block_id_x") + Variable::make(Int(32), "result.min.0"), channels),
                call->args[2],
                matches));
            assert(expr_match(
                Broadcast::make(Variable::make(Int(32), "result.s0.y.__block_id_y") + Variable::make(Int(32), "result.min.1"), channels),
                call->args[3],
                matches));
            assert(expr_match(
                Ramp::make(0, 1, channels), call->args[4], matches));
            assert(expr_match(
                Call::make(
                    UInt(8, channels),
                    Call::image_load,
                    {
                        Broadcast::make(StringImm::make("input"), channels),
                        Broadcast::make(Variable::make(Handle(1), "input.buffer"), channels),
                        Broadcast::make(
                            Add::make(
                                Variable::make(Int(32), "result.s0.x.__block_id_x"),
                                Variable::make(Int(32), "result.min.0")) -
                            Variable::make(Int(32), "input.min.0"),
                            channels),
                        Broadcast::make(Variable::make(Int(32), "input.extent.0"), channels),
                        Broadcast::make(
                            Add::make(
                                Variable::make(Int(32), "result.s0.y.__block_id_y"),
                                Variable::make(Int(32), "result.min.1")) -
                            Variable::make(Int(32), "input.min.1"),
                            channels),
                        Broadcast::make(Variable::make(Int(32), "input.extent.1"), channels),
                        Ramp::make(0, 1, channels),
                        Broadcast::make(channels, channels)
                    },
                    Call::CallType::PureIntrinsic),
                call->args[5],
                matches));
        }
        IRMutator::visit(call);
    }
public:
    ValidateInterleavedVectorizedPipeline(int _channels) : ValidateInterleavedPipeline(_channels) {}
};

Image<uint8_t> make_interleaved_image(uint8_t *host, int W, int H, int channels) {
    buffer_t buf = { 0 };
    buf.host = host;
    buf.extent[0] = W;
    buf.stride[0] = channels;
    buf.extent[1] = H;
    buf.stride[1] = buf.stride[0] * buf.extent[0];
    buf.extent[2] = channels;
    buf.stride[2] = 1;
    buf.elem_size = 1;
    return Image<uint8_t>(&buf);
}

void copy_interleaved(bool vectorized = false, int channels = 4) {
    ImageParam input8(UInt(8), 3, "input");
    input8.set_stride(0, channels)
        .set_stride(1, Halide::Expr())
        .set_stride(2, 1)
        .set_bounds(2, 0, channels);  // expecting interleaved image
    uint8_t *in_buf = new uint8_t[128 * 128 * channels];
    Image<uint8_t> in = make_interleaved_image(in_buf, 128, 128, channels);
    input8.set(in);

    Var x, y, c;
    Func result("result");
    result(x, y, c) = input8(x, y, c);
    result.output_buffer()
        .set_stride(0, channels)
        .set_stride(1, Halide::Expr())
        .set_stride(2, 1)
        .set_bounds(2, 0, channels);  // expecting interleaved image

    result.bound(c, 0, channels);
    result.shader(x, y, c, DeviceAPI::Renderscript);
    if (vectorized) result.vectorize(c);

    result.add_custom_lowering_pass(
        vectorized?
            new ValidateInterleavedVectorizedPipeline(channels):
            new ValidateInterleavedPipeline(channels));

    result.compile_jit();

    delete[] in_buf;
}

int main(int argc, char **argv) {
    copy_interleaved(true, 4);
    copy_interleaved(false, 4);
    copy_interleaved(true, 3);
    copy_interleaved(false, 3);

    std::cout << "Done!" << std::endl;
    return 0;
}
<|endoftext|>