<commit_before>/* EmulationDevice.cc - accessing accelerator memory as memory mapped region.

   Copyright (c) 2021 Pekka Jääskeläinen / Tampere University

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

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

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
   IN THE SOFTWARE.
*/

#include "EmulationDevice.h"

#include "EmulationRegion.h"
#include "accel-shared.h"

#include <unistd.h>
#include <iostream>

EmulationDevice::EmulationDevice() {

    // The principle of the emulator is that instead of mmapping a real
    // accelerator, we just allocate a regular array, which corresponds
    // to the mmap. The accel_emulate function is working in another thread
    // and will fill that array and respond to the driver asynchronously.
    // The driver doesn't really need to know about emulating except
    // in the initial mapping of the accelerator
    E.emulating_address = calloc(1, EMULATING_MAX_SIZE);
    assert(E.emulating_address != NULL && "Emulating calloc failed\n");

    // Create emulator thread
    E.emulate_exit_called = 0;
    E.emulate_init_done = 0;
    pthread_create(&emulate_thread, NULL, emulate_accel, &E);
    while (!E.emulate_init_done)
      ; // Wait for the thread to initialize
    POCL_MSG_PRINT_INFO("accel: started emulating\n");

    ControlMemory =
        new EmulationRegion((size_t)E.emulating_address, ACCEL_DEFAULT_CTRL_SIZE);

    discoverDeviceParameters();

    InstructionMemory = new EmulationRegion(imem_start, imem_size);
    CQMemory = new EmulationRegion(cq_start, cq_size);
    DataMemory = new EmulationRegion(dmem_start, dmem_size);
}

EmulationDevice::~EmulationDevice() {
    POCL_MSG_PRINT_INFO("accel: freeing emulated accel");
    E.emulate_exit_called = 1; // signal for the emulator to stop
    pthread_join(emulate_thread, NULL);
    free((void *)E.emulating_address); // from
                                        // calloc(emulating_address)
}

/*
 * AlmaIF v1 based accel emulator
 * Base_address is a preallocated emulation array that corresponds to the
 * memory map of the accelerator
 * Does operations 0,1,2,3,4
 * */
void *emulate_accel(void *E_void) {

  emulation_data_t *E = (emulation_data_t *)E_void;
  void *base_address = E->emulating_address;

  uint32_t ctrl_size = 1024;
  uint32_t imem_size = 0;
  uint32_t dmem_size = EMULATING_MAX_SIZE * 3 / 4;
  // The accelerator can choose the size of the queue (must be a power-of-two)
  // Can be even 1, to make the packet handling easiest with static offsets
  uint32_t queue_length = 3;
  uint32_t cqmem_size = (queue_length + 1) * AQL_PACKET_LENGTH;

  // The accelerator can set the starting addresses
  // Even the order can be changed if the accelerator wants to
  // Here packing the memory regions tighly as an example.
  uintptr_t imem_start = (uintptr_t)base_address + ctrl_size;
  uintptr_t cqmem_start = imem_start + imem_size;
  uintptr_t dmem_start = cqmem_start + cqmem_size;

  volatile uint32_t *Control = (uint32_t *)base_address;
  volatile uint8_t *Instruction = (uint8_t *)imem_start;
  volatile uint32_t *CQ = (uint32_t *)cqmem_start;
  volatile uint8_t *Data = (uint8_t *)dmem_start;

  // Set initial values for info registers:
  Control[ACCEL_INFO_DEV_CLASS / 4] = 0xE; // Unused
  Control[ACCEL_INFO_DEV_ID / 4] = 0;      // Unused
  Control[ACCEL_INFO_IF_TYPE / 4] = 3;
  Control[ACCEL_INFO_CORE_COUNT / 4] = 1;
  Control[ACCEL_INFO_CTRL_SIZE / 4] = 1024;

#define PTR_SIZE sizeof(uint32_t *)
  Control[ACCEL_INFO_PTR_SIZE / 4] = PTR_SIZE;

  // The emulation doesn't use Instruction/Configuration memory. This memory
  // space is a place to write accelerator specific configuration values
  // that are written BEFORE hw reset is deasserted.
  // E.g. program binaries of a processor-based accelerator
  Control[ACCEL_INFO_IMEM_SIZE / 4] = 0;
  Control[ACCEL_INFO_IMEM_START_LOW / 4] = (uint32_t)imem_start;
  Control[ACCEL_INFO_IMEM_START_HIGH / 4] = (uint32_t)(imem_start >> 32);

  Control[ACCEL_INFO_CQMEM_SIZE_LOW / 4] = cqmem_size;
  Control[ACCEL_INFO_CQMEM_START_LOW / 4] = (uint32_t)cqmem_start;
  Control[ACCEL_INFO_CQMEM_START_HIGH / 4] = (uint32_t)(cqmem_start >> 32);

  Control[ACCEL_INFO_DMEM_SIZE_LOW / 4] = dmem_size;
  Control[ACCEL_INFO_DMEM_START_LOW / 4] = (uint32_t)dmem_start;
  Control[ACCEL_INFO_DMEM_START_HIGH / 4] = (uint32_t)(dmem_start >> 32);

  uint32_t feature_flags_low = ACCEL_FF_BIT_AXI_MASTER;
  Control[ACCEL_INFO_FEATURE_FLAGS_LOW / 4] = feature_flags_low;

  // Signal the driver that the initial values are set
  // (in hardware this signal is probably not needed, since the values are
  // initialized in hw reset)
  E->emulate_init_done = 1;
  POCL_MSG_PRINT_INFO("accel emulate: Emulator initialized");

  int read_iter = 0;
  CQ[ACCEL_CQ_READ / 4] = read_iter;
  CQ[ACCEL_CQ_LENGTH / 4] = queue_length;

  // Accelerator is in infinite loop to process the commands
  // For emulating purposes we include the exit signal that the driver can
  // use to terminate the emulating thread. In hw this could be
  // a while(1) loop.
  while (!E->emulate_exit_called) {

    // Don't start computing anything before soft reset is lifted.
    // (This could probably be outside of the loop)
    int reset = Control[ACCEL_CONTROL_REG_COMMAND / 4];
    if (reset != ACCEL_CONTINUE_CMD) {
      usleep(100);
      continue;
    }

    // Compute packet location
    uint32_t packet_loc = ((read_iter % queue_length) + 1) * AQL_PACKET_LENGTH;
    struct AQLDispatchPacket *packet =
        (struct AQLDispatchPacket *)(CQ + packet_loc/4);

    // The driver will mark the packet as not INVALID when it wants us to
    // compute it
    if (packet->header == AQL_PACKET_INVALID) {
      usleep(100);
      continue;
    }

    uint16_t header = packet->header;
    if (header & (1 << AQL_PACKET_BARRIER_AND)) {
      struct AQLAndPacket *andPacket = (struct AQLAndPacket *)packet;
      POCL_MSG_PRINT_INFO("accel emulate: Found valid AND packet from location "
                          "%u, starting parsing:",
                          packet_loc);
      for (int i = 0; i < AQL_MAX_SIGNAL_COUNT; i++) {
        uint32_t *signal = (uint32_t *)(andPacket->dep_signals[i]);
        if (signal != NULL) {
          while (*signal == 0) {
            usleep(100);
          }
        }
      }
      POCL_MSG_PRINT_INFO("accel emulate: And packet done\n");
    }
    else if (header & (1 << AQL_PACKET_KERNEL_DISPATCH)) {
      POCL_MSG_PRINT_INFO("accel emulate: Found valid kernel dispatch packet from location "
                          "%u, starting parsing:",
                          packet_loc);
      POCL_MSG_PRINT_INFO("accel emulate: kernargs are at 0x%zx\n",
                          packet->kernarg_address);
      // Find the 3 pointers
      // Pointer size can be different on different systems
      // Also the endianness might need some attention in the real case.

      union args_u {
        uint32_t *ptrs[3];
        uint8_t values[3 * PTR_SIZE];
      } args;
      for (int i = 0; i < 3; i++) {
        for (int k = 0; k < PTR_SIZE; k++) {
          args.values[PTR_SIZE * i + k] =
              *(uint8_t *)(packet->kernarg_address + PTR_SIZE * i + k);
        }
      }
      uint32_t *arg0 = args.ptrs[0];
      uint32_t *arg1 = args.ptrs[1];
      uint32_t *arg2 = args.ptrs[2];

      POCL_MSG_PRINT_INFO("accel emulate: FOUND args arg0=%p, arg1=%p, arg2=%p\n",
                          arg0, arg1, arg2);

      // Check how many dimensions are in use, and set the unused ones to 1.
      int dim_x = packet->grid_size_x;
      int dim_y = (packet->dimensions >= 2) ? (packet->grid_size_y) : 1;
      int dim_z = (packet->dimensions == 3) ? (packet->grid_size_z) : 1;

      int red_count = 0;
      POCL_MSG_PRINT_INFO(
          "accel emulate: Parsing done: starting loops with dims (%i,%i,%i)",
          dim_x, dim_y, dim_z);
      for (int x = 0; x < dim_x; x++) {
        for (int y = 0; y < dim_y; y++) {
          for (int z = 0; z < dim_z; z++) {
            // Linearize grid
            int idx = x * dim_y * dim_z + y * dim_z + z;
            // Do the operation based on the kernel_object (integer id)
            switch (packet->kernel_object) {
            case (POCL_CDBI_COPY_I8):
              arg1[idx] = arg0[idx];
              break;
            case (POCL_CDBI_ADD_I32):
              arg2[idx] = arg0[idx] + arg1[idx];
              break;
            case (POCL_CDBI_MUL_I32):
              arg2[idx] = arg0[idx] * arg1[idx];
              break;
            case (POCL_CDBI_COUNTRED):
              uint32_t pixel = arg0[idx];
              uint8_t pixel_r = pixel & 0xFF;
              if (pixel_r > 100) {
                red_count++;
              }
            }
          }
        }
      }
      if (packet->kernel_object == POCL_CDBI_LEDBLINK) {
        std::cout << "Emulation blinking " << dim_x << " led(s) at interval "
                  << arg0[0] << " us " << arg1[0] << " times" << std::endl;
      }
      if (packet->kernel_object == POCL_CDBI_COUNTRED) {
        arg1[0] = red_count;
      }

      POCL_MSG_PRINT_INFO("accel emulate: Kernel done");
    }

    // Completion signal is given as absolute address
    if (packet->completion_signal) {
      *(uint32_t *)packet->completion_signal = 1;
    }
    packet->header = AQL_PACKET_INVALID;

    read_iter++; // move on to the next AQL packet
    CQ[ACCEL_CQ_READ / 4] = read_iter;
  }

  return NULL;
}
<commit_msg>accel: EmulationDevice: support pocl.abs.f32<commit_after>/* EmulationDevice.cc - accessing accelerator memory as memory mapped region.

   Copyright (c) 2021 Pekka Jääskeläinen / Tampere University

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

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

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
   IN THE SOFTWARE.
*/

#include "EmulationDevice.h"

#include "EmulationRegion.h"
#include "accel-shared.h"

#include <unistd.h>
#include <iostream>

EmulationDevice::EmulationDevice() {

    // The principle of the emulator is that instead of mmapping a real
    // accelerator, we just allocate a regular array, which corresponds
    // to the mmap. The accel_emulate function is working in another thread
    // and will fill that array and respond to the driver asynchronously.
    // The driver doesn't really need to know about emulating except
    // in the initial mapping of the accelerator
    E.emulating_address = calloc(1, EMULATING_MAX_SIZE);
    assert(E.emulating_address != NULL && "Emulating calloc failed\n");

    // Create emulator thread
    E.emulate_exit_called = 0;
    E.emulate_init_done = 0;
    pthread_create(&emulate_thread, NULL, emulate_accel, &E);
    while (!E.emulate_init_done)
      ; // Wait for the thread to initialize
    POCL_MSG_PRINT_INFO("accel: started emulating\n");

    ControlMemory =
        new EmulationRegion((size_t)E.emulating_address, ACCEL_DEFAULT_CTRL_SIZE);

    discoverDeviceParameters();

    InstructionMemory = new EmulationRegion(imem_start, imem_size);
    CQMemory = new EmulationRegion(cq_start, cq_size);
    DataMemory = new EmulationRegion(dmem_start, dmem_size);
}

EmulationDevice::~EmulationDevice() {
    POCL_MSG_PRINT_INFO("accel: freeing emulated accel");
    E.emulate_exit_called = 1; // signal for the emulator to stop
    pthread_join(emulate_thread, NULL);
    free((void *)E.emulating_address); // from
                                        // calloc(emulating_address)
}

/*
 * AlmaIF v1 based accel emulator
 * Base_address is a preallocated emulation array that corresponds to the
 * memory map of the accelerator
 * Does operations 0,1,2,3,4
 * */
void *emulate_accel(void *E_void) {

  emulation_data_t *E = (emulation_data_t *)E_void;
  void *base_address = E->emulating_address;

  uint32_t ctrl_size = 1024;
  uint32_t imem_size = 0;
  uint32_t dmem_size = EMULATING_MAX_SIZE * 3 / 4;
  // The accelerator can choose the size of the queue (must be a power-of-two)
  // Can be even 1, to make the packet handling easiest with static offsets
  uint32_t queue_length = 3;
  uint32_t cqmem_size = (queue_length + 1) * AQL_PACKET_LENGTH;

  // The accelerator can set the starting addresses
  // Even the order can be changed if the accelerator wants to
  // Here packing the memory regions tighly as an example.
  uintptr_t imem_start = (uintptr_t)base_address + ctrl_size;
  uintptr_t cqmem_start = imem_start + imem_size;
  uintptr_t dmem_start = cqmem_start + cqmem_size;

  volatile uint32_t *Control = (uint32_t *)base_address;
  volatile uint8_t *Instruction = (uint8_t *)imem_start;
  volatile uint32_t *CQ = (uint32_t *)cqmem_start;
  volatile uint8_t *Data = (uint8_t *)dmem_start;

  // Set initial values for info registers:
  Control[ACCEL_INFO_DEV_CLASS / 4] = 0xE; // Unused
  Control[ACCEL_INFO_DEV_ID / 4] = 0;      // Unused
  Control[ACCEL_INFO_IF_TYPE / 4] = 3;
  Control[ACCEL_INFO_CORE_COUNT / 4] = 1;
  Control[ACCEL_INFO_CTRL_SIZE / 4] = 1024;

#define PTR_SIZE sizeof(uint32_t *)
  Control[ACCEL_INFO_PTR_SIZE / 4] = PTR_SIZE;

  // The emulation doesn't use Instruction/Configuration memory. This memory
  // space is a place to write accelerator specific configuration values
  // that are written BEFORE hw reset is deasserted.
  // E.g. program binaries of a processor-based accelerator
  Control[ACCEL_INFO_IMEM_SIZE / 4] = 0;
  Control[ACCEL_INFO_IMEM_START_LOW / 4] = (uint32_t)imem_start;
  Control[ACCEL_INFO_IMEM_START_HIGH / 4] = (uint32_t)(imem_start >> 32);

  Control[ACCEL_INFO_CQMEM_SIZE_LOW / 4] = cqmem_size;
  Control[ACCEL_INFO_CQMEM_START_LOW / 4] = (uint32_t)cqmem_start;
  Control[ACCEL_INFO_CQMEM_START_HIGH / 4] = (uint32_t)(cqmem_start >> 32);

  Control[ACCEL_INFO_DMEM_SIZE_LOW / 4] = dmem_size;
  Control[ACCEL_INFO_DMEM_START_LOW / 4] = (uint32_t)dmem_start;
  Control[ACCEL_INFO_DMEM_START_HIGH / 4] = (uint32_t)(dmem_start >> 32);

  uint32_t feature_flags_low = ACCEL_FF_BIT_AXI_MASTER;
  Control[ACCEL_INFO_FEATURE_FLAGS_LOW / 4] = feature_flags_low;

  // Signal the driver that the initial values are set
  // (in hardware this signal is probably not needed, since the values are
  // initialized in hw reset)
  E->emulate_init_done = 1;
  POCL_MSG_PRINT_INFO("accel emulate: Emulator initialized");

  int read_iter = 0;
  CQ[ACCEL_CQ_READ / 4] = read_iter;
  CQ[ACCEL_CQ_LENGTH / 4] = queue_length;

  // Accelerator is in infinite loop to process the commands
  // For emulating purposes we include the exit signal that the driver can
  // use to terminate the emulating thread. In hw this could be
  // a while(1) loop.
  while (!E->emulate_exit_called) {

    // Don't start computing anything before soft reset is lifted.
    // (This could probably be outside of the loop)
    int reset = Control[ACCEL_CONTROL_REG_COMMAND / 4];
    if (reset != ACCEL_CONTINUE_CMD) {
      usleep(100);
      continue;
    }

    // Compute packet location
    uint32_t packet_loc = ((read_iter % queue_length) + 1) * AQL_PACKET_LENGTH;
    struct AQLDispatchPacket *packet =
        (struct AQLDispatchPacket *)(CQ + packet_loc/4);

    // The driver will mark the packet as not INVALID when it wants us to
    // compute it
    if (packet->header == AQL_PACKET_INVALID) {
      usleep(100);
      continue;
    }

    uint16_t header = packet->header;
    if (header & (1 << AQL_PACKET_BARRIER_AND)) {
      struct AQLAndPacket *andPacket = (struct AQLAndPacket *)packet;
      POCL_MSG_PRINT_INFO("accel emulate: Found valid AND packet from location "
                          "%u, starting parsing:",
                          packet_loc);
      for (int i = 0; i < AQL_MAX_SIGNAL_COUNT; i++) {
        uint32_t *signal = (uint32_t *)(andPacket->dep_signals[i]);
        if (signal != NULL) {
          while (*signal == 0) {
            usleep(100);
          }
        }
      }
      POCL_MSG_PRINT_INFO("accel emulate: And packet done\n");
    }
    else if (header & (1 << AQL_PACKET_KERNEL_DISPATCH)) {
      POCL_MSG_PRINT_INFO("accel emulate: Found valid kernel dispatch packet from location "
                          "%u, starting parsing:",
                          packet_loc);
      POCL_MSG_PRINT_INFO("accel emulate: kernargs are at 0x%zx\n",
                          packet->kernarg_address);
      // Find the 3 pointers
      // Pointer size can be different on different systems
      // Also the endianness might need some attention in the real case.

      union args_u {
        uint32_t *ptrs[3];
        uint8_t values[3 * PTR_SIZE];
      } args;
      for (int i = 0; i < 3; i++) {
        for (int k = 0; k < PTR_SIZE; k++) {
          args.values[PTR_SIZE * i + k] =
              *(uint8_t *)(packet->kernarg_address + PTR_SIZE * i + k);
        }
      }
      uint32_t *arg0 = args.ptrs[0];
      uint32_t *arg1 = args.ptrs[1];
      uint32_t *arg2 = args.ptrs[2];

      POCL_MSG_PRINT_INFO("accel emulate: FOUND args arg0=%p, arg1=%p, arg2=%p\n",
                          arg0, arg1, arg2);

      // Check how many dimensions are in use, and set the unused ones to 1.
      int dim_x = packet->grid_size_x;
      int dim_y = (packet->dimensions >= 2) ? (packet->grid_size_y) : 1;
      int dim_z = (packet->dimensions == 3) ? (packet->grid_size_z) : 1;

      int red_count = 0;
      POCL_MSG_PRINT_INFO(
          "accel emulate: Parsing done: starting loops with dims (%i,%i,%i)",
          dim_x, dim_y, dim_z);
      for (int x = 0; x < dim_x; x++) {
        for (int y = 0; y < dim_y; y++) {
          for (int z = 0; z < dim_z; z++) {
            // Linearize grid
            int idx = x * dim_y * dim_z + y * dim_z + z;
            // Do the operation based on the kernel_object (integer id)
            switch (packet->kernel_object) {
            case (POCL_CDBI_COPY_I8):
              arg1[idx] = arg0[idx];
              break;
            case (POCL_CDBI_ADD_I32):
              arg2[idx] = arg0[idx] + arg1[idx];
              break;
            case (POCL_CDBI_MUL_I32):
              arg2[idx] = arg0[idx] * arg1[idx];
              break;
            case (POCL_CDBI_COUNTRED):
              {
                  uint32_t pixel = arg0[idx];
                  uint8_t pixel_r = pixel & 0xFF;
                  if (pixel_r > 100) {
                      red_count++;
                    }
              }
              break;
            case (POCL_CDBI_ABS_F32):
              {
                  float *arg0f = (float*)arg0;
                  float *arg1f = (float*)arg1;
                  arg1f[idx] = std::abs(arg0f[idx]);
              }
              break;
            }
          }
        }
      }
      if (packet->kernel_object == POCL_CDBI_LEDBLINK) {
        std::cout << "Emulation blinking " << dim_x << " led(s) at interval "
                  << arg0[0] << " us " << arg1[0] << " times" << std::endl;
      }
      if (packet->kernel_object == POCL_CDBI_COUNTRED) {
        arg1[0] = red_count;
      }

      POCL_MSG_PRINT_INFO("accel emulate: Kernel done");
    }

    // Completion signal is given as absolute address
    if (packet->completion_signal) {
      *(uint32_t *)packet->completion_signal = 1;
    }
    packet->header = AQL_PACKET_INVALID;

    read_iter++; // move on to the next AQL packet
    CQ[ACCEL_CQ_READ / 4] = read_iter;
  }

  return NULL;
}
<|endoftext|>


<commit_before>#pragma once
#include <Siv3D.hpp> // August 2016 v2
#include "include/AnchorPoint.hpp"
#include "include/BoundingRect.hpp"

class BezierCurves
{
public:

	void update()
	{
		if (Input::MouseR.clicked)
		{
			m_anchorPoints.emplace_back(Mouse::PosF());
		}

		if (Input::MouseR.pressed)
		{
			m_anchorPoints.back().setSymmetricallyB(Mouse::PosF());
		}

		for (auto i : step(m_anchorPoints.size()))
		{
			if (m_anchorPoints[i].updateControlPoint(AnchorPointRadius()))
			{
				break;
			}
		}
	}

	void draw()const
	{
		for (const auto& p : m_anchorPoints)
		{
			p.draw(AnchorPointRadius());
		}

		std::vector<Vec2> pp;
		for (size_t i = 0; i + 1 < m_anchorPoints.size(); ++i)
		{
			const auto l0 = m_anchorPoints[i].outerHandle();
			const auto l1 = m_anchorPoints[i + 1].innerHandle();

			const auto& p0 = l0.begin;
			const auto& p1 = l0.end;
			const auto& p2 = l1.begin;
			const auto& p3 = l1.end;

			const auto getPos = [&](double t) {return (1 - t)*(1 - t)*(1 - t)*p0 + 3.0*(1 - t)*(1 - t)*t*p1 + 3.0*(1 - t)*t*t*p2 + t*t*t*p3; };

			const Vec2 a = (3 * p3 - 9 * p2 + 9 * p1 - 3 * p0);
			const Vec2 b = (6 * p0 - 12 * p1 + 6 * p2);
			const Vec2 c = 3 * (p1 - p0);

			const Vec2 d = b*b - 4 * a*c;

			/*
			https://stackoverflow.com/questions/24809978/calculating-the-bounding-box-of-cubic-bezier-curve
			*/
			BoundingRect boundingRect;
			boundingRect.add(p0);
			boundingRect.add(p3);

			if (0 < d.x)
			{
				const double t1 = (-b.x + sqrt(d.x)) / (2 * a.x);
				const double t2 = (-b.x - sqrt(d.x)) / (2 * a.x);
				if (0 < t1&&t1 < 1) {
					boundingRect.add(getPos(t1));
					//Circle(getPos(t1), controllPointRadius).draw(Color(255, 0, 0, 128));
				}
				if (0 < t2&&t2 < 1) {
					boundingRect.add(getPos(t2));
					//Circle(getPos(t2), controllPointRadius).draw(Color(0, 255, 0, 128));
				}
			}
			if (0 < d.y)
			{
				const double t1 = (-b.y + sqrt(d.y)) / (2 * a.y);
				const double t2 = (-b.y - sqrt(d.y)) / (2 * a.y);
				if (0 < t1&&t1 < 1) {
					boundingRect.add(getPos(t1));
					//Circle(getPos(t1), controllPointRadius).draw(Color(0, 0, 255, 128));
				}
				if (0 < t2&&t2 < 1) {
					boundingRect.add(getPos(t2));
					//Circle(getPos(t2), controllPointRadius).draw(Color(255, 255, 0, 128));
				}
			}
			//boundingRect.get().drawFrame();

			const int divNum = 30;
			for (int p = 0; p < divNum; ++p)
			{
				const double t = 1.0*p / (divNum - 1);
				pp.push_back(getPos(t));
			}
		}

		if (!pp.empty())
		{
			LineString(pp).draw(Palette::Yellow);
		}
	}

private:

	static double AnchorPointRadius()
	{
		return 5.0;
	}

	std::vector<AnchorPoint> m_anchorPoints;
};<commit_msg>add close path<commit_after>#pragma once
#include <Siv3D.hpp> // August 2016 v2
#include "include/AnchorPoint.hpp"
#include "include/BoundingRect.hpp"

class BezierCurves
{
public:

	void update()
	{
		if (Input::MouseR.clicked)
		{
			if (2 <= m_anchorPoints.size() && Circle(m_anchorPoints.front().anchorPoint(), AnchorPointRadius()).mouseOver)
			{
				m_isClosed = true;
			}

			if (!m_isClosed)
			{
				m_anchorPoints.emplace_back(Mouse::PosF());
			}
		}

		if (Input::MouseR.pressed)
		{
			if (!m_isClosed)
			{
				m_anchorPoints.back().setSymmetricallyB(Mouse::PosF());
			}
		}

		for (auto i : step(m_anchorPoints.size()))
		{
			if (m_anchorPoints[i].updateControlPoint(AnchorPointRadius()))
			{
				break;
			}
		}
	}

	void draw()const
	{
		for (const auto& p : m_anchorPoints)
		{
			p.draw(AnchorPointRadius());
		}

		std::vector<Vec2> pp;
		for (size_t i = 0; i + 1 < m_anchorPoints.size() || (m_isClosed && i < m_anchorPoints.size()); ++i)
		{
			const auto l0 = m_anchorPoints[i].outerHandle();
			const auto l1 = m_anchorPoints[(i + 1) % m_anchorPoints.size()].innerHandle();

			const auto& p0 = l0.begin;
			const auto& p1 = l0.end;
			const auto& p2 = l1.begin;
			const auto& p3 = l1.end;

			const auto getPos = [&](double t) {return (1 - t)*(1 - t)*(1 - t)*p0 + 3.0*(1 - t)*(1 - t)*t*p1 + 3.0*(1 - t)*t*t*p2 + t*t*t*p3; };

			const Vec2 a = (3 * p3 - 9 * p2 + 9 * p1 - 3 * p0);
			const Vec2 b = (6 * p0 - 12 * p1 + 6 * p2);
			const Vec2 c = 3 * (p1 - p0);

			const Vec2 d = b*b - 4 * a*c;

			/*
			https://stackoverflow.com/questions/24809978/calculating-the-bounding-box-of-cubic-bezier-curve
			*/
			BoundingRect boundingRect;
			boundingRect.add(p0);
			boundingRect.add(p3);

			if (0 < d.x)
			{
				const double t1 = (-b.x + sqrt(d.x)) / (2 * a.x);
				const double t2 = (-b.x - sqrt(d.x)) / (2 * a.x);
				if (0 < t1&&t1 < 1) {
					boundingRect.add(getPos(t1));
					//Circle(getPos(t1), controllPointRadius).draw(Color(255, 0, 0, 128));
				}
				if (0 < t2&&t2 < 1) {
					boundingRect.add(getPos(t2));
					//Circle(getPos(t2), controllPointRadius).draw(Color(0, 255, 0, 128));
				}
			}
			if (0 < d.y)
			{
				const double t1 = (-b.y + sqrt(d.y)) / (2 * a.y);
				const double t2 = (-b.y - sqrt(d.y)) / (2 * a.y);
				if (0 < t1&&t1 < 1) {
					boundingRect.add(getPos(t1));
					//Circle(getPos(t1), controllPointRadius).draw(Color(0, 0, 255, 128));
				}
				if (0 < t2&&t2 < 1) {
					boundingRect.add(getPos(t2));
					//Circle(getPos(t2), controllPointRadius).draw(Color(255, 255, 0, 128));
				}
			}
			//boundingRect.get().drawFrame();

			const int divNum = 30;
			for (int p = 0; p < divNum; ++p)
			{
				const double t = 1.0*p / (divNum - 1);
				pp.push_back(getPos(t));
			}
		}

		if (!pp.empty())
		{
			LineString(pp).draw(Palette::Yellow);
		}
	}

private:

	static double AnchorPointRadius()
	{
		return 5.0;
	}

	std::vector<AnchorPoint> m_anchorPoints;
	bool m_isClosed = false;
};<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Andrew Duggan
 * Copyright (C) 2014 Synaptics 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.
 */

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <unistd.h>
#include <time.h>
#include <string>
#include <sstream>

#include "hiddevice.h"
#include "rmi4update.h"

#define VERSION_MAJOR		1
#define VERSION_MINOR		2
#define VERSION_SUBMINOR	4

#define RMI4UPDATE_GETOPTS	"hfd:plv"

void printHelp(const char *prog_name)
{
	fprintf(stdout, "Usage: %s [OPTIONS] FIRMWAREFILE\n", prog_name);
	fprintf(stdout, "\t-h, --help\tPrint this message\n");
	fprintf(stdout, "\t-f, --force\tForce updating firmware even it the image provided is older\n\t\t\tthen the current firmware on the device.\n");
	fprintf(stdout, "\t-d, --device\thidraw device file associated with the device being updated.\n");
	fprintf(stdout, "\t-p, --fw-props\tPrint the firmware properties.\n");
	fprintf(stdout, "\t-l, --lockdown\tPerform lockdown.\n");
	fprintf(stdout, "\t-v, --version\tPrint version number.\n");
}

void printVersion()
{
	fprintf(stdout, "rmi4update version %d.%d.%d\n",
		VERSION_MAJOR, VERSION_MINOR, VERSION_SUBMINOR);
}

int UpdateDevice(FirmwareImage & image, bool force, bool performLockdown, const char * deviceFile)
{
	HIDDevice rmidevice;
	int rc;

	rc = rmidevice.Open(deviceFile);
	if (rc)
		return rc;

	RMI4Update update(rmidevice, image);
	rc = update.UpdateFirmware(force, performLockdown);
	if (rc != UPDATE_SUCCESS)
		return rc;

	return rc;
}

int GetFirmwareProps(const char * deviceFile, std::string &props)
{
	HIDDevice rmidevice;
	int rc = UPDATE_SUCCESS;
	std::stringstream ss;

	rc = rmidevice.Open(deviceFile);
	if (rc)
		return rc;

	rmidevice.ScanPDT(0x1);
	rmidevice.QueryBasicProperties();

	ss << rmidevice.GetFirmwareVersionMajor() << "."
		<< rmidevice.GetFirmwareVersionMinor() << "."
		<< std::hex << rmidevice.GetFirmwareID();

	if (rmidevice.InBootloader())
		ss << " bootloader";

	props = ss.str();

	return rc;
}

int main(int argc, char **argv)
{
	int rc;
	FirmwareImage image;
	int opt;
	int index;
	char *deviceName = NULL;
	const char *firmwareName = NULL;
	bool force = false;
	static struct option long_options[] = {
		{"help", 0, NULL, 'h'},
		{"force", 0, NULL, 'f'},
		{"device", 1, NULL, 'd'},
		{"fw-props", 0, NULL, 'p'},
		{"lockdown", 0, NULL, 'l'},
		{"version", 0, NULL, 'v'},
		{0, 0, 0, 0},
	};
	struct dirent * devDirEntry;
	DIR * devDir;
	bool printFirmwareProps = false;
	bool performLockdown = false;

	while ((opt = getopt_long(argc, argv, RMI4UPDATE_GETOPTS, long_options, &index)) != -1) {
		switch (opt) {
			case 'h':
				printHelp(argv[0]);
				return 0;
			case 'f':
				force = true;
				break;
			case 'd':
				deviceName = optarg;
				break;
			case 'p':
				printFirmwareProps = true;
				break;
			case 'l':
				performLockdown = true;
				break;
			case 'v':
				printVersion();
				return 0;
			default:
				break;

		}
	}

	if (printFirmwareProps) {
		std::string props;

		if (!deviceName) {
			fprintf(stderr, "Specifiy which device to query\n");
			return 1;
		}
		rc = GetFirmwareProps(deviceName, props);
		if (rc) {
			fprintf(stderr, "Failed to read properties from device: %s\n", update_err_to_string(rc));
			return 1;
		}
		fprintf(stdout, "%s\n", props.c_str());
		return 0;
	}

	if (optind < argc) {
		firmwareName = argv[optind];
	} else {
		printHelp(argv[0]);
		return -1;
	}

	rc = image.Initialize(firmwareName);
	if (rc != UPDATE_SUCCESS) {
		fprintf(stderr, "Failed to initialize the firmware image: %s\n", update_err_to_string(rc));
		return 1;
	}

	if (deviceName) {
		rc = UpdateDevice(image, force, performLockdown, deviceName);

		return rc;
	} else {
		char deviceFile[PATH_MAX];
		bool found = false;

		devDir = opendir("/dev");
		if (!devDir)
			return -1;

		while ((devDirEntry = readdir(devDir)) != NULL) {
			if (strstr(devDirEntry->d_name, "hidraw")) {
				char rawDevice[PATH_MAX];
				strncpy(rawDevice, devDirEntry->d_name, PATH_MAX);
				snprintf(deviceFile, PATH_MAX, "/dev/%s", devDirEntry->d_name);
				rc = UpdateDevice(image, force, performLockdown, deviceFile);
				if (rc != 0) {
					continue;
				} else {
					found = true;
					break;
				}
			}
		}
		closedir(devDir);

		if (!found)
			return rc;
	}

	return 0;
}
<commit_msg>rmi4update: add option to print the config id<commit_after>/*
 * Copyright (C) 2014 Andrew Duggan
 * Copyright (C) 2014 Synaptics 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.
 */

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <unistd.h>
#include <time.h>
#include <string>
#include <sstream>

#include "hiddevice.h"
#include "rmi4update.h"

#define VERSION_MAJOR		1
#define VERSION_MINOR		2
#define VERSION_SUBMINOR	4

#define RMI4UPDATE_GETOPTS	"hfd:pclv"

void printHelp(const char *prog_name)
{
	fprintf(stdout, "Usage: %s [OPTIONS] FIRMWAREFILE\n", prog_name);
	fprintf(stdout, "\t-h, --help\tPrint this message\n");
	fprintf(stdout, "\t-f, --force\tForce updating firmware even it the image provided is older\n\t\t\tthen the current firmware on the device.\n");
	fprintf(stdout, "\t-d, --device\thidraw device file associated with the device being updated.\n");
	fprintf(stdout, "\t-p, --fw-props\tPrint the firmware properties.\n");
	fprintf(stdout, "\t-c, --config-id\tPrint the config id.\n");
	fprintf(stdout, "\t-l, --lockdown\tPerform lockdown.\n");
	fprintf(stdout, "\t-v, --version\tPrint version number.\n");
}

void printVersion()
{
	fprintf(stdout, "rmi4update version %d.%d.%d\n",
		VERSION_MAJOR, VERSION_MINOR, VERSION_SUBMINOR);
}

int UpdateDevice(FirmwareImage & image, bool force, bool performLockdown, const char * deviceFile)
{
	HIDDevice rmidevice;
	int rc;

	rc = rmidevice.Open(deviceFile);
	if (rc)
		return rc;

	RMI4Update update(rmidevice, image);
	rc = update.UpdateFirmware(force, performLockdown);
	if (rc != UPDATE_SUCCESS)
		return rc;

	return rc;
}

int GetFirmwareProps(const char * deviceFile, std::string &props, bool configid)
{
	HIDDevice rmidevice;
	int rc = UPDATE_SUCCESS;
	std::stringstream ss;

	rc = rmidevice.Open(deviceFile);
	if (rc)
		return rc;

	rmidevice.ScanPDT(0x1);
	rmidevice.QueryBasicProperties();

	if (configid) {
		ss << std::hex << rmidevice.GetConfigID();
	} else {
		ss << rmidevice.GetFirmwareVersionMajor() << "."
			<< rmidevice.GetFirmwareVersionMinor() << "."
			<< std::hex << rmidevice.GetFirmwareID();

		if (rmidevice.InBootloader())
			ss << " bootloader";
	}

	props = ss.str();

	return rc;
}

int main(int argc, char **argv)
{
	int rc;
	FirmwareImage image;
	int opt;
	int index;
	char *deviceName = NULL;
	const char *firmwareName = NULL;
	bool force = false;
	static struct option long_options[] = {
		{"help", 0, NULL, 'h'},
		{"force", 0, NULL, 'f'},
		{"device", 1, NULL, 'd'},
		{"fw-props", 0, NULL, 'p'},
		{"config-id", 0, NULL, 'c'},
		{"lockdown", 0, NULL, 'l'},
		{"version", 0, NULL, 'v'},
		{0, 0, 0, 0},
	};
	struct dirent * devDirEntry;
	DIR * devDir;
	bool printFirmwareProps = false;
	bool printConfigid = false;
	bool performLockdown = false;

	while ((opt = getopt_long(argc, argv, RMI4UPDATE_GETOPTS, long_options, &index)) != -1) {
		switch (opt) {
			case 'h':
				printHelp(argv[0]);
				return 0;
			case 'f':
				force = true;
				break;
			case 'd':
				deviceName = optarg;
				break;
			case 'p':
				printFirmwareProps = true;
				break;
			case 'c':
				printFirmwareProps = true;
				printConfigid = true;
				break;
			case 'l':
				performLockdown = true;
				break;
			case 'v':
				printVersion();
				return 0;
			default:
				break;

		}
	}

	if (printFirmwareProps) {
		std::string props;

		if (!deviceName) {
			fprintf(stderr, "Specifiy which device to query\n");
			return 1;
		}
		rc = GetFirmwareProps(deviceName, props, printConfigid);
		if (rc) {
			fprintf(stderr, "Failed to read properties from device: %s\n", update_err_to_string(rc));
			return 1;
		}
		fprintf(stdout, "%s\n", props.c_str());
		return 0;
	}

	if (optind < argc) {
		firmwareName = argv[optind];
	} else {
		printHelp(argv[0]);
		return -1;
	}

	rc = image.Initialize(firmwareName);
	if (rc != UPDATE_SUCCESS) {
		fprintf(stderr, "Failed to initialize the firmware image: %s\n", update_err_to_string(rc));
		return 1;
	}

	if (deviceName) {
		rc = UpdateDevice(image, force, performLockdown, deviceName);

		return rc;
	} else {
		char deviceFile[PATH_MAX];
		bool found = false;

		devDir = opendir("/dev");
		if (!devDir)
			return -1;

		while ((devDirEntry = readdir(devDir)) != NULL) {
			if (strstr(devDirEntry->d_name, "hidraw")) {
				char rawDevice[PATH_MAX];
				strncpy(rawDevice, devDirEntry->d_name, PATH_MAX);
				snprintf(deviceFile, PATH_MAX, "/dev/%s", devDirEntry->d_name);
				rc = UpdateDevice(image, force, performLockdown, deviceFile);
				if (rc != 0) {
					continue;
				} else {
					found = true;
					break;
				}
			}
		}
		closedir(devDir);

		if (!found)
			return rc;
	}

	return 0;
}
<|endoftext|>


<commit_before><commit_msg>fixed tail call elimination<commit_after><|endoftext|>


<commit_before><commit_msg>Delete coord.cpp<commit_after><|endoftext|>


<commit_before>/* The following has been auto-generated by makedll.pl */
#ifndef ecmdDllCapi_H
#define ecmdDllCapi_H

#include <inttypes.h>
#include <vector>
#include <string>
#include <ecmdStructs.H>
#include <ecmdReturnCodes.H>
#include <ecmdDataBuffer.H>

extern "C" {

/* Dll Common load function - verifies version */
int dllLoadDll (const char * i_version, int debugLevel);
/* Dll Specific load function - used by Cronus/GFW to init variables/object models*/
int dllInitDll ();

/* Dll Common unload function */
int dllUnloadDll ();
/* Dll Specific unload function - deallocates variables/object models*/
int dllFreeDll();

/* Dll Common Command Line Args Function*/
int dllCommonCommandArgs(int*  io_argc, char** io_argv[]);
/* Dll Specific Command Line Args Function*/
int dllSpecificCommandArgs(int*  io_argc, char** io_argv[]);

int dllQueryDllInfo(ecmdDllInfo & o_dllInfo);

int dllQueryConfig(ecmdChipTarget & i_target, ecmdQueryData & o_queryData, ecmdQueryDetail_t i_detail );

int dllQuerySelected(ecmdChipTarget & io_target, ecmdQueryData & o_queryData);

int dllQueryRing(ecmdChipTarget & i_target, std::list<ecmdRingData> & o_queryData, const char * i_ringName );

int dllQueryArray(ecmdChipTarget & i_target, ecmdArrayData & o_queryData, const char * i_arrayName);

int dllQuerySpy(ecmdChipTarget & i_target, ecmdSpyData & o_queryData, const char * i_spyName);

int dllQueryFileLocation(ecmdChipTarget & i_target, ecmdFileType_t i_fileType, std::string & o_fileLocation);

int dllGetRing(ecmdChipTarget & i_target, const char * i_ringName, ecmdDataBuffer & o_data);

int dllPutRing(ecmdChipTarget & i_target, const char * i_ringName, ecmdDataBuffer & i_data);

int dllGetScom(ecmdChipTarget & i_target, uint32_t i_address, ecmdDataBuffer & o_data);

int dllPutScom(ecmdChipTarget & i_target, uint32_t i_address, ecmdDataBuffer & i_data);

int dllSendCmd(ecmdChipTarget & i_target, uint32_t i_instruction, uint32_t i_modifier, ecmdDataBuffer & o_status);

int dllGetSpy(ecmdChipTarget & i_target, const char * i_spyName, ecmdDataBuffer & o_data);

int dllGetSpyEnum(ecmdChipTarget & i_target, const char * i_spyName, std::string & o_enumValue);

int dllGetSpyEccGrouping(ecmdChipTarget & i_target, const char * i_spyEccGroupName, ecmdDataBuffer & o_groupData, ecmdDataBuffer & o_eccData, ecmdDataBuffer & o_eccErrorMask);

int dllPutSpy(ecmdChipTarget & i_target, const char * i_spyName, ecmdDataBuffer & i_data);

int dllPutSpyEnum(ecmdChipTarget & i_target, const char * i_spyName, const std::string i_enumValue);

void dllEnableRingCache();

int dllDisableRingCache();

int dllFlushRingCache();

int dllGetArray(ecmdChipTarget & i_target, const char * i_arrayName, ecmdDataBuffer & i_address, ecmdDataBuffer & o_data);

int dllGetArrayMultiple(ecmdChipTarget & i_target, const char * i_arrayName, std::list<ecmdArrayEntry> & io_entries);

int dllPutArray(ecmdChipTarget & i_target, const char * i_arrayName, ecmdDataBuffer & i_address, ecmdDataBuffer & i_data);

int dllPutArrayMultiple(ecmdChipTarget & i_target, const char * i_arrayName, std::list<ecmdArrayEntry> & i_entries);

int dllFlushSys();

int dllIplSys();

int dllSimaet(const char* i_function);

int dllSimcheckpoint(const char* i_checkpoint);

int dllSimclock(int i_cycles);

int dllSimecho(const char* i_message);

int dllSimexit();

int dllSimEXPECTFAC(unsigned int i_symbol, int i_bitlength, ecmdDataBuffer & i_expect, int i_row , int i_offset );

int dllSimEXPECTFACS(const char* i_facname, int i_bitlength, ecmdDataBuffer & i_expect, int i_row , int i_offset );

int dllSimexpecttcfac(const char* i_tcfacname, int i_bitlength, ecmdDataBuffer & i_expect, int i_row );

int dllSimgetcurrentcycle(int & o_cyclecount);

int dllSimGETFAC(unsigned int i_symbol, int i_bitlength, ecmdDataBuffer & o_data, int i_row , int i_offset );

int dllSimGETFACS(const char* i_facname, int i_bitlength, ecmdDataBuffer & o_data, int i_row , int i_offset );

int dllSimGETFACX(const char* i_facname, int i_bitlength, ecmdDataBuffer & o_data, int i_row , int i_offset );

int dllSimgettcfac(const char* i_tcfacname, ecmdDataBuffer & o_data, int i_row , int i_startbit , int i_bitlength );

int dllSiminit(const char* i_checkpoint);

int dllSimPUTFAC(unsigned int i_symbol, int i_bitlength, ecmdDataBuffer & i_data, int i_row , int i_offset );

int dllSimPUTFACS(const char* i_facname, int i_bitlength, ecmdDataBuffer & i_data, int i_row , int i_offset );

int dllSimPUTFACX(const char* i_facname, int i_bitlength, ecmdDataBuffer & i_data, int i_row , int i_offset );

int dllSimputtcfac(const char* i_tcfacname, int i_bitlength, ecmdDataBuffer & i_data, int i_row , int i_numrows );

int dllSimrestart(const char* i_checkpoint);

int dllSimSTKFAC(unsigned int i_symbol, int i_bitlength, ecmdDataBuffer & i_data, int i_row , int i_offset );

int dllSimSTKFACS(const char* i_facname, int i_bitlength, ecmdDataBuffer & i_data, int i_row , int i_offset );

int dllSimstktcfac(const char* i_tcfacname, int i_bitlength, ecmdDataBuffer & i_data, int i_row , int i_numrows );

int dllSimSUBCMD(const char* i_command);

int dllSimsymbol(const char* i_facname, unsigned int & o_symbol);

int dllSimtckinterval(int i_tckinterval);

int dllSimUNSTICK(unsigned int i_symbol, int i_bitlength, int i_row , int i_offset );

int dllSimUNSTICKS(const char* i_facname, int i_bitlength, int i_row , int i_offset );

int dllSimunsticktcfac(const char* i_tcfacname, int i_bitlength, ecmdDataBuffer & i_data, int i_row , int i_numrows );

std::string dllGetErrorMsg(int i_errorCode);

int dllRegisterErrorMsg(int i_errorCode, const char* i_whom, const char* i_message);

void dllOutputError(const char* i_message);

void dllOutputWarning(const char* i_message);

void dllOutput(const char* i_message);

} //extern C

#endif
/* The previous has been auto-generated by makedll.pl */
<commit_msg>Latest api updates<commit_after>/* The following has been auto-generated by makedll.pl */
#ifndef ecmdDllCapi_H
#define ecmdDllCapi_H

#include <inttypes.h>
#include <vector>
#include <string>
#include <ecmdStructs.H>
#include <ecmdReturnCodes.H>
#include <ecmdDataBuffer.H>

extern "C" {

/* Dll Common load function - verifies version */
int dllLoadDll (const char * i_version, int debugLevel);
/* Dll Specific load function - used by Cronus/GFW to init variables/object models*/
int dllInitDll ();

/* Dll Common unload function */
int dllUnloadDll ();
/* Dll Specific unload function - deallocates variables/object models*/
int dllFreeDll();

/* Dll Common Command Line Args Function*/
int dllCommonCommandArgs(int*  io_argc, char** io_argv[]);
/* Dll Specific Command Line Args Function*/
int dllSpecificCommandArgs(int*  io_argc, char** io_argv[]);

int dllQueryDllInfo(ecmdDllInfo & o_dllInfo);

int dllQueryConfig(ecmdChipTarget & i_target, ecmdQueryData & o_queryData, ecmdQueryDetail_t i_detail );

int dllQuerySelected(ecmdChipTarget & io_target, ecmdQueryData & o_queryData);

int dllQueryRing(ecmdChipTarget & i_target, std::list<ecmdRingData> & o_queryData, const char * i_ringName );

int dllQueryArray(ecmdChipTarget & i_target, ecmdArrayData & o_queryData, const char * i_arrayName);

int dllQuerySpy(ecmdChipTarget & i_target, ecmdSpyData & o_queryData, const char * i_spyName);

int dllQueryFileLocation(ecmdChipTarget & i_target, ecmdFileType_t i_fileType, std::string & o_fileLocation);

int dllGetRing(ecmdChipTarget & i_target, const char * i_ringName, ecmdDataBuffer & o_data);

int dllPutRing(ecmdChipTarget & i_target, const char * i_ringName, ecmdDataBuffer & i_data);

int dllGetScom(ecmdChipTarget & i_target, uint32_t i_address, ecmdDataBuffer & o_data);

int dllPutScom(ecmdChipTarget & i_target, uint32_t i_address, ecmdDataBuffer & i_data);

int dllSendCmd(ecmdChipTarget & i_target, uint32_t i_instruction, uint32_t i_modifier, ecmdDataBuffer & o_status);

int dllGetSpy(ecmdChipTarget & i_target, const char * i_spyName, ecmdDataBuffer & o_data);

int dllGetSpyEnum(ecmdChipTarget & i_target, const char * i_spyName, std::string & o_enumValue);

int dllGetSpyEccGrouping(ecmdChipTarget & i_target, const char * i_spyEccGroupName, ecmdDataBuffer & o_groupData, ecmdDataBuffer & o_eccData, ecmdDataBuffer & o_eccErrorMask);

int dllPutSpy(ecmdChipTarget & i_target, const char * i_spyName, ecmdDataBuffer & i_data);

int dllPutSpyEnum(ecmdChipTarget & i_target, const char * i_spyName, const std::string i_enumValue);

void dllEnableRingCache();

int dllDisableRingCache();

int dllFlushRingCache();

int dllGetArray(ecmdChipTarget & i_target, const char * i_arrayName, ecmdDataBuffer & i_address, ecmdDataBuffer & o_data);

int dllGetArrayMultiple(ecmdChipTarget & i_target, const char * i_arrayName, std::list<ecmdArrayEntry> & io_entries);

int dllPutArray(ecmdChipTarget & i_target, const char * i_arrayName, ecmdDataBuffer & i_address, ecmdDataBuffer & i_data);

int dllPutArrayMultiple(ecmdChipTarget & i_target, const char * i_arrayName, std::list<ecmdArrayEntry> & i_entries);

int dllFlushSys();

int dllIplSys();

int dllSimaet(const char* i_function);

int dllSimcheckpoint(const char* i_checkpoint);

int dllSimclock(int i_cycles);

int dllSimecho(const char* i_message);

int dllSimexit();

int dllSimEXPECTFAC(const char* i_facname, int i_bitlength, ecmdDataBuffer & i_expect, int i_row , int i_offset );

int dllSimexpecttcfac(const char* i_tcfacname, int i_bitlength, ecmdDataBuffer & i_expect, int i_row );

int dllSimgetcurrentcycle(int & o_cyclecount);

int dllSimGETFAC(const char* i_facname, int i_bitlength, ecmdDataBuffer & o_data, int i_row , int i_offset );

int dllSimGETFACX(const char* i_facname, int i_bitlength, ecmdDataBuffer & o_data, int i_row , int i_offset );

int dllSimgettcfac(const char* i_tcfacname, ecmdDataBuffer & o_data, int i_row , int i_startbit , int i_bitlength );

int dllSiminit(const char* i_checkpoint);

int dllSimPUTFAC(const char* i_facname, int i_bitlength, ecmdDataBuffer & i_data, int i_row , int i_offset );

int dllSimPUTFACX(const char* i_facname, int i_bitlength, ecmdDataBuffer & i_data, int i_row , int i_offset );

int dllSimputtcfac(const char* i_tcfacname, int i_bitlength, ecmdDataBuffer & i_data, int i_row , int i_numrows );

int dllSimrestart(const char* i_checkpoint);

int dllSimSTKFAC(const char* i_facname, int i_bitlength, ecmdDataBuffer & i_data, int i_row , int i_offset );

int dllSimstktcfac(const char* i_tcfacname, int i_bitlength, ecmdDataBuffer & i_data, int i_row , int i_numrows );

int dllSimSUBCMD(const char* i_command);

int dllSimtckinterval(int i_tckinterval);

int dllSimUNSTICK(const char* i_facname, int i_bitlength, int i_row , int i_offset );

int dllSimunsticktcfac(const char* i_tcfacname, int i_bitlength, ecmdDataBuffer & i_data, int i_row , int i_numrows );

std::string dllGetErrorMsg(int i_errorCode);

int dllRegisterErrorMsg(int i_errorCode, const char* i_whom, const char* i_message);

void dllOutputError(const char* i_message);

void dllOutputWarning(const char* i_message);

void dllOutput(const char* i_message);

} //extern C

#endif
/* The previous has been auto-generated by makedll.pl */
<|endoftext|>


<commit_before>/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm.h"
#include "SkGradientShader.h"
#include "SkPatchUtils.h"

static sk_sp<SkShader> make_shader() {
    const SkColor colors[] = {
        SK_ColorRED, SK_ColorCYAN, SK_ColorGREEN, SK_ColorWHITE, SK_ColorMAGENTA, SK_ColorBLUE,
        SK_ColorYELLOW,
    };
    const SkPoint pts[] = { { 100.f / 4.f, 0.f }, { 3.f * 100.f / 4.f, 100.f } };

    return SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors),
                                        SkShader::kMirror_TileMode);
}

static void draw_control_points(SkCanvas* canvas, const SkPoint cubics[12]) {
    //draw control points
    SkPaint paint;
    SkPoint bottom[SkPatchUtils::kNumPtsCubic];
    SkPatchUtils::GetBottomCubic(cubics, bottom);
    SkPoint top[SkPatchUtils::kNumPtsCubic];
    SkPatchUtils::GetTopCubic(cubics, top);
    SkPoint left[SkPatchUtils::kNumPtsCubic];
    SkPatchUtils::GetLeftCubic(cubics, left);
    SkPoint right[SkPatchUtils::kNumPtsCubic];
    SkPatchUtils::GetRightCubic(cubics, right);

    paint.setColor(SK_ColorBLACK);
    paint.setStrokeWidth(0.5f);
    SkPoint corners[4] = { bottom[0], bottom[3], top[0], top[3] };
    canvas->drawPoints(SkCanvas::kLines_PointMode, 4, bottom, paint);
    canvas->drawPoints(SkCanvas::kLines_PointMode, 2, bottom + 1, paint);
    canvas->drawPoints(SkCanvas::kLines_PointMode, 4, top, paint);
    canvas->drawPoints(SkCanvas::kLines_PointMode, 4, left, paint);
    canvas->drawPoints(SkCanvas::kLines_PointMode, 4, right, paint);

    canvas->drawPoints(SkCanvas::kLines_PointMode, 2, top + 1, paint);
    canvas->drawPoints(SkCanvas::kLines_PointMode, 2, left + 1, paint);
    canvas->drawPoints(SkCanvas::kLines_PointMode, 2, right + 1, paint);

    paint.setStrokeWidth(2);

    paint.setColor(SK_ColorRED);
    canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, corners, paint);

    paint.setColor(SK_ColorBLUE);
    canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, bottom + 1, paint);

    paint.setColor(SK_ColorCYAN);
    canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, top + 1, paint);

    paint.setColor(SK_ColorYELLOW);
    canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, left + 1, paint);

    paint.setColor(SK_ColorGREEN);
    canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, right + 1, paint);
}

DEF_SIMPLE_GM(patch_primitive, canvas, 1500, 1100) {
        SkPaint paint;

        // The order of the colors and points is clockwise starting at upper-left corner.
        const SkPoint cubics[SkPatchUtils::kNumCtrlPts] = {
            //top points
            {100,100},{150,50},{250,150}, {300,100},
            //right points
            {250, 150},{350,250},
            //bottom points
            {300,300},{250,250},{150,350},{100,300},
            //left points
            {50,250},{150,150}
        };

        const SkColor colors[SkPatchUtils::kNumCorners] = {
            SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorCYAN
        };
        const SkPoint texCoords[SkPatchUtils::kNumCorners] = {
            {0.0f, 0.0f}, {100.0f, 0.0f}, {100.0f,100.0f}, {0.0f, 100.0f}}
        ;

        const SkBlendMode modes[] = {
            SkBlendMode::kSrc,
            SkBlendMode::kDst,
            SkBlendMode::kModulate,
        };

        sk_sp<SkShader> shader(make_shader());

        canvas->save();
        for (int y = 0; y < 3; y++) {
            for (int x = 0; x < 4; x++) {
                canvas->save();
                canvas->translate(x * 350.0f, y * 350.0f);
                switch (x) {
                    case 0:
                        canvas->drawPatch(cubics, nullptr, nullptr, modes[y], paint);
                        break;
                    case 1:
                        canvas->drawPatch(cubics, colors, nullptr, modes[y], paint);
                        break;
                    case 2:
                        paint.setShader(shader);
                        canvas->drawPatch(cubics, nullptr, texCoords, modes[y], paint);
                        paint.setShader(nullptr);
                        break;
                    case 3:
                        paint.setShader(shader);
                        canvas->drawPatch(cubics, colors, texCoords, modes[y], paint);
                        paint.setShader(nullptr);
                        break;
                    default:
                        break;
                }

                draw_control_points(canvas, cubics);
                canvas->restore();
            }
        }
        canvas->restore();
}
<commit_msg>add gm to test alpha in drawPatch<commit_after>/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm.h"
#include "SkGradientShader.h"
#include "SkPatchUtils.h"
#include "SkPath.h"

static sk_sp<SkShader> make_shader() {
    const SkColor colors[] = {
        SK_ColorRED, SK_ColorCYAN, SK_ColorGREEN, SK_ColorWHITE, SK_ColorMAGENTA, SK_ColorBLUE,
        SK_ColorYELLOW,
    };
    const SkPoint pts[] = { { 100.f / 4.f, 0.f }, { 3.f * 100.f / 4.f, 100.f } };

    return SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors),
                                        SkShader::kMirror_TileMode);
}

static void draw_control_points(SkCanvas* canvas, const SkPoint cubics[12]) {
    //draw control points
    SkPaint paint;
    SkPoint bottom[SkPatchUtils::kNumPtsCubic];
    SkPatchUtils::GetBottomCubic(cubics, bottom);
    SkPoint top[SkPatchUtils::kNumPtsCubic];
    SkPatchUtils::GetTopCubic(cubics, top);
    SkPoint left[SkPatchUtils::kNumPtsCubic];
    SkPatchUtils::GetLeftCubic(cubics, left);
    SkPoint right[SkPatchUtils::kNumPtsCubic];
    SkPatchUtils::GetRightCubic(cubics, right);

    paint.setColor(SK_ColorBLACK);
    paint.setStrokeWidth(0.5f);
    SkPoint corners[4] = { bottom[0], bottom[3], top[0], top[3] };
    canvas->drawPoints(SkCanvas::kLines_PointMode, 4, bottom, paint);
    canvas->drawPoints(SkCanvas::kLines_PointMode, 2, bottom + 1, paint);
    canvas->drawPoints(SkCanvas::kLines_PointMode, 4, top, paint);
    canvas->drawPoints(SkCanvas::kLines_PointMode, 4, left, paint);
    canvas->drawPoints(SkCanvas::kLines_PointMode, 4, right, paint);

    canvas->drawPoints(SkCanvas::kLines_PointMode, 2, top + 1, paint);
    canvas->drawPoints(SkCanvas::kLines_PointMode, 2, left + 1, paint);
    canvas->drawPoints(SkCanvas::kLines_PointMode, 2, right + 1, paint);

    paint.setStrokeWidth(2);

    paint.setColor(SK_ColorRED);
    canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, corners, paint);

    paint.setColor(SK_ColorBLUE);
    canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, bottom + 1, paint);

    paint.setColor(SK_ColorCYAN);
    canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, top + 1, paint);

    paint.setColor(SK_ColorYELLOW);
    canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, left + 1, paint);

    paint.setColor(SK_ColorGREEN);
    canvas->drawPoints(SkCanvas::kPoints_PointMode, 2, right + 1, paint);
}

// The order of the colors and points is clockwise starting at upper-left corner.
const SkPoint gCubics[SkPatchUtils::kNumCtrlPts] = {
    //top points
    {100,100},{150,50},{250,150}, {300,100},
    //right points
    {250, 150},{350,250},
    //bottom points
    {300,300},{250,250},{150,350},{100,300},
    //left points
    {50,250},{150,150}
};

const SkPoint gTexCoords[SkPatchUtils::kNumCorners] = {
    {0.0f, 0.0f}, {100.0f, 0.0f}, {100.0f,100.0f}, {0.0f, 100.0f}
};

static void dopatch(SkCanvas* canvas, const SkColor colors[]) {
    SkPaint paint;

    const SkBlendMode modes[] = {
        SkBlendMode::kSrc,
        SkBlendMode::kDst,
        SkBlendMode::kModulate,
    };

    sk_sp<SkShader> shader(make_shader());

    canvas->save();
    for (int y = 0; y < 3; y++) {
        for (int x = 0; x < 4; x++) {
            canvas->save();
            canvas->translate(x * 350.0f, y * 350.0f);
            switch (x) {
                case 0:
                    canvas->drawPatch(gCubics, nullptr, nullptr, modes[y], paint);
                    break;
                case 1:
                    canvas->drawPatch(gCubics, colors, nullptr, modes[y], paint);
                    break;
                case 2:
                    paint.setShader(shader);
                    canvas->drawPatch(gCubics, nullptr, gTexCoords, modes[y], paint);
                    paint.setShader(nullptr);
                    break;
                case 3:
                    paint.setShader(shader);
                    canvas->drawPatch(gCubics, colors, gTexCoords, modes[y], paint);
                    paint.setShader(nullptr);
                    break;
                default:
                    break;
            }

            draw_control_points(canvas, gCubics);
            canvas->restore();
        }
    }
    canvas->restore();
}

DEF_SIMPLE_GM(patch_primitive, canvas, 1500, 1100) {
    const SkColor colors[SkPatchUtils::kNumCorners] = {
        SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorCYAN
    };
    dopatch(canvas, colors);
}
DEF_SIMPLE_GM(patch_alpha, canvas, 1500, 1100) {
    const SkColor colors[SkPatchUtils::kNumCorners] = {
        SK_ColorRED, 0x0000FF00, SK_ColorBLUE, 0x00FF00FF,
    };
    dopatch(canvas, colors);
}

// These two should look the same (one patch, one simple path)
DEF_SIMPLE_GM(patch_alpha_test, canvas, 550, 250) {
    canvas->translate(-75, -75);

    const SkColor colors[SkPatchUtils::kNumCorners] = {
        0x80FF0000, 0x80FF0000, 0x80FF0000, 0x80FF0000,
    };
    SkPaint paint;
    canvas->drawPatch(gCubics, colors, nullptr, SkBlendMode::kModulate, paint);

    canvas->translate(300, 0);

    SkPath path;
    path.moveTo(gCubics[0]);
    path.cubicTo(gCubics[ 1], gCubics[ 2], gCubics[ 3]);
    path.cubicTo(gCubics[ 4], gCubics[ 5], gCubics[ 6]);
    path.cubicTo(gCubics[ 7], gCubics[ 8], gCubics[ 9]);
    path.cubicTo(gCubics[10], gCubics[11], gCubics[ 0]);
    paint.setColor(colors[0]);
    canvas->drawPath(path, paint);
}

<|endoftext|>


<commit_before>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.

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. */

#include "Function.h"
#include "Im2Col.h"

namespace paddle {

/*
 * \brief Converts the image data of four dimensions(NCHW) into
 *        a sequence data of three dimensions(NST) in the forward calculation,
 *        which is reversed in the backward calculation.
 *        Where N is batch size, S is the length of the sequence after each
 *        image is expanded, T is the size of each time step in the sequence.
 *
 * Arguments in forward function:
 * \param inputs[0]  Image data of NCHW format.
 * \param outputs[0] Sequence data of NST format.
 *
 * Arguments in backward function:
 * \param inputs[0]  Sequence data of NST format.
 * \param outputs[0] Image data of NCHW format.
 */
class ImageExpandFunction : public FunctionBase {
public:
  void init(const FuncConfig& config) override {
    // function arguments
    strides_ = config.get<std::vector<size_t>>("strides");
    paddings_ = config.get<std::vector<size_t>>("paddings");
    blocks_ = config.get<std::vector<size_t>>("blocks");

    // number of inputs and outputs
    numInputs_ = 1;
    numOutputs_ = 1;
  }

  virtual void calc(const BufferArgs& inputs, const BufferArgs& outputs) {}

  void check(const TensorShape& image, const TensorShape& sequence) const {
    // image shape should be 4-dimensional.
    CHECK_EQ(image.ndims(), (size_t)4);
    // sequence shape should be 3-dimensional.
    CHECK_EQ(sequence.ndims(), (size_t)3);
    // The batchSize of the image needs to be equal to
    // the batchSize of the sequence.
    CHECK_EQ(image[0], sequence[0]);
  }

  // Calculate the shape of colData based on the shape of the image
  // and the shape of the sequence.
  TensorShape getColShape(const TensorShape& image,
                          const TensorShape& sequence) const {
    size_t inputChannels = image[1];
    size_t inputHeight = image[2];
    size_t inputWidth = image[3];
    size_t seqLength = sequence[1];
    size_t stepSize = sequence[2];
    size_t outputHeight =
        1 +
        (inputHeight + 2 * paddingH() - blockH() + strideH() - 1) / strideH();
    size_t outputWidth =
        1 +
        (inputWidth + 2 * paddingW() - blockW() + strideW() - 1) / strideW();
    CHECK_EQ(seqLength, outputHeight * outputWidth);
    CHECK_EQ(stepSize, inputChannels * blockH() * blockW());

    // [outputHeight, outputWidth, inputChannels, filterHeight, filterWidth]
    return TensorShape({outputHeight,
                        outputWidth,
                        inputChannels,
                        (size_t)blockH(),
                        (size_t)blockW()});
  }

protected:
  std::vector<size_t> strides_;
  std::vector<size_t> paddings_;
  std::vector<size_t> blocks_;

  inline int strideH() const { return strides_[0]; }

  inline int strideW() const { return strides_[1]; }

  inline int paddingH() const { return paddings_[0]; }

  inline int paddingW() const { return paddings_[1]; }

  inline int blockH() const { return blocks_[0]; }

  inline int blockW() const { return blocks_[1]; }
};

template <DeviceType Device>
class ImageExpandForward : public ImageExpandFunction {
public:
  void init(const FuncConfig& config) override {
    ImageExpandFunction::init(config);
  }

  void calc(const BufferArgs& inputs, const BufferArgs& outputs) override {
    CHECK_EQ(numInputs_, inputs.size());
    CHECK_EQ(numOutputs_, outputs.size());
    const TensorShape& image = inputs[0].shape();
    const TensorShape& sequence = outputs[0].shape();
    check(image, sequence);

    TensorShape imShape = TensorShape({image[1], image[2], image[3]});
    TensorShape colShape = getColShape(image, sequence);
    size_t batchSize = image[0];

    real* imageData = inputs[0].data<real>();
    real* seqData = outputs[0].data<real>();
    Im2ColFunctor<kOCF, Device, real> im2col;
    for (size_t i = 0; i < batchSize; i++) {
      // The result of im2col is [outputHeight, outputWidth,
      // inputChannels, filterHeight, filterWidth], and it is easy to
      // reshape into [seqLength, stepSize], where seqLength is equal
      // output_height * output_width, stepSize is equal
      // input_channels * filter_height * filter_width
      im2col(imageData,
             imShape,
             seqData,
             colShape,
             strideH(),
             strideW(),
             paddingH(),
             paddingW());
      imageData += imShape.getElements();
      seqData += colShape.getElements();
    }
  }
};

template <DeviceType Device>
class ImageExpandBackward : public ImageExpandFunction {
public:
  void init(const FuncConfig& config) override {
    ImageExpandFunction::init(config);
  }

  void calc(const BufferArgs& inputs, const BufferArgs& outputs) override {
    CHECK_EQ(numInputs_, inputs.size());
    CHECK_EQ(numOutputs_, outputs.size());
    // Since the implementation of Col2ImFunctor is ADD_TO,
    // this function only supports ADD_TO mode.
    CHECK_EQ(outputs[0].getArgType(), ADD_TO);
    const TensorShape& image = outputs[0].shape();
    const TensorShape& sequence = inputs[0].shape();
    check(image, sequence);

    TensorShape imShape = TensorShape({image[1], image[2], image[3]});
    TensorShape colShape = getColShape(image, sequence);
    size_t batchSize = image[0];

    real* imageData = outputs[0].data<real>();
    real* seqData = inputs[0].data<real>();
    Col2ImFunctor<kOCF, Device, real> col2im;
    for (size_t i = 0; i < batchSize; i++) {
      col2im(imageData,
             imShape,
             seqData,
             colShape,
             strideH(),
             strideW(),
             paddingH(),
             paddingW());
      imageData += imShape.getElements();
      seqData += colShape.getElements();
    }
  }
};

REGISTER_TYPED_FUNC(ImageExpand, CPU, ImageExpandForward);
REGISTER_TYPED_FUNC(ImageExpandGrad, CPU, ImageExpandBackward);
#ifndef PADDLE_ONLY_CPU
REGISTER_TYPED_FUNC(ImageExpand, GPU, ImageExpandForward);
REGISTER_TYPED_FUNC(ImageExpandGrad, GPU, ImageExpandBackward);
#endif

}  // namespace paddle
<commit_msg>Fix ImageExpandFunction.<commit_after>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.

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. */

#include "Function.h"
#include "Im2Col.h"

namespace paddle {

/*
 * \brief Converts the image data of four dimensions(NCHW) into
 *        a sequence data of three dimensions(NST) in the forward calculation,
 *        which is reversed in the backward calculation.
 *        Where N is batch size, S is the length of the sequence after each
 *        image is expanded, T is the size of each time step in the sequence.
 *
 * Arguments in forward function:
 * \param inputs[0]  Image data of NCHW format.
 * \param outputs[0] Sequence data of NST format.
 *
 * Arguments in backward function:
 * \param inputs[0]  Sequence data of NST format.
 * \param outputs[0] Image data of NCHW format.
 */
class ImageExpandFunction : public FunctionBase {
public:
  void init(const FuncConfig& config) override {
    // function arguments
    strides_ = config.get<std::vector<size_t>>("strides");
    paddings_ = config.get<std::vector<size_t>>("paddings");
    blocks_ = config.get<std::vector<size_t>>("blocks");

    // number of inputs and outputs
    numInputs_ = 1;
    numOutputs_ = 1;
  }

  void checkShape(const TensorShape& image, const TensorShape& sequence) const {
    // image shape should be 4-dimensional.
    CHECK_EQ(image.ndims(), (size_t)4);
    // sequence shape should be 3-dimensional.
    CHECK_EQ(sequence.ndims(), (size_t)3);
    // The batchSize of the image needs to be equal to
    // the batchSize of the sequence.
    CHECK_EQ(image[0], sequence[0]);
  }

  // Calculate the shape of colData based on the shape of the image
  // and the shape of the sequence.
  TensorShape getColShape(const TensorShape& image,
                          const TensorShape& sequence) const {
    size_t inputChannels = image[1];
    size_t inputHeight = image[2];
    size_t inputWidth = image[3];
    size_t seqLength = sequence[1];
    size_t stepSize = sequence[2];
    size_t outputHeight =
        1 +
        (inputHeight + 2 * paddingH() - blockH() + strideH() - 1) / strideH();
    size_t outputWidth =
        1 +
        (inputWidth + 2 * paddingW() - blockW() + strideW() - 1) / strideW();
    CHECK_EQ(seqLength, outputHeight * outputWidth);
    CHECK_EQ(stepSize, inputChannels * blockH() * blockW());

    // [outputHeight, outputWidth, inputChannels, filterHeight, filterWidth]
    return TensorShape({outputHeight,
                        outputWidth,
                        inputChannels,
                        (size_t)blockH(),
                        (size_t)blockW()});
  }

protected:
  std::vector<size_t> strides_;
  std::vector<size_t> paddings_;
  std::vector<size_t> blocks_;

  inline int strideH() const { return strides_[0]; }

  inline int strideW() const { return strides_[1]; }

  inline int paddingH() const { return paddings_[0]; }

  inline int paddingW() const { return paddings_[1]; }

  inline int blockH() const { return blocks_[0]; }

  inline int blockW() const { return blocks_[1]; }
};

template <DeviceType Device>
class ImageExpandForward : public ImageExpandFunction {
public:
  void init(const FuncConfig& config) override {
    ImageExpandFunction::init(config);
  }

  void check(const BufferArgs& inputs, const BufferArgs& outputs) override {
    const TensorShape& image = inputs[0].shape();
    const TensorShape& sequence = outputs[0].shape();
    checkShape(image, sequence);
  }

  void calc(const BufferArgs& inputs, const BufferArgs& outputs) override {
    CHECK_EQ(numInputs_, inputs.size());
    CHECK_EQ(numOutputs_, outputs.size());
    check(inputs, outputs);
    const TensorShape& image = inputs[0].shape();
    const TensorShape& sequence = outputs[0].shape();

    TensorShape imShape = TensorShape({image[1], image[2], image[3]});
    TensorShape colShape = getColShape(image, sequence);
    size_t batchSize = image[0];

    real* imageData = inputs[0].data<real>();
    real* seqData = outputs[0].data<real>();
    Im2ColFunctor<kOCF, Device, real> im2col;
    for (size_t i = 0; i < batchSize; i++) {
      // The result of im2col is [outputHeight, outputWidth,
      // inputChannels, filterHeight, filterWidth], and it is easy to
      // reshape into [seqLength, stepSize], where seqLength is equal
      // output_height * output_width, stepSize is equal
      // input_channels * filter_height * filter_width
      im2col(imageData,
             imShape,
             seqData,
             colShape,
             strideH(),
             strideW(),
             paddingH(),
             paddingW());
      imageData += imShape.getElements();
      seqData += colShape.getElements();
    }
  }
};

template <DeviceType Device>
class ImageExpandBackward : public ImageExpandFunction {
public:
  void init(const FuncConfig& config) override {
    ImageExpandFunction::init(config);
  }

  void check(const BufferArgs& inputs, const BufferArgs& outputs) override {
    const TensorShape& image = outputs[0].shape();
    const TensorShape& sequence = inputs[0].shape();
    checkShape(image, sequence);
  }

  void calc(const BufferArgs& inputs, const BufferArgs& outputs) override {
    CHECK_EQ(numInputs_, inputs.size());
    CHECK_EQ(numOutputs_, outputs.size());
    check(inputs, outputs);
    // Since the implementation of Col2ImFunctor is ADD_TO,
    // this function only supports ADD_TO mode.
    CHECK_EQ(outputs[0].getArgType(), ADD_TO);
    const TensorShape& image = outputs[0].shape();
    const TensorShape& sequence = inputs[0].shape();

    TensorShape imShape = TensorShape({image[1], image[2], image[3]});
    TensorShape colShape = getColShape(image, sequence);
    size_t batchSize = image[0];

    real* imageData = outputs[0].data<real>();
    real* seqData = inputs[0].data<real>();
    Col2ImFunctor<kOCF, Device, real> col2im;
    for (size_t i = 0; i < batchSize; i++) {
      col2im(imageData,
             imShape,
             seqData,
             colShape,
             strideH(),
             strideW(),
             paddingH(),
             paddingW());
      imageData += imShape.getElements();
      seqData += colShape.getElements();
    }
  }
};

REGISTER_TYPED_FUNC(ImageExpand, CPU, ImageExpandForward);
REGISTER_TYPED_FUNC(ImageExpandGrad, CPU, ImageExpandBackward);
#ifndef PADDLE_ONLY_CPU
REGISTER_TYPED_FUNC(ImageExpand, GPU, ImageExpandForward);
REGISTER_TYPED_FUNC(ImageExpandGrad, GPU, ImageExpandBackward);
#endif

}  // namespace paddle
<|endoftext|>