<commit_before>#include "GLFW.h"
#include <stdexcept>

#ifdef USE_GLFW3
  #include <GLFW/glfw3.h>
#else
  #include <GL/glfw.h>
#endif // USE_GLFW3

namespace glfw
{
#ifdef USE_GLFW3
  const int KEY_LEFT          = GLFW_KEY_LEFT;
  const int KEY_RIGHT         = GLFW_KEY_RIGHT;
  const int KEY_UP            = GLFW_KEY_UP;
  const int KEY_DOWN          = GLFW_KEY_DOWN;
  const int KEY_TAB           = GLFW_KEY_TAB;
  const int KEY_ESC           = GLFW_KEY_ESCAPE;

  const int KEY_G             = GLFW_KEY_G;
  const int KEY_H             = GLFW_KEY_H;

  const int KEY_PRESS         = GLFW_PRESS;
  const int KEY_RELEASE       = GLFW_RELEASE;

#else
  const int KEY_LEFT          = GLFW_KEY_LEFT;
  const int KEY_RIGHT         = GLFW_KEY_RIGHT;
  const int KEY_UP            = GLFW_KEY_UP;
  const int KEY_DOWN          = GLFW_KEY_DOWN;
  const int KEY_TAB           = GLFW_KEY_TAB;
  const int KEY_ESC           = GLFW_KEY_ESC;

  const int KEY_G             = 71;
  const int KEY_H             = 72;

  const int KEY_PRESS         = GLFW_PRESS;
  const int KEY_RELEASE       = GLFW_RELEASE;

#endif // USE_GLFW3

  void init()
  {
    if (!glfwInit())
    {
      throw std::runtime_error("Unable to initialize glfw");
    }
  }

  void terminate()
  {
    glfwTerminate();
  }

  double time()
  {
    return glfwGetTime();
  }

  void sleep(double duration)
  {
#ifdef USE_GLFW3
#else
    glfwSleep(duration);
#endif // USE_GLFW3
  }

  void swapInterval(int interval)
  {
    glfwSwapInterval(interval);
  }

  WindowSize::WindowSize(int width, int height)
    : m_width(width)
    , m_height(height)
  {
  }

  int WindowSize::width() const {
    return m_width;
  }

  int WindowSize::height() const {
    return m_height;
  }

  Window::Window(int width, int height, const char* title)
  {
#ifdef USE_GLFW3
    m_window = glfwCreateWindow(width, height, title, NULL, NULL);
#else
    if (!glfwOpenWindow(width, height, 0, 0, 0, 0, 0, 0, GLFW_WINDOW))
    {
      throw std::runtime_error("Unable to create window");
    }
#endif // USE_GLFW3
  }

  Window::Window(const Window& window)
  {
#ifdef USE_GLFW3
    m_window = window.m_window;
#endif // USE_GLFW3
  }

  void Window::swapBuffers() const
  {
#ifdef USE_GLFW3
    glfwSwapBuffers(m_window);
#else
    glfwSwapBuffers();
#endif // USE_GLFW3
  }

  bool Window::isOpen() const
  {
#ifdef USE_GLFW3
    return true;
#else
    return glfwGetWindowParam(GLFW_OPENED);
#endif // USE_GLFW3
  }

  void Window::makeCurrent() const
  {
#ifdef USE_GLFW3
    glfwMakeContextCurrent(m_window);
#endif // USE_GLFW3
  }

  void Window::pollEvents() const
  {
#ifdef USE_GLFW3
    glfwPollEvents();
#endif // USE_GLFW3
  }

  int Window::getKey(int key) const
  {
#ifdef USE_GLFW3
    return glfwGetKey(m_window, key);
#else
    return glfwGetKey(key);
#endif // USE_GLFW3
  }
}
<commit_msg>added new ctor for Window<commit_after>#include "GLFW.h"
#include <stdexcept>

#ifdef USE_GLFW3
  #include <GLFW/glfw3.h>
#else
  #include <GL/glfw.h>
#endif // USE_GLFW3

namespace glfw
{
#ifdef USE_GLFW3
  const int KEY_LEFT          = GLFW_KEY_LEFT;
  const int KEY_RIGHT         = GLFW_KEY_RIGHT;
  const int KEY_UP            = GLFW_KEY_UP;
  const int KEY_DOWN          = GLFW_KEY_DOWN;
  const int KEY_TAB           = GLFW_KEY_TAB;
  const int KEY_ESC           = GLFW_KEY_ESCAPE;

  const int KEY_G             = GLFW_KEY_G;
  const int KEY_H             = GLFW_KEY_H;

  const int KEY_PRESS         = GLFW_PRESS;
  const int KEY_RELEASE       = GLFW_RELEASE;

#else
  const int KEY_LEFT          = GLFW_KEY_LEFT;
  const int KEY_RIGHT         = GLFW_KEY_RIGHT;
  const int KEY_UP            = GLFW_KEY_UP;
  const int KEY_DOWN          = GLFW_KEY_DOWN;
  const int KEY_TAB           = GLFW_KEY_TAB;
  const int KEY_ESC           = GLFW_KEY_ESC;

  const int KEY_G             = 71;
  const int KEY_H             = 72;

  const int KEY_PRESS         = GLFW_PRESS;
  const int KEY_RELEASE       = GLFW_RELEASE;

#endif // USE_GLFW3

  void init()
  {
    if (!glfwInit())
    {
      throw std::runtime_error("Unable to initialize glfw");
    }
  }

  void terminate()
  {
    glfwTerminate();
  }

  double time()
  {
    return glfwGetTime();
  }

  void sleep(double duration)
  {
#ifdef USE_GLFW3
#else
    glfwSleep(duration);
#endif // USE_GLFW3
  }

  void swapInterval(int interval)
  {
    glfwSwapInterval(interval);
  }

  WindowSize::WindowSize(int width, int height)
    : m_width(width)
    , m_height(height)
  {
  }

  int WindowSize::width() const {
    return m_width;
  }

  int WindowSize::height() const {
    return m_height;
  }

  Window::Window(const WindowSize& size, const char* title)
    :Window(size.width(), size.height(), title)
  {
  }

  Window::Window(int width, int height, const char* title)
  {
#ifdef USE_GLFW3
    m_window = glfwCreateWindow(width, height, title, NULL, NULL);
#else
    if (!glfwOpenWindow(width, height, 0, 0, 0, 0, 0, 0, GLFW_WINDOW))
    {
      throw std::runtime_error("Unable to create window");
    }
#endif // USE_GLFW3
  }

  Window::Window(const Window& window)
  {
#ifdef USE_GLFW3
    m_window = window.m_window;
#endif // USE_GLFW3
  }

  void Window::swapBuffers() const
  {
#ifdef USE_GLFW3
    glfwSwapBuffers(m_window);
#else
    glfwSwapBuffers();
#endif // USE_GLFW3
  }

  bool Window::isOpen() const
  {
#ifdef USE_GLFW3
    return true;
#else
    return glfwGetWindowParam(GLFW_OPENED);
#endif // USE_GLFW3
  }

  void Window::makeCurrent() const
  {
#ifdef USE_GLFW3
    glfwMakeContextCurrent(m_window);
#endif // USE_GLFW3
  }

  void Window::pollEvents() const
  {
#ifdef USE_GLFW3
    glfwPollEvents();
#endif // USE_GLFW3
  }

  int Window::getKey(int key) const
  {
#ifdef USE_GLFW3
    return glfwGetKey(m_window, key);
#else
    return glfwGetKey(key);
#endif // USE_GLFW3
  }
}
<|endoftext|>


<commit_before>#ifndef __ENVIRE_MAPS_GRID_HPP__
#define __ENVIRE_MAPS_GRID_HPP__

#include <iostream>

#include <boost/shared_ptr.hpp>
#include <boost/multi_array.hpp>

#include "GridBase.hpp"

namespace envire
{
    namespace maps
    {
        template <typename T>
        class Grid : public GridBase {

        public:
            typedef boost::multi_array<T,2> ArrayType;

            Grid()
                :GridBase(),
                holder(new ArrayType())
            {
            }

            Grid(const T& default_value, GridConfig config)
                : GridBase(config),
                holder(new ArrayType()),
                default_value(default_value)
            {
            }

            Grid(const Grid& other) :
                GridBase(other.config),
                default_value(other.default_value),
                holder(new ArrayType(*(other.holder)))
            {
            }

            ~Grid()
            {
                delete holder;
            }

            const T& getDefaultValue() const
            {
                return default_value;
            }

            const T& at(const Eigen::Vector2d& pos) const
            {
                Index idx;
                if (!toGrid(pos, idx))
                    throw std::runtime_error("Provided position is out of the grid.");
                return get(idx);
            }

            T& at(const Eigen::Vector2d& pos)
            {
                Index idx;
                if (!toGrid(pos, idx))
                    throw std::runtime_error("Provided position is out of the grid");
                return get(idx);
            }

            const T& at(Index idx) const
            {
                if (!inGrid(idx))
                    throw std::runtime_error("Provided index is out of the grid");
                return get(idx);
            }

            T& at(Index idx)
            {
                if (!inGrid(idx))
                    throw std::runtime_error("Provided index is out of the grid");
                return get(idx);
            }

            const T& at(size_t x, size_t y) const
            {
                Index idx(x, y);
                if (!inGrid(idx))
                    throw std::runtime_error("Provided index is out of the grid");
                return get(idx);
            }

            T& at(size_t x, size_t y)
            {
                Index idx(x, y);
                if (!inGrid(idx))
                    throw std::runtime_error("Provided index is out of the grid");
                return get(idx);
            }

            const T& getMax() const
            {
                const ArrayType &array = getArray();
                // TODO: if max_element return end iterator
                return *(std::max_element(array.origin(), array.origin() + array.num_elements()));
            }

            const T& getMin() const
            {
                const ArrayType &array = getArray();
                // TODO: if min_element return end iterator
                return *(std::min_element(array.origin(), array.origin() + array.num_elements()));
            }

            void moveBy(Index idx)
            {
                // if all grid values should be moved outside
                if (abs(idx.x) >= getCellSizeX()
                    || abs(idx.y) >= getCellSizeY())
                {
                    init();
                    return;
                }

                ArrayType &src = getArray();

                ArrayType tmp;
                tmp.resize(boost::extents[getCellSizeY()][getCellSizeX()]);
                std::fill(tmp.data(),
                            tmp.data() + tmp.num_elements(),
                            default_value);

                boost::swap(tmp, src);

                for (int x = 0; x < getCellSizeX(); ++x)
                {
                    for (int y = 0; y < getCellSizeY(); ++y)
                    {
                        int x_new = x + idx.x;
                        int y_new = y + idx.y;

                        if (x_new >= 0 && x_new < getCellSizeX()
                            && y_new >= 0 && y_new < getCellSizeY())
                        {
                            get(Index(x_new, y_new)) = *(tmp.data() + y * getCellSizeX() + x);
                        }
                    }
                }
            }

            void clear()
            {
                init();
            }

        private:
            ArrayType* holder;
            T default_value;

            T& get(Index idx)
            {
                return *(getArray().data() + idx.y * getCellSizeX() + idx.x);
            }

            const T& get(Index idx) const
            {
                return *(getArray().data() + idx.y * getCellSizeX() + idx.x);
            }

            void init() const
            {
                if (getCellSizeX() == 0 || getCellSizeY() == 0)
                    throw std::runtime_error("The grid size is zero! (therefore the array to hold the cells could be not allocated properly)");

                holder->resize(boost::extents[getCellSizeY()][getCellSizeX()]);
                std::fill(holder->data(),
                            holder->data() + holder->num_elements(),
                            default_value);
            }

            ArrayType& getArray()
            {
                if (holder->num_elements() == 0)
                    init();

                return *holder;
            }

            const ArrayType& getArray() const
            {
                if (holder->num_elements() == 0)
                    init();

                return *holder;
            }
        };
    }
}

#endif // __ENVIRE_MAPS_GRID_HPP__<commit_msg>delete todos<commit_after>#ifndef __ENVIRE_MAPS_GRID_HPP__
#define __ENVIRE_MAPS_GRID_HPP__

#include <iostream>

#include <boost/shared_ptr.hpp>
#include <boost/multi_array.hpp>

#include "GridBase.hpp"

namespace envire
{
    namespace maps
    {
        template <typename T>
        class Grid : public GridBase {

        public:
            typedef boost::multi_array<T,2> ArrayType;

            Grid()
                :GridBase(),
                holder(new ArrayType())
            {
            }

            Grid(const T& default_value, GridConfig config)
                : GridBase(config),
                holder(new ArrayType()),
                default_value(default_value)
            {
            }

            Grid(const Grid& other) :
                GridBase(other.config),
                default_value(other.default_value),
                holder(new ArrayType(*(other.holder)))
            {
            }

            ~Grid()
            {
                delete holder;
            }

            const T& getDefaultValue() const
            {
                return default_value;
            }

            const T& at(const Eigen::Vector2d& pos) const
            {
                Index idx;
                if (!toGrid(pos, idx))
                    throw std::runtime_error("Provided position is out of the grid.");
                return get(idx);
            }

            T& at(const Eigen::Vector2d& pos)
            {
                Index idx;
                if (!toGrid(pos, idx))
                    throw std::runtime_error("Provided position is out of the grid");
                return get(idx);
            }

            const T& at(Index idx) const
            {
                if (!inGrid(idx))
                    throw std::runtime_error("Provided index is out of the grid");
                return get(idx);
            }

            T& at(Index idx)
            {
                if (!inGrid(idx))
                    throw std::runtime_error("Provided index is out of the grid");
                return get(idx);
            }

            const T& at(size_t x, size_t y) const
            {
                Index idx(x, y);
                if (!inGrid(idx))
                    throw std::runtime_error("Provided index is out of the grid");
                return get(idx);
            }

            T& at(size_t x, size_t y)
            {
                Index idx(x, y);
                if (!inGrid(idx))
                    throw std::runtime_error("Provided index is out of the grid");
                return get(idx);
            }

            const T& getMax() const
            {
                const ArrayType &array = getArray();
                return *(std::max_element(array.origin(), array.origin() + array.num_elements()));
            }

            const T& getMin() const
            {
                const ArrayType &array = getArray();
                return *(std::min_element(array.origin(), array.origin() + array.num_elements()));
            }

            void moveBy(Index idx)
            {
                // if all grid values should be moved outside
                if (abs(idx.x) >= getCellSizeX()
                    || abs(idx.y) >= getCellSizeY())
                {
                    init();
                    return;
                }

                ArrayType &src = getArray();

                ArrayType tmp;
                tmp.resize(boost::extents[getCellSizeY()][getCellSizeX()]);
                std::fill(tmp.data(),
                            tmp.data() + tmp.num_elements(),
                            default_value);

                boost::swap(tmp, src);

                for (int x = 0; x < getCellSizeX(); ++x)
                {
                    for (int y = 0; y < getCellSizeY(); ++y)
                    {
                        int x_new = x + idx.x;
                        int y_new = y + idx.y;

                        if (x_new >= 0 && x_new < getCellSizeX()
                            && y_new >= 0 && y_new < getCellSizeY())
                        {
                            get(Index(x_new, y_new)) = *(tmp.data() + y * getCellSizeX() + x);
                        }
                    }
                }
            }

            void clear()
            {
                init();
            }

        private:
            ArrayType* holder;
            T default_value;

            T& get(Index idx)
            {
                return *(getArray().data() + idx.y * getCellSizeX() + idx.x);
            }

            const T& get(Index idx) const
            {
                return *(getArray().data() + idx.y * getCellSizeX() + idx.x);
            }

            void init() const
            {
                if (getCellSizeX() == 0 || getCellSizeY() == 0)
                    throw std::runtime_error("The grid size is zero! (therefore the array to hold the cells could be not allocated properly)");

                holder->resize(boost::extents[getCellSizeY()][getCellSizeX()]);
                std::fill(holder->data(),
                            holder->data() + holder->num_elements(),
                            default_value);
            }

            ArrayType& getArray()
            {
                if (holder->num_elements() == 0)
                    init();

                return *holder;
            }

            const ArrayType& getArray() const
            {
                if (holder->num_elements() == 0)
                    init();

                return *holder;
            }
        };
    }
}

#endif // __ENVIRE_MAPS_GRID_HPP__<|endoftext|>


<commit_before>// Image.hh for Fluxbox Window Manager
// Copyright (c) 2001 - 2002 Henrik Kinnunen (fluxbox@linuxmail.org)
//
// Image.hh for Blackbox - an X11 Window manager
// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
//
// 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.

// $Id: Image.hh,v 1.11 2002/08/04 15:55:13 fluxgen Exp $

#ifndef	 IMAGE_HH
#define	 IMAGE_HH

#include "Timer.hh"
#include "BaseDisplay.hh"
#include "Color.hh"
#include "Texture.hh"

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <list>

class BImageControl;

/**
	Renders to pixmap
*/
class BImage {
public:
	BImage(BImageControl *ic, unsigned int, unsigned int);
	~BImage();
	/// render to pixmap
	Pixmap render(const FbTk::Texture *src_texture);
	/// render solid texture to pixmap
	Pixmap renderSolid(const FbTk::Texture *src_texture);
	/// render gradient texture to pixmap
	Pixmap renderGradient(const FbTk::Texture *src_texture);

protected:
	/**
		Render to pixmap
		@return rendered pixmap
	*/
	Pixmap renderPixmap();
	/**
		Render to XImage
		@returns allocated and rendered XImage, user is responsible to deallocate
	*/
	XImage *renderXImage();
	/**
		@name render functions
	*/
	//@{
	void invert();
	void bevel1();
	void bevel2();
	void dgradient();
	void egradient();
	void hgradient();
	void pgradient();
	void rgradient();
	void vgradient();
	void cdgradient();
	void pcgradient();
	//@}

private:
	BImageControl *control;

#ifdef		INTERLACE
	bool interlaced;
#endif // INTERLACE

	XColor *colors; // color table

	const FbTk::Color *from, *to;
	int red_offset, green_offset, blue_offset, red_bits, green_bits, blue_bits,
		ncolors, cpc, cpccpc;
	unsigned char *red, *green, *blue, *red_table, *green_table, *blue_table;
	unsigned int width, height, *xtable, *ytable;
};

/**
	Holds screen info and color tables
*/
class BImageControl : public TimeoutHandler {
public:
	BImageControl(BaseDisplay *disp, ScreenInfo *screen, bool = False, int = 4,
		unsigned long = 300000l, unsigned long = 200l);
	virtual ~BImageControl();

	inline BaseDisplay *baseDisplay() { return basedisplay; }

	inline bool doDither() { return dither; }
	inline const Colormap &colormap() const { return m_colormap; }
	inline const ScreenInfo *getScreenInfo() const { return screeninfo; }
	inline Window drawable() const { return window; }

	/// @return visual of screen
	inline Visual *visual() { return screeninfo->getVisual(); }
	/// @return Bits per pixel of screen
	inline int bitsPerPixel() const { return bits_per_pixel; }
	/// @return depth of screen
	inline int depth() const { return screen_depth; }
	inline int colorsPerChannel() const	{ return colors_per_channel; }

	unsigned long color(const char *colorname);
	unsigned long color(const char *, unsigned char *, unsigned char *,
												 unsigned char *);
	unsigned long getSqrt(unsigned int val);
	/**
		Render to pixmap
		@param width width of pixmap
		@param height height of pixmap
		@param src_texture texture type to render
		@return pixmap of the rendered image, on failure None
	*/
	Pixmap renderImage(unsigned int width, unsigned int height,
		const FbTk::Texture *src_texture);

	void installRootColormap();
	void removeImage(Pixmap thepix);
	void colorTables(unsigned char **, unsigned char **, unsigned char **,
			int *, int *, int *, int *, int *, int *);
	void getXColorTable(XColor **, int *);
	void getGradientBuffers(unsigned int, unsigned int,
			unsigned int **, unsigned int **);
	void setDither(bool d) { dither = d; }
	void setColorsPerChannel(int cpc);
	void parseTexture(FbTk::Texture *ret_texture, const char *sval);
	void parseColor(FbTk::Color *ret_color, const char *sval = 0);

	virtual void timeout();

protected:
	/**
		Search cache for a specific pixmap
		@return None if no cache was found
	*/
	Pixmap searchCache(unsigned int width, unsigned int height, unsigned long texture_type,
		const FbTk::Color &color, const FbTk::Color &color_to);

private:
	bool dither;
	BaseDisplay *basedisplay;
	ScreenInfo *screeninfo;
#ifdef		TIMEDCACHE
	BTimer timer;
#endif // TIMEDCACHE

	Colormap m_colormap;

	Window window;
	XColor *colors; ///< color table

	int colors_per_channel, ncolors, screen_number, screen_depth,
		bits_per_pixel, red_offset, green_offset, blue_offset,
		red_bits, green_bits, blue_bits;

	unsigned char red_color_table[256], green_color_table[256],
		blue_color_table[256];
	unsigned int *grad_xbuffer, *grad_ybuffer, grad_buffer_width,
		grad_buffer_height;

	static unsigned long *sqrt_table; /// sqrt lookup table

	typedef struct Cache {
		Pixmap pixmap;

		unsigned int count, width, height;
		unsigned long pixel1, pixel2, texture;
	} Cache;

	unsigned long cache_max;
	typedef std::list<Cache *> CacheList;

	CacheList cache;
};

#endif // IMAGE_HH

<commit_msg>moved color parsing to Color.cc<commit_after>// Image.hh for Fluxbox Window Manager
// Copyright (c) 2001 - 2002 Henrik Kinnunen (fluxbox@linuxmail.org)
//
// Image.hh for Blackbox - an X11 Window manager
// Copyright (c) 1997 - 2000 Brad Hughes (bhughes@tcac.net)
//
// 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.

// $Id: Image.hh,v 1.12 2002/09/14 13:50:38 fluxgen Exp $

#ifndef	 IMAGE_HH
#define	 IMAGE_HH

#include "Timer.hh"
#include "BaseDisplay.hh"
#include "Color.hh"
#include "Texture.hh"

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <list>

class BImageControl;

/**
	Renders to pixmap
*/
class BImage {
public:
	BImage(BImageControl *ic, unsigned int, unsigned int);
	~BImage();
	/// render to pixmap
	Pixmap render(const FbTk::Texture *src_texture);
	/// render solid texture to pixmap
	Pixmap renderSolid(const FbTk::Texture *src_texture);
	/// render gradient texture to pixmap
	Pixmap renderGradient(const FbTk::Texture *src_texture);

protected:
	/**
		Render to pixmap
		@return rendered pixmap
	*/
	Pixmap renderPixmap();
	/**
		Render to XImage
		@returns allocated and rendered XImage, user is responsible to deallocate
	*/
	XImage *renderXImage();
	/**
		@name render functions
	*/
	//@{
	void invert();
	void bevel1();
	void bevel2();
	void dgradient();
	void egradient();
	void hgradient();
	void pgradient();
	void rgradient();
	void vgradient();
	void cdgradient();
	void pcgradient();
	//@}

private:
	BImageControl *control;

#ifdef		INTERLACE
	bool interlaced;
#endif // INTERLACE

	XColor *colors; // color table

	const FbTk::Color *from, *to;
	int red_offset, green_offset, blue_offset, red_bits, green_bits, blue_bits,
		ncolors, cpc, cpccpc;
	unsigned char *red, *green, *blue, *red_table, *green_table, *blue_table;
	unsigned int width, height, *xtable, *ytable;
};

/**
	Holds screen info and color tables
*/
class BImageControl : public TimeoutHandler {
public:
	BImageControl(BaseDisplay *disp, ScreenInfo *screen, bool = False, int = 4,
		unsigned long = 300000l, unsigned long = 200l);
	virtual ~BImageControl();

	inline BaseDisplay *baseDisplay() { return basedisplay; }

	inline bool doDither() { return dither; }
	inline const Colormap &colormap() const { return m_colormap; }
	inline const ScreenInfo *getScreenInfo() const { return screeninfo; }
	inline Window drawable() const { return window; }

	/// @return visual of screen
	inline Visual *visual() { return screeninfo->getVisual(); }
	/// @return Bits per pixel of screen
	inline int bitsPerPixel() const { return bits_per_pixel; }
	/// @return depth of screen
	inline int depth() const { return screen_depth; }
	inline int colorsPerChannel() const	{ return colors_per_channel; }

	unsigned long color(const char *colorname);
	unsigned long color(const char *, unsigned char *, unsigned char *,
												 unsigned char *);
	unsigned long getSqrt(unsigned int val);
	/**
		Render to pixmap
		@param width width of pixmap
		@param height height of pixmap
		@param src_texture texture type to render
		@return pixmap of the rendered image, on failure None
	*/
	Pixmap renderImage(unsigned int width, unsigned int height,
		const FbTk::Texture *src_texture);

	void installRootColormap();
	void removeImage(Pixmap thepix);
	void colorTables(unsigned char **, unsigned char **, unsigned char **,
			int *, int *, int *, int *, int *, int *);
	void getXColorTable(XColor **, int *);
	void getGradientBuffers(unsigned int, unsigned int,
			unsigned int **, unsigned int **);
	void setDither(bool d) { dither = d; }
	void setColorsPerChannel(int cpc);
	void parseTexture(FbTk::Texture *ret_texture, const char *sval);

	virtual void timeout();

protected:
	/**
		Search cache for a specific pixmap
		@return None if no cache was found
	*/
	Pixmap searchCache(unsigned int width, unsigned int height, unsigned long texture_type,
		const FbTk::Color &color, const FbTk::Color &color_to);

private:
	bool dither;
	BaseDisplay *basedisplay;
	ScreenInfo *screeninfo;
#ifdef		TIMEDCACHE
	BTimer timer;
#endif // TIMEDCACHE

	Colormap m_colormap;

	Window window;
	XColor *colors; ///< color table

	int colors_per_channel, ncolors, screen_number, screen_depth,
		bits_per_pixel, red_offset, green_offset, blue_offset,
		red_bits, green_bits, blue_bits;

	unsigned char red_color_table[256], green_color_table[256],
		blue_color_table[256];
	unsigned int *grad_xbuffer, *grad_ybuffer, grad_buffer_width,
		grad_buffer_height;

	static unsigned long *sqrt_table; /// sqrt lookup table

	typedef struct Cache {
		Pixmap pixmap;

		unsigned int count, width, height;
		unsigned long pixel1, pixel2, texture;
	} Cache;

	unsigned long cache_max;
	typedef std::list<Cache *> CacheList;

	CacheList cache;
};

#endif // IMAGE_HH

<|endoftext|>


<commit_before>#include "LICM.h"
#include "ExprUsesVar.h"
#include "IREquality.h"
#include "IRMutator.h"
#include "IROperator.h"
#include "Scope.h"

namespace Halide {
namespace Internal {

using std::string;
using std::map;
using std::vector;
using std::pair;

// Is it safe to lift an Expr out of a loop (and potentially across a device boundary)
class CanLift : public IRVisitor {
    using IRVisitor::visit;

    void visit(const Call *op) {
        if (!op->is_pure()) {
            result = false;
        } else {
            IRVisitor::visit(op);
        }
    }

    void visit(const Load *op) {
        result = false;
    }

    void visit(const Variable *op) {
        if (varying.contains(op->name)) {
            result = false;
        }
    }

    const Scope<int> &varying;

public:
    bool result {true};

    CanLift(const Scope<int> &v) : varying(v) {}
};

// Lift pure loop invariants to the top level. Applied independently
// to each loop.
class LiftLoopInvariants : public IRMutator {
    using IRMutator::visit;

    Scope<int> varying;

    bool can_lift(const Expr &e) {
        CanLift check(varying);
        e.accept(&check);
        return check.result;
    }

    bool should_lift(const Expr &e) {
        if (!can_lift(e)) return false;
        if (e.as<Variable>()) return false;
        if (e.as<Broadcast>()) return false;
        if (is_const(e)) return false;
        // bool vectors are buggy enough in LLVM that lifting them is a bad idea.
        // (We just skip all vectors on the principle that we don't want them
        // on the stack anyway.)
        if (e.type().is_vector()) return false;
        return true;
    }

    void visit(const Let *op) {
        varying.push(op->name, 0);
        IRMutator::visit(op);
        varying.pop(op->name);
    }

    void visit(const LetStmt *op) {
        varying.push(op->name, 0);
        IRMutator::visit(op);
        varying.pop(op->name);
    }

    void visit(const For *op) {
        varying.push(op->name, 0);
        IRMutator::visit(op);
        varying.pop(op->name);
    }

public:

    using IRMutator::mutate;

    Expr mutate(const Expr &e) {
        if (should_lift(e)) {
            auto it = lifted.find(e);
            if (it == lifted.end()) {
                string name = unique_name('t');
                lifted[e] = name;
                return Variable::make(e.type(), name);
            } else {
                return Variable::make(e.type(), it->second);
            }
        } else {
            return IRMutator::mutate(e);
        }
    }

    map<Expr, string, IRDeepCompare> lifted;
};

class LICM : public IRMutator {
    using IRVisitor::visit;

    bool in_gpu_loop {false};

    void visit(const For *op) {
        bool old_in_gpu_loop = in_gpu_loop;
        in_gpu_loop =
            (op->for_type == ForType::GPUBlock ||
             op->for_type == ForType::GPUThread);

        if (old_in_gpu_loop && in_gpu_loop) {
            // Don't lift lets to in-between gpu blocks/threads
            IRMutator::visit(op);
        } else if (op->device_api == DeviceAPI::GLSL ||
                   op->device_api == DeviceAPI::OpenGLCompute) {
            // Don't lift anything out of OpenGL loops
            IRMutator::visit(op);
        } else {

            // Lift invariants
            LiftLoopInvariants lifter;
            Stmt new_stmt = lifter.mutate(op);

            // Recurse
            const For *loop = new_stmt.as<For>();
            internal_assert(loop);

            new_stmt = For::make(loop->name, loop->min, loop->extent,
                                 loop->for_type, loop->device_api, mutate(loop->body));

            // Wrap lets for the lifted invariants
            for (const auto &p : lifter.lifted) {
                new_stmt = LetStmt::make(p.second, p.first, new_stmt);
            }

            stmt = new_stmt;
        }

        in_gpu_loop = old_in_gpu_loop;
    }
};

// Reassociate summations to group together the loop invariants. Useful to run before LICM.
class GroupLoopInvariants : public IRMutator {
    using IRMutator::visit;

    Scope<int> var_depth;

    class ExprDepth : public IRVisitor {
        using IRVisitor::visit;
        const Scope<int> &depth;

        void visit(const Variable *op) {
            if (depth.contains(op->name)) {
                result = std::max(result, depth.get(op->name));
            }
        }
    public:
        int result = -1;
        ExprDepth(const Scope<int> &var_depth) : depth(var_depth) {}
    };

    int expr_depth(const Expr &e) {
        ExprDepth depth(var_depth);
        e.accept(&depth);
        return depth.result;
    }

    struct Term {
        Expr expr;
        bool positive;
        int depth;
    };

    vector<Term> extract_summation(Expr e) {
        vector<Term> pending, terms;
        pending.push_back({e, true, 0});
        while (!pending.empty()) {
            Term next = pending.back();
            pending.pop_back();
            const Add *add = next.expr.as<Add>();
            const Sub *sub = next.expr.as<Sub>();
            if (add) {
                pending.push_back({add->a, next.positive, 0});
                pending.push_back({add->b, next.positive, 0});
            } else if (sub) {
                pending.push_back({sub->a, next.positive, 0});
                pending.push_back({sub->b, !next.positive, 0});
            } else {
                next.expr = mutate(next.expr);
                if (next.expr.as<Add>() || next.expr.as<Sub>()) {
                    // After mutation it became an add or sub, throw it back on the pending queue.
                    pending.push_back(next);
                } else {
                    next.depth = expr_depth(next.expr);
                    terms.push_back(next);
                }
            }
        }

        // Sort the terms by loop depth
        std::sort(terms.begin(), terms.end(),
                  [](const Term &a, const Term &b) {
                      return a.depth > b.depth;
                  });

        return terms;
    }

    Expr reassociate_summation(Expr e) {

        vector<Term> terms = extract_summation(e);

        Expr result;
        while (!terms.empty()) {
            Term next = terms.back();
            terms.pop_back();
            if (result.defined()) {
                if (next.positive) {
                    result += next.expr;
                } else {
                    result -= next.expr;
                }
            } else if (next.positive) {
                result = next.expr;
            } else {
                result = make_zero(next.expr.type()) - next.expr;
            }
        }

        return result;
    }

    void visit(const Sub *op) {
        expr = reassociate_summation(op);
    }

    void visit(const Add *op) {
        expr = reassociate_summation(op);
    }

    int depth = 0;

    void visit(const For *op) {
        depth++;
        var_depth.push(op->name, depth);
        IRMutator::visit(op);
        var_depth.pop(op->name);
        depth--;
    }

    void visit(const Let *op) {
        var_depth.push(op->name, expr_depth(op->value));
        IRMutator::visit(op);
        var_depth.pop(op->name);
    }

    void visit(const LetStmt *op) {
        var_depth.push(op->name, expr_depth(op->value));
        IRMutator::visit(op);
        var_depth.pop(op->name);
    }
};

// Turn for loops of size one into let statements
Stmt loop_invariant_code_motion(Stmt s) {
    s = GroupLoopInvariants().mutate(s);
    s = LICM().mutate(s);
    return s;
}

}
}
<commit_msg>Leave constants in<commit_after>#include "LICM.h"
#include "CSE.h"
#include "ExprUsesVar.h"
#include "IREquality.h"
#include "IRMutator.h"
#include "IROperator.h"
#include "Scope.h"

namespace Halide {
namespace Internal {

using std::string;
using std::map;
using std::vector;
using std::pair;

// Is it safe to lift an Expr out of a loop (and potentially across a device boundary)
class CanLift : public IRVisitor {
    using IRVisitor::visit;

    void visit(const Call *op) {
        if (!op->is_pure()) {
            result = false;
        } else {
            IRVisitor::visit(op);
        }
    }

    void visit(const Load *op) {
        result = false;
    }

    void visit(const Variable *op) {
        if (varying.contains(op->name)) {
            result = false;
        }
    }

    const Scope<int> &varying;

public:
    bool result {true};

    CanLift(const Scope<int> &v) : varying(v) {}
};

// Lift pure loop invariants to the top level. Applied independently
// to each loop.
class LiftLoopInvariants : public IRMutator {
    using IRMutator::visit;

    Scope<int> varying;

    bool can_lift(const Expr &e) {
        CanLift check(varying);
        e.accept(&check);
        return check.result;
    }

    bool should_lift(const Expr &e) {
        if (!can_lift(e)) return false;
        if (e.as<Variable>()) return false;
        if (e.as<Broadcast>()) return false;
        if (is_const(e)) return false;
        // bool vectors are buggy enough in LLVM that lifting them is a bad idea.
        // (We just skip all vectors on the principle that we don't want them
        // on the stack anyway.)
        if (e.type().is_vector()) return false;
        return true;
    }

    void visit(const Let *op) {
        varying.push(op->name, 0);
        IRMutator::visit(op);
        varying.pop(op->name);
    }

    void visit(const LetStmt *op) {
        varying.push(op->name, 0);
        IRMutator::visit(op);
        varying.pop(op->name);
    }

    void visit(const For *op) {
        varying.push(op->name, 0);
        IRMutator::visit(op);
        varying.pop(op->name);
    }

public:

    using IRMutator::mutate;

    Expr mutate(const Expr &e) {
        if (should_lift(e)) {
            auto it = lifted.find(e);
            if (it == lifted.end()) {
                string name = unique_name('t');
                lifted[e] = name;
                return Variable::make(e.type(), name);
            } else {
                return Variable::make(e.type(), it->second);
            }
        } else {
            return IRMutator::mutate(e);
        }
    }

    map<Expr, string, IRDeepCompare> lifted;
};

class LICM : public IRMutator {
    using IRVisitor::visit;

    bool in_gpu_loop {false};

    void visit(const For *op) {
        bool old_in_gpu_loop = in_gpu_loop;
        in_gpu_loop =
            (op->for_type == ForType::GPUBlock ||
             op->for_type == ForType::GPUThread);

        if (old_in_gpu_loop && in_gpu_loop) {
            // Don't lift lets to in-between gpu blocks/threads
            IRMutator::visit(op);
        } else if (op->device_api == DeviceAPI::GLSL ||
                   op->device_api == DeviceAPI::OpenGLCompute) {
            // Don't lift anything out of OpenGL loops
            IRMutator::visit(op);
        } else {

            // Lift invariants
            LiftLoopInvariants lifter;
            Stmt new_stmt = lifter.mutate(op);

            // Recurse
            const For *loop = new_stmt.as<For>();
            internal_assert(loop);

            new_stmt = For::make(loop->name, loop->min, loop->extent,
                                 loop->for_type, loop->device_api, mutate(loop->body));

            // Wrap lets for the lifted invariants
            for (const auto &p : lifter.lifted) {
                new_stmt = LetStmt::make(p.second, p.first, new_stmt);
            }

            stmt = new_stmt;
        }

        in_gpu_loop = old_in_gpu_loop;
    }
};

// Reassociate summations to group together the loop invariants. Useful to run before LICM.
class GroupLoopInvariants : public IRMutator {
    using IRMutator::visit;

    Scope<int> var_depth;

    class ExprDepth : public IRVisitor {
        using IRVisitor::visit;
        const Scope<int> &depth;

        void visit(const Variable *op) {
            if (depth.contains(op->name)) {
                result = std::max(result, depth.get(op->name));
            }
        }
    public:
        int result = 0;
        ExprDepth(const Scope<int> &var_depth) : depth(var_depth) {}
    };

    int expr_depth(const Expr &e) {
        if (is_const(e)) return 0x7fffffff;
        ExprDepth depth(var_depth);
        e.accept(&depth);
        return depth.result;
    }

    struct Term {
        Expr expr;
        bool positive;
        int depth;
    };

    vector<Term> extract_summation(Expr e) {
        vector<Term> pending, terms;
        pending.push_back({e, true, 0});
        while (!pending.empty()) {
            Term next = pending.back();
            pending.pop_back();
            const Add *add = next.expr.as<Add>();
            const Sub *sub = next.expr.as<Sub>();
            if (add) {
                pending.push_back({add->a, next.positive, 0});
                pending.push_back({add->b, next.positive, 0});
            } else if (sub) {
                pending.push_back({sub->a, next.positive, 0});
                pending.push_back({sub->b, !next.positive, 0});
            } else {
                next.expr = mutate(next.expr);
                if (next.expr.as<Add>() || next.expr.as<Sub>()) {
                    // After mutation it became an add or sub, throw it back on the pending queue.
                    pending.push_back(next);
                } else {
                    next.depth = expr_depth(next.expr);
                    terms.push_back(next);
                }
            }
        }

        // Sort the terms by loop depth
        std::sort(terms.begin(), terms.end(),
                  [](const Term &a, const Term &b) {
                      return a.depth > b.depth;
                  });

        return terms;
    }

    Expr reassociate_summation(Expr e) {

        vector<Term> terms = extract_summation(e);

        Expr result;
        bool positive = true;
        while (!terms.empty()) {
            Term next = terms.back();
            terms.pop_back();
            if (result.defined()) {
                if (next.positive == positive) {
                    result += next.expr;
                } else if (next.positive) {
                    result = next.expr - result;
                    positive = true;
                } else {
                    result -= next.expr;
                }
            } else {
                result = next.expr;
                positive = next.positive;
            }
        }

        if (!positive) {
            result = make_zero(result.type()) - result;
        }

        return result;
    }

    void visit(const Sub *op) {
        expr = reassociate_summation(op);
    }

    void visit(const Add *op) {
        expr = reassociate_summation(op);
    }

    int depth = 0;

    void visit(const For *op) {
        depth++;
        var_depth.push(op->name, depth);
        IRMutator::visit(op);
        var_depth.pop(op->name);
        depth--;
    }

    void visit(const Let *op) {
        var_depth.push(op->name, expr_depth(op->value));
        IRMutator::visit(op);
        var_depth.pop(op->name);
    }

    void visit(const LetStmt *op) {
        var_depth.push(op->name, expr_depth(op->value));
        IRMutator::visit(op);
        var_depth.pop(op->name);
    }
};

// Turn for loops of size one into let statements
Stmt loop_invariant_code_motion(Stmt s) {
    s = GroupLoopInvariants().mutate(s);
    s = common_subexpression_elimination(s);
    s = LICM().mutate(s);
    return s;
}

}
}
<|endoftext|>


<commit_before>#include <algorithm>
#include <string>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <tesseract/baseapi.h>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>

#include "imagereconstruct.hpp"

#define SMOKETEST 0

using namespace std;
using namespace cv;
namespace fs = boost::filesystem;

Mat sourceImage, finalImage, histImage, tmp;
Mat hist;

void createHistogram(Mat& src) {
    int histSize = 256;
    float range[] = { 0, 256 };
    const float *ranges[] = { range };
    calcHist(&src, 1, 0, Mat(), hist, 1, &histSize, ranges, true, false);

    // Let's draw our histogram
    int histHeight = 512;
    int histWidth = 512;
    int widthBucket = cvRound((double) histWidth/histSize);

    histImage = Mat(histHeight, histWidth, CV_32FC3, Scalar(0));
    normalize(hist, hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());

    for(int i = 1; i < histSize; i++)
    {
        line(histImage, Point(widthBucket * (i - 1), histHeight - cvRound(hist.at<float>(i - 1))) ,
             Point(widthBucket * i, histHeight - cvRound(hist.at<float>(i))),
             Scalar(255, 255, 255), 1);
    }
}

int* horizontalSegments(Mat& src) {
    int* seg = (int*) calloc(src.cols, sizeof(int));

    for(int i = 0; i < src.cols; i++) {
        for(int k = 0; k < src.rows; k++) {
            uchar pixel = src.data[src.cols * k + i];

            if(pixel)
                seg[i]++;
        }
    }

    return seg;
}

Mat drawHorizontalSegments(int* seg, int rows, int cols) {
    Mat segImage = Mat(rows, cols, CV_8U, Scalar(0));

    for(int i = 0; i < cols; i++) {
        if(seg[i] > 0)
            line(segImage, Point(i, rows - 1), Point(i, rows - 1 - seg[i]), Scalar(255), 1);
    }

    return segImage;
}

int* verticalSegments(Mat& src) {
    int* seg = (int*) calloc(src.rows, sizeof(int));

    for(int i = 0; i < src.rows; i++) {
        for(int k = 0; k < src.cols; k++) {
            uchar pixel = src.data[src.cols * i + k];

            if(pixel)
                seg[i]++;
        }
    }

    return seg;
}

Mat drawVerticalSegments(int* seg, int rows, int cols) {
    Mat segImage = Mat(rows, cols, CV_8U, Scalar(0));

    for(int i = 0; i < rows; i++) {
        if(seg[i] > 0)
            line(segImage, Point(0, i), Point(seg[i], i), Scalar(255), 1);
    }

    return segImage;
}

vector<pair<int, int> > createSegmentPairs(int* seg, int segSize) {
    int top = 0, bottom = 0;
    bool in = false;

    vector<pair<int, int> > pairs;

    for(int i = 0; i < segSize; i++) {
        if(seg[i])
            in = true;
        else
            in = false;

        if(in) {
            if(!top) {
                top = i;
                bottom = i;
            } else {
                bottom = i;
            }

            // corner case
            if(i == segSize - 1) {
                pairs.push_back(make_pair(top, bottom));
                top = bottom = 0;
            }
        } else {
            if(top && bottom) {
                pairs.push_back(make_pair(top, bottom));
                top = bottom = 0;
            }
        }
    }

    return pairs;
}

vector<pair<int, int> > filterVerticalPairs(vector<pair<int, int> > verticalPairs) {
    vector<pair<int, int> > new_pairs;

    int biggest = 0, index = 0;

    for(int i = 0; i < verticalPairs.size(); i++) {
        int current = verticalPairs[i].second - verticalPairs[i].first;

        if(current > biggest) {
            index = i;
        }
    }

    new_pairs.push_back(make_pair(verticalPairs[index].first, verticalPairs[index].second));

    return new_pairs;
}

vector<pair<int, int> > filterHorizontalPairs(vector<pair<int, int> > horizontalPairs, int segSize) {
    int MAGIC_DIFF = 10;
    int MAGIC_SIZE = 10;

    vector<pair<int, int> > new_pairs;

    int* seg = (int*) calloc(segSize, sizeof(int));

    for(int i = 0; i < horizontalPairs.size(); i++) {
        int size = horizontalPairs[i].second - horizontalPairs[i].first;

        // Too small
        if(size < MAGIC_SIZE) {
            // Check right side
            if(i < horizontalPairs.size() - 1 && horizontalPairs.size() > 1) {
                if(horizontalPairs[i + 1].first - horizontalPairs[i].second < MAGIC_DIFF) {
                    for(int k = horizontalPairs[i].first; k <= horizontalPairs[i + 1].second; k++)
                        seg[k] = 1;
                }
                // Check left side
            } else if(i > 0 && horizontalPairs.size() > 1) {
                if(horizontalPairs[i].first - horizontalPairs[i - 1].second < MAGIC_DIFF) {
                    for(int k = horizontalPairs[i - 1].first; k <= horizontalPairs[i].second; k++)
                        seg[k] = 1;
                }
            }
            // This one is large enough
        } else {
            for(int k = horizontalPairs[i].first; k <= horizontalPairs[i].second; k++)
                seg[k] = 1;
        }
    }

    return createSegmentPairs(seg, segSize);
}

int main(int argc, char** argv) {
    const int RESIZE_FACTOR = 2;
    const string DATA_PATH = "/Users/Mike/Documents/Eclipse Workspace/SCB3/data/";

    int total = 0;

    fs::path folder(DATA_PATH);

    if(!exists(folder))
        return -1;

    fs::directory_iterator endItr;
    for(fs::directory_iterator itr(folder); itr != endItr; itr++) {
        string fullPath = itr->path().string();
        string fileName = itr->path().filename().string();

        // Skip all dot files
        if(fileName[0] == '.')
            continue;

        // Retrieve captcha string
        string captchaCode = boost::replace_all_copy(fileName, ".png", "");
        boost::replace_all(captchaCode, "at", "@");
        boost::replace_all(captchaCode, "pct", "%");
        boost::replace_all(captchaCode, "and", "&");

        total++;
        cout << total << ".) file: " << fileName << ", code: " << captchaCode << endl;

        // Load our base image
        sourceImage = imread(fullPath, CV_LOAD_IMAGE_GRAYSCALE);

        // Is it loaded?
        if(!sourceImage.data)
            return -1;

        // Resize the image 2x
        resize(sourceImage, sourceImage, Size(sourceImage.cols * RESIZE_FACTOR, sourceImage.rows * RESIZE_FACTOR));

        // Define our final image
        finalImage = sourceImage.clone();

        // Apply adaptive threshold
        adaptiveThreshold(finalImage, finalImage, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 3, 1);

        // Use the thresholded image as a mask
        sourceImage.copyTo(tmp, finalImage);
        tmp.copyTo(finalImage);

        // Normalize new image
        normalize(finalImage, finalImage, 0, 255, NORM_MINMAX, CV_8U);

        // Let's calculate histogram for our image
        createHistogram(finalImage);

        // Get lower bound of our threshold value
        int thresholdValueLow = 0;
        for(int i = 0; i < 256; i++) {
            if(cvRound(hist.at<float>(i)) > 4) {
                thresholdValueLow = i;
            }
        }

        // Calculate final threshold value
        int thresholdValue = thresholdValueLow + (int)((255 - thresholdValueLow) / 10 * 4);

        // Apply threshold
        threshold(finalImage, finalImage, thresholdValue, 255, THRESH_BINARY);

        // Apply dilation and erosion
        Mat element = getStructuringElement(MORPH_ELLIPSE, Size(5, 5));
        dilate(finalImage, finalImage, element);
        erode(finalImage, finalImage, element);

        // Segments
        int* segH = horizontalSegments(finalImage);
        int* segV = verticalSegments(finalImage);

        Mat segHImage = drawHorizontalSegments(segH, finalImage.rows, finalImage.cols);
        Mat segVImage = drawVerticalSegments(segV, finalImage.rows, finalImage.cols);

        // Let's draw the rectangles
        vector<pair<int, int> > verticalPairs = filterVerticalPairs(createSegmentPairs(segV, finalImage.rows));
        vector<pair<int, int> > horizontalPairs = filterHorizontalPairs(createSegmentPairs(segH, finalImage.cols), finalImage.cols);

        for(vector<pair<int, int> >::iterator itV = verticalPairs.begin(); itV != verticalPairs.end(); itV++) {
            for(vector<pair<int, int> >::iterator itH = horizontalPairs.begin(); itH != horizontalPairs.end(); itH++) {
                rectangle(finalImage, Point(itH->first, itV->first), Point(itH->second, itV->second), Scalar(255));
            }
        }

        imshow("Final image", finalImage);
        //        imshow("HSeg", segHImage);
        //        imshow("VSeg", segVImage);
        imshow("Histogram", histImage);
        waitKey();

        sourceImage.release();
        finalImage.release();
        tmp.release();
#if SMOKETEST == 0
        if(total == 10) break;
#endif
    }

    return 0;
}
<commit_msg>Fine-tuned merging. Added splitting and shrinking of segments.<commit_after>#include <algorithm>
#include <string>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <tesseract/baseapi.h>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>

#include "imagereconstruct.hpp"

#define SMOKETEST 0

using namespace std;
using namespace cv;
namespace fs = boost::filesystem;

Mat sourceImage, finalImage, histImage, tmp;
Mat hist;

struct Square {
    int x;
    int y;
    int width;
    int height;
};

void createHistogram(Mat& src) {
    int histSize = 256;
    float range[] = { 0, 256 };
    const float *ranges[] = { range };
    calcHist(&src, 1, 0, Mat(), hist, 1, &histSize, ranges, true, false);

    // Let's draw our histogram
    int histHeight = 512;
    int histWidth = 512;
    int widthBucket = cvRound((double) histWidth/histSize);

    histImage = Mat(histHeight, histWidth, CV_32FC3, Scalar(0));
    normalize(hist, hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());

    for(int i = 1; i < histSize; i++)
    {
        line(histImage, Point(widthBucket * (i - 1), histHeight - cvRound(hist.at<float>(i - 1))) ,
             Point(widthBucket * i, histHeight - cvRound(hist.at<float>(i))),
             Scalar(255, 255, 255), 1);
    }
}

int* horizontalSegments(Mat& src) {
    int* seg = (int*) calloc(src.cols, sizeof(int));

    for(int i = 0; i < src.cols; i++) {
        for(int k = 0; k < src.rows; k++) {
            uchar pixel = src.data[src.cols * k + i];

            if(pixel)
                seg[i]++;
        }
    }

    return seg;
}

Mat drawHorizontalSegments(int* seg, int rows, int cols) {
    Mat segImage = Mat(rows, cols, CV_8U, Scalar(0));

    for(int i = 0; i < cols; i++) {
        if(seg[i] > 0)
            line(segImage, Point(i, rows - 1), Point(i, rows - 1 - seg[i]), Scalar(255), 1);
    }

    return segImage;
}

int* verticalSegments(Mat& src) {
    int* seg = (int*) calloc(src.rows, sizeof(int));

    for(int i = 0; i < src.rows; i++) {
        for(int k = 0; k < src.cols; k++) {
            uchar pixel = src.data[src.cols * i + k];

            if(pixel)
                seg[i]++;
        }
    }

    return seg;
}

Mat drawVerticalSegments(int* seg, int rows, int cols) {
    Mat segImage = Mat(rows, cols, CV_8U, Scalar(0));

    for(int i = 0; i < rows; i++) {
        if(seg[i] > 0)
            line(segImage, Point(0, i), Point(seg[i], i), Scalar(255), 1);
    }

    return segImage;
}

vector<pair<int, int> > createSegmentPairs(int* seg, int segSize) {
    int top = 0, bottom = 0;
    bool in = false;

    vector<pair<int, int> > pairs;

    for(int i = 0; i < segSize; i++) {
        if(seg[i])
            in = true;
        else
            in = false;

        if(in) {
            if(!top) {
                top = i;
                bottom = i;
            } else {
                bottom = i;
            }

            // corner case
            if(i == segSize - 1) {
                pairs.push_back(make_pair(top, bottom));
                top = bottom = 0;
            }
        } else {
            if(top && bottom) {
                pairs.push_back(make_pair(top, bottom));
                top = bottom = 0;
            }
        }
    }

    return pairs;
}

vector<pair<int, int> > filterVerticalPairs(vector<pair<int, int> > verticalPairs) {
    vector<pair<int, int> > new_pairs;

    int biggest = 0, index = 0;

    for(int i = 0; i < verticalPairs.size(); i++) {
        int current = verticalPairs[i].second - verticalPairs[i].first;

        if(current > biggest) {
            index = i;
            biggest = current;
        }
    }

    new_pairs.push_back(make_pair(verticalPairs[index].first, verticalPairs[index].second));

    return new_pairs;
}

vector<pair<int, int> > filterHorizontalPairs(vector<pair<int, int> > horizontalPairs, int segSize) {
    int MAGIC_DIFF = 10;
    int MAGIC_SIZE = 12;

    vector<pair<int, int> > new_pairs;

    int* seg = (int*) calloc(segSize, sizeof(int));

    for(int i = 0; i < horizontalPairs.size(); i++) {
        int size = horizontalPairs[i].second - horizontalPairs[i].first;

        // Too small
        if(size < MAGIC_SIZE) {
            // Check right side
            if(i < horizontalPairs.size() - 1 && horizontalPairs.size() > 1) {
                if(horizontalPairs[i + 1].first - horizontalPairs[i].second < MAGIC_DIFF) {
                    for(int k = horizontalPairs[i].first; k <= horizontalPairs[i + 1].second; k++)
                        seg[k] = 1;
                }
            }

            // Check left side
            if(i > 0 && horizontalPairs.size() > 1) {
                if(horizontalPairs[i].first - horizontalPairs[i - 1].second < MAGIC_DIFF) {
                    for(int k = horizontalPairs[i - 1].first; k <= horizontalPairs[i].second; k++)
                        seg[k] = 1;
                }
            }
        // This one is large enough
        } else {
            for(int k = horizontalPairs[i].first; k <= horizontalPairs[i].second; k++)
                seg[k] = 1;
        }
    }

    return createSegmentPairs(seg, segSize);
}

vector<pair<int, int> > splitLarge(vector<pair<int, int> > horizontalSegments) {
    int MAGIC_SIZE = 50;

    vector<pair<int, int> > new_pairs;

    for(int i = 0; i < horizontalSegments.size(); i++) {
        int size = horizontalSegments[i].second - horizontalSegments[i].first;

        if(size > MAGIC_SIZE) {
            int f1 = horizontalSegments[i].first;
            int s1 = (int)((horizontalSegments[i].second - horizontalSegments[i].first) / 2) + horizontalSegments[i].first;
            int f2 = (int)((horizontalSegments[i].second - horizontalSegments[i].first) / 2) + horizontalSegments[i].first + 2;
            int s2 = horizontalSegments[i].second;

            new_pairs.push_back(make_pair(f1, s1));
            new_pairs.push_back(make_pair(f2, s2));
        } else {
            new_pairs.push_back(horizontalSegments[i]);
        }
    }

    return new_pairs;
}

void drawSegmentRectangles(Mat& image, vector<pair<int, int> > verticalPairs, vector<pair<int, int> > horizontalPairs) {
    for(vector<pair<int, int> >::iterator itV = verticalPairs.begin(); itV != verticalPairs.end(); itV++) {
        for(vector<pair<int, int> >::iterator itH = horizontalPairs.begin(); itH != horizontalPairs.end(); itH++) {
            rectangle(image, Point(itH->first, itV->first), Point(itH->second, itV->second), Scalar(255));
        }
    }
}

vector<Square> getSquares(vector<pair<int, int> > verticalPairs, vector<pair<int, int> > horizontalPairs) {
    vector<Square> squares;

    for(vector<pair<int, int> >::iterator itV = verticalPairs.begin(); itV != verticalPairs.end(); itV++) {
        for(vector<pair<int, int> >::iterator itH = horizontalPairs.begin(); itH != horizontalPairs.end(); itH++) {
            squares.push_back({ itH->first, itV->first, itH->second - itH->first, itV->second - itV->first });
        }
    }

    return squares;
}

// image must be a binary image
vector<Square> shrinkSquares(Mat& image, vector<Square> squares) {
    vector<Square> new_squares;

    for(int i = 0; i < squares.size(); i++) {
        int top = -1, bottom = 0, left = 9999, right = -1;
        Mat tmp2 = image(Rect(squares[i].x, squares[i].y, squares[i].width, squares[i].height));
        Mat tmp = tmp2.clone();

        for(int y = 0; y < tmp.rows; y++) {
            for(int x = 0; x < tmp.cols; x++) {
                int pixel = tmp.data[x + y * tmp.cols];

                if(pixel) {
                    tmp.data[x + y * tmp.cols] = 127;
                    if(top == -1) top = y; // store the lowest value
                    if(left > x) left = x;
                    bottom = y; // y will be always incremented, we just store the highest value
                    if(right < x) right = x;
                }
            }
        }

        top -= 1;
        left -= 1;
        bottom += 1;
        right += 1;

        new_squares.push_back({ squares[i].x + left, squares[i].y + top, right - left, bottom - top });
        tmp.release();
        tmp2.release();
    }

    return new_squares;
}

bool compareSquares(Square a, Square b) {
    return a.width * a.height > b.width * b.height;
}

vector<Square> takeSquares(vector<Square> squares, int number) {
    vector<Square> new_squares;

    sort(squares.begin(), squares.end(), compareSquares);
    int min = MIN(number, (int)squares.size());

    for(int i = 0; i < min; i++) {
        new_squares.push_back(squares[i]);
    }

    return new_squares;
}

void drawSquares(Mat& image, vector<Square> squares) {
    for(int i = 0; i < squares.size(); i++)
        rectangle(image, Point(squares[i].x, squares[i].y), Point(squares[i].x + squares[i].width, squares[i].y + squares[i].height), Scalar(255));
}

int main(int argc, char** argv) {
    const int RESIZE_FACTOR = 2;
    const string DATA_PATH = "/Users/Mike/Documents/Eclipse Workspace/SCB3/data/";

    int total = 0;

    fs::path folder(DATA_PATH);

    if(!exists(folder))
        return -1;

    fs::directory_iterator endItr;
    for(fs::directory_iterator itr(folder); itr != endItr; itr++) {
        string fullPath = itr->path().string();
        string fileName = itr->path().filename().string();

        // Skip all dot files
        if(fileName[0] == '.')
            continue;

        // Retrieve captcha string
        string captchaCode = boost::replace_all_copy(fileName, ".png", "");
        boost::replace_all(captchaCode, "at", "@");
        boost::replace_all(captchaCode, "pct", "%");
        boost::replace_all(captchaCode, "and", "&");

        total++;
        cout << total << ".) file: " << fileName << ", code: " << captchaCode << endl;

        // Load our base image
        sourceImage = imread(fullPath, CV_LOAD_IMAGE_GRAYSCALE);

        // Is it loaded?
        if(!sourceImage.data)
            return -1;

        // Resize the image 2x
        resize(sourceImage, sourceImage, Size(sourceImage.cols * RESIZE_FACTOR, sourceImage.rows * RESIZE_FACTOR));

        // Define our final image
        finalImage = sourceImage.clone();

        // Apply adaptive threshold
        adaptiveThreshold(finalImage, finalImage, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 3, 1);

        // Use the thresholded image as a mask
        sourceImage.copyTo(tmp, finalImage);
        tmp.copyTo(finalImage);

        // Normalize new image
        normalize(finalImage, finalImage, 0, 255, NORM_MINMAX, CV_8U);

        // Let's calculate histogram for our image
        createHistogram(finalImage);

        // Get lower bound of our threshold value
        int thresholdValueLow = 0;
        for(int i = 0; i < 256; i++) {
            if(cvRound(hist.at<float>(i)) > 4) {
                thresholdValueLow = i;
            }
        }

        // Calculate final threshold value
        int thresholdValue = thresholdValueLow + (int)((255 - thresholdValueLow) / 10 * 4);

        // Apply threshold
        threshold(finalImage, finalImage, thresholdValue, 255, THRESH_BINARY);

        // Apply dilation and erosion
        Mat element = getStructuringElement(MORPH_ELLIPSE, Size(5, 5));
        dilate(finalImage, finalImage, element);
        erode(finalImage, finalImage, element);

        // Segments
        int* segH = horizontalSegments(finalImage);
        int* segV = verticalSegments(finalImage);

        Mat segHImage = drawHorizontalSegments(segH, finalImage.rows, finalImage.cols);
        Mat segVImage = drawVerticalSegments(segV, finalImage.rows, finalImage.cols);

        // Create pairs
        vector<pair<int, int> > verticalPairs = filterVerticalPairs(createSegmentPairs(segV, finalImage.rows));
        vector<pair<int, int> > horizontalPairs = splitLarge(filterHorizontalPairs(createSegmentPairs(segH, finalImage.cols), finalImage.cols));

        // Get segment squares
        vector<Square> squares = takeSquares(shrinkSquares(finalImage, getSquares(verticalPairs, horizontalPairs)), 6);

        // Let's draw the rectangles
        drawSquares(finalImage, squares);
        drawSquares(sourceImage, squares);

        imshow("Final image", finalImage);
        imshow("Source image", sourceImage);
        //        imshow("HSeg", segHImage);
        //        imshow("VSeg", segVImage);
        imshow("Histogram", histImage);
        waitKey();

        sourceImage.release();
        finalImage.release();
        tmp.release();
#if SMOKETEST == 0
        if(total == 10) break;
#endif
    }

    return 0;
}
<|endoftext|>


<commit_before>#include <GL/freeglut.h>
#include <iostream>
#include <thread>
//#include <unistd.h>

#include "sim/Constants.h"
#include "sim/Maze.h"
#include "sim/MazeGraphic.h"
#include "sim/MazeFileUtilities.h"
#include "sim/Mouse.h"
#include "sim/MouseGraphic.h"
#include "sim/MouseInterface.h"
#include "sim/Parameters.h"
#include "sim/Tile.h"
#include "sim/Sleep.h"
#include "algo/Solver.h"

// Function declarations
void draw();
void solve();
void keyInput(unsigned char key, int x, int y);

// Global object variable declarations
Solver* g_solver;
sim::MazeGraphic* g_mazeGraphic;
sim::MouseGraphic* g_mouseGraphic;

// Global primitive variable declarations
static /*non-const*/ bool PAUSED = false; // Initially set to false
static /*non-const*/ int SLEEP_TIME = 150; // ms between simulation steps
static /*non-const*/ bool UNDO_REQUESTED = false; // Whether or not an undo was requested
static /*non-const*/ bool RESET_REQUESTED = false; // Whether or not a reset was requested

int main(int argc, char* argv[]){

    // TODO: read input file, and check size, use this as value instead of parameter

    // Ensure that the size parameters are valid
    if (sim::MAZE_WIDTH < 1 || sim::MAZE_HEIGHT < 1){
        std::cout << "Impossible maze size - check \"src/sim/Parameters.h\"" << std::endl;
        return 0;
    }

    // Initialize local simulation objects
    sim::Maze maze(sim::MAZE_WIDTH, sim::MAZE_HEIGHT, sim::getMazeFileDirPath(argv[0]), sim::MAZE_FILE);
    sim::Mouse mouse(&maze);
    sim::MouseInterface mouseInterface(&mouse, &SLEEP_TIME, &PAUSED, &UNDO_REQUESTED, &RESET_REQUESTED);
    Solver solver(&mouseInterface);

    // Initialize the local graphics objects
    sim::MazeGraphic mazeGraphic(&maze);
    sim::MouseGraphic mouseGraphic(&mouse);

    // Assign global variables
    g_solver = &solver;
    g_mazeGraphic = &mazeGraphic;
    g_mouseGraphic = &mouseGraphic;

    // GLUT Initialization
    glutInit(&argc, argv);
    glutInitWindowSize(sim::WINDOW_WIDTH, sim::WINDOW_HEIGHT);
    glutInitDisplayMode(GLUT_RGBA);
    glutInitWindowPosition(0, 0);
    glutCreateWindow(sim::MAZE_FILE.c_str());
    glClearColor(0.0,0.0,0.0,1.0);
    glClear(GL_COLOR_BUFFER_BIT);
    glutDisplayFunc(draw);
    glutKeyboardFunc(keyInput);

    // Start the solving loop (the name "first" is not important)
    std::thread first(solve);

    // Start the graphics loop (which never terminates)
    glutMainLoop();
}

// Draw method for the GLUT environment
void draw(){
    glClear(GL_COLOR_BUFFER_BIT);
    g_mazeGraphic->draw();
    g_mouseGraphic->draw();
    glFlush();
    sim::sleep(sim::SLEEP_TIME_MIN); // Reduces CPU usage
    glutPostRedisplay();
}

void solve(){
    sim::sleep(250); // Wait for 0.25 seconds for GLUT to intialize
    g_solver->solve();
}

void keyInput(unsigned char key, int x, int y){
    if (key == 32){ // Space bar
        PAUSED = !PAUSED;
    }
    else if (key == 'f' || key == 'F'){ // Faster
        SLEEP_TIME /= 1.15;
        if (SLEEP_TIME < sim::SLEEP_TIME_MIN){
            SLEEP_TIME = sim::SLEEP_TIME_MIN;
        }
    }
    else if (key == 's' || key == 'S'){ // Slower
        SLEEP_TIME *= 1.2;
        if (SLEEP_TIME > sim::SLEEP_TIME_MAX){
            SLEEP_TIME = sim::SLEEP_TIME_MAX;
        }
    }
    else if (key == 'u' || key == 'U'){
        // Undo request - reset the position mouse but retains memory
        UNDO_REQUESTED = true;
    }
    else if (key == 'r' || key == 'R'){
        // Reset requested - reset the position mouse and don't retain memory
        RESET_REQUESTED = true;
    }
    else if (key == 'q' || key == 'Q'){ // Quit
        exit(0);
    }
}
<commit_msg>check if push working<commit_after>#include <GL/freeglut.h>
#include <iostream>
#include <thread>
//#include <unistd.h>

#include "sim/Constants.h"
#include "sim/Maze.h"
#include "sim/MazeGraphic.h"
#include "sim/MazeFileUtilities.h"
#include "sim/Mouse.h"
#include "sim/MouseGraphic.h"
#include "sim/MouseInterface.h"
#include "sim/Parameters.h"
#include "sim/Tile.h"
#include "sim/Sleep.h"
#include "algo/Solver.h"

// Function declarations
void draw();
void solve();
void keyInput(unsigned char key, int x, int y);

// Global object variable declarations
Solver* g_solver;
sim::MazeGraphic* g_mazeGraphic;
sim::MouseGraphic* g_mouseGraphic;

// Global primitive variable declarations
static /*non-const*/ bool PAUSED = false; // Initially set to false
static /*non-const*/ int SLEEP_TIME = 150; // ms between simulation steps
static /*non-const*/ bool UNDO_REQUESTED = false; // Whether or not an undo was requested
static /*non-const*/ bool RESET_REQUESTED = false; // Whether or not a reset was requested
//check
int main(int argc, char* argv[]){

    // TODO: read input file, and check size, use this as value instead of parameter

    // Ensure that the size parameters are valid
    if (sim::MAZE_WIDTH < 1 || sim::MAZE_HEIGHT < 1){
        std::cout << "Impossible maze size - check \"src/sim/Parameters.h\"" << std::endl;
        return 0;
    }

    // Initialize local simulation objects
    sim::Maze maze(sim::MAZE_WIDTH, sim::MAZE_HEIGHT, sim::getMazeFileDirPath(argv[0]), sim::MAZE_FILE);
    sim::Mouse mouse(&maze);
    sim::MouseInterface mouseInterface(&mouse, &SLEEP_TIME, &PAUSED, &UNDO_REQUESTED, &RESET_REQUESTED);
    Solver solver(&mouseInterface);

    // Initialize the local graphics objects
    sim::MazeGraphic mazeGraphic(&maze);
    sim::MouseGraphic mouseGraphic(&mouse);

    // Assign global variables
    g_solver = &solver;
    g_mazeGraphic = &mazeGraphic;
    g_mouseGraphic = &mouseGraphic;

    // GLUT Initialization
    glutInit(&argc, argv);
    glutInitWindowSize(sim::WINDOW_WIDTH, sim::WINDOW_HEIGHT);
    glutInitDisplayMode(GLUT_RGBA);
    glutInitWindowPosition(0, 0);
    glutCreateWindow(sim::MAZE_FILE.c_str());
    glClearColor(0.0,0.0,0.0,1.0);
    glClear(GL_COLOR_BUFFER_BIT);
    glutDisplayFunc(draw);
    glutKeyboardFunc(keyInput);

    // Start the solving loop (the name "first" is not important)
    std::thread first(solve);

    // Start the graphics loop (which never terminates)
    glutMainLoop();
}

// Draw method for the GLUT environment
void draw(){
    glClear(GL_COLOR_BUFFER_BIT);
    g_mazeGraphic->draw();
    g_mouseGraphic->draw();
    glFlush();
    sim::sleep(sim::SLEEP_TIME_MIN); // Reduces CPU usage
    glutPostRedisplay();
}

void solve(){
    sim::sleep(250); // Wait for 0.25 seconds for GLUT to intialize
    g_solver->solve();
}

void keyInput(unsigned char key, int x, int y){
    if (key == 32){ // Space bar
        PAUSED = !PAUSED;
    }
    else if (key == 'f' || key == 'F'){ // Faster
        SLEEP_TIME /= 1.15;
        if (SLEEP_TIME < sim::SLEEP_TIME_MIN){
            SLEEP_TIME = sim::SLEEP_TIME_MIN;
        }
    }
    else if (key == 's' || key == 'S'){ // Slower
        SLEEP_TIME *= 1.2;
        if (SLEEP_TIME > sim::SLEEP_TIME_MAX){
            SLEEP_TIME = sim::SLEEP_TIME_MAX;
        }
    }
    else if (key == 'u' || key == 'U'){
        // Undo request - reset the position mouse but retains memory
        UNDO_REQUESTED = true;
    }
    else if (key == 'r' || key == 'R'){
        // Reset requested - reset the position mouse and don't retain memory
        RESET_REQUESTED = true;
    }
    else if (key == 'q' || key == 'Q'){ // Quit
        exit(0);
    }
}
<|endoftext|>


<commit_before>//
//  Z80.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 14/05/2017.
//  Copyright © 2017 Thomas Harte. All rights reserved.
//

#ifndef Z80_hpp
#define Z80_hpp

#include <cstdint>

#include "../MicroOpScheduler.hpp"
#include "../RegisterSizes.hpp"

namespace CPU {
namespace Z80 {

/*
	The list of registers that can be accessed via @c set_value_of_register and @c set_value_of_register.
*/
enum Register {
	ProgramCounter,
	StackPointer,

	A,		Flags,	AF,
	B,		C,		BC,
	D,		E,		DE,
	H,		L,		HL,

	ADash,		FlagsDash,	AFDash,
	BDash,		CDash,		BCDash,
	DDash,		EDash,		DEDash,
	HDash,		LDash,		HLDash,

	IXh,	IXl,	IX,
	IYh,	IYl,	IY,
	R,		I,
};

/*
	Flags as defined on the Z80; can be used to decode the result of @c get_flags or to form a value for @c set_flags.
*/
enum Flag: uint8_t {
	Sign		= 0x80,
	Zero		= 0x40,
	Bit5		= 0x20,
	HalfCarry	= 0x10,
	Bit3		= 0x08,
	Parity		= 0x04,
	Overflow	= 0x04,
	Subtract	= 0x02,
	Carry		= 0x01
};

/*!
	Subclasses will be given the task of performing bus operations, allowing them to provide whatever interface they like
	between a Z80 and the rest of the system. @c BusOperation lists the types of bus operation that may be requested.

	@c None is reserved for internal use. It will never be requested from a subclass.
*/
enum BusOperation {
	ReadOpcode,
	Read, Write,
	Input, Output,
	Interrupt,
	BusRequest, BusAcknowledge,
	None
};

struct MicroOp {
	enum {
	} type;
	void *source;
	void *destination;
};

/*!
	@abstact An abstract base class for emulation of a 6502 processor via the curiously recurring template pattern/f-bounded polymorphism.

	@discussion Subclasses should implement @c perform_bus_operation(BusOperation operation, uint16_t address, uint8_t *value) in
	order to provide the bus on which the 6502 operates and @c flush(), which is called upon completion of a continuous run
	of cycles to allow a subclass to bring any on-demand activities up to date.

	Additional functionality can be provided by the host machine by providing a jam handler and inserting jam opcodes where appropriate;
	that will cause call outs when the program counter reaches those addresses. @c return_from_subroutine can be used to exit from a
	jammed state.
*/
template <class T> class Processor: public MicroOpScheduler<MicroOp> {
	private:
		uint8_t a_, i_, r_;
		RegisterPair bc_, de_, hl_;
		RegisterPair afDash_, bcDash_, deDash_, hlDash_;
		RegisterPair ix_, iy_, pc_, sp_;
		uint8_t carry_flag_, sign_result_, bit5_result_, half_carry_flag_, bit3_result_, parity_overflow_flag_, subtract_flag_;

		/*!
			Called to announce the end of a run_for_cycles period, allowing deferred work to take place.

			Users of the 6502 template may override this.
		*/
		void flush() {}

	public:
		/*!
			Gets the flags register.

			@see set_flags

			@returns The current value of the flags register.
		*/
		uint8_t get_flags() {
			return
				carry_flag_ |
				(sign_result_ & Flag::Sign) |
				(bit5_result_ & Flag::Bit5) |
				half_carry_flag_ |
				(bit3_result_ & Flag::Bit3) |
				parity_overflow_flag_ |
				subtract_flag_;
		}

		/*!
			Sets the flags register.

			@see set_flags

			@param flags The new value of the flags register.
		*/
		void set_flags(uint8_t flags) {
			carry_flag_				= flags & Flag::Carry;
			sign_result_			= flags;
			bit5_result_			= flags;
			half_carry_flag_		= flags & Flag::HalfCarry;
			bit3_result_			= flags;
			parity_overflow_flag_	= flags & Flag::Parity;
			subtract_flag_			= flags & Flag::Subtract;
		}

		/*!
			Gets the value of a register.

			@see set_value_of_register

			@param r The register to set.
			@returns The value of the register. 8-bit registers will be returned as unsigned.
		*/
		uint16_t get_value_of_register(Register r) {
			switch (r) {
				case Register::ProgramCounter:			return pc_.full;
				case Register::StackPointer:			return sp_.full;

				case Register::A:						return a_;
				case Register::Flags:					return get_flags();
				case Register::AF:						return (uint16_t)((a_ << 8) | get_flags());
				case Register::B:						return bc_.bytes.high;
				case Register::C:						return bc_.bytes.low;
				case Register::BC:						return bc_.full;
				case Register::D:						return de_.bytes.high;
				case Register::E:						return de_.bytes.low;
				case Register::DE:						return de_.full;
				case Register::H:						return hl_.bytes.high;
				case Register::L:						return hl_.bytes.low;
				case Register::HL:						return hl_.full;

				case Register::ADash:					return afDash_.bytes.high;
				case Register::FlagsDash:				return afDash_.bytes.low;
				case Register::AFDash:					return afDash_.full;
				case Register::BDash:					return bcDash_.bytes.high;
				case Register::CDash:					return bcDash_.bytes.low;
				case Register::BCDash:					return bcDash_.full;
				case Register::DDash:					return deDash_.bytes.high;
				case Register::EDash:					return deDash_.bytes.low;
				case Register::DEDash:					return deDash_.full;
				case Register::HDash:					return hlDash_.bytes.high;
				case Register::LDash:					return hlDash_.bytes.low;
				case Register::HLDash:					return hlDash_.full;

				case Register::IXh:						return ix_.bytes.high;
				case Register::IXl:						return ix_.bytes.low;
				case Register::IX:						return ix_.full;
				case Register::IYh:						return iy_.bytes.high;
				case Register::IYl:						return iy_.bytes.low;
				case Register::IY:						return iy_.full;

				case Register::R:						return r_;
				case Register::I:						return i_;

				default: return 0;
			}
		}

		/*!
			Sets the value of a register.

			@see get_value_of_register

			@param r The register to set.
			@param value The value to set. If the register is only 8 bit, the value will be truncated.
		*/
		void set_value_of_register(Register r, uint16_t value) {
			switch (r) {
				case Register::ProgramCounter:	pc_.full = value;				break;
				case Register::StackPointer:	sp_.full = value;				break;

				case Register::A:				a_ = (uint8_t)value;			break;
				case Register::AF:				a_ = (uint8_t)(value >> 8);		// deliberate fallthrough...
				case Register::Flags:			set_flags((uint8_t)value);		break;

				case Register::B:				bc_.bytes.high = (uint8_t)value;		break;
				case Register::C:				bc_.bytes.low = (uint8_t)value;			break;
				case Register::BC:				bc_.full = value;						break;
				case Register::D:				de_.bytes.high = (uint8_t)value;		break;
				case Register::E:				de_.bytes.low = (uint8_t)value;			break;
				case Register::DE:				de_.full = value;						break;
				case Register::H:				hl_.bytes.high = (uint8_t)value;		break;
				case Register::L:				hl_.bytes.low = (uint8_t)value;			break;
				case Register::HL:				hl_.full = value;						break;

				case Register::ADash:			afDash_.bytes.high = (uint8_t)value;	break;
				case Register::FlagsDash:		afDash_.bytes.low = (uint8_t)value;		break;
				case Register::AFDash:			afDash_.full = value;					break;
				case Register::BDash:			bcDash_.bytes.high = (uint8_t)value;	break;
				case Register::CDash:			bcDash_.bytes.low = (uint8_t)value;		break;
				case Register::BCDash:			bcDash_.full = value;					break;
				case Register::DDash:			deDash_.bytes.high = (uint8_t)value;	break;
				case Register::EDash:			deDash_.bytes.low = (uint8_t)value;		break;
				case Register::DEDash:			deDash_.full = value;					break;
				case Register::HDash:			hlDash_.bytes.high = (uint8_t)value;	break;
				case Register::LDash:			hlDash_.bytes.low = (uint8_t)value;		break;
				case Register::HLDash:			hlDash_.full = value;					break;

				case Register::IXh:				ix_.bytes.high = (uint8_t)value;		break;
				case Register::IXl:				ix_.bytes.low = (uint8_t)value;			break;
				case Register::IX:				ix_.full = value;						break;
				case Register::IYh:				iy_.bytes.high = (uint8_t)value;		break;
				case Register::IYl:				iy_.bytes.low = (uint8_t)value;			break;
				case Register::IY:				iy_.full = value;						break;

				case Register::R:				r_ = (uint8_t)value;					break;
				case Register::I:				i_ = (uint8_t)value;					break;

				default: break;
			}
		}
};

}
}

#endif /* Z80_hpp */
<commit_msg>Moved flush, added run_for_cycles, which does nothing right now.<commit_after>//
//  Z80.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 14/05/2017.
//  Copyright © 2017 Thomas Harte. All rights reserved.
//

#ifndef Z80_hpp
#define Z80_hpp

#include <cstdint>

#include "../MicroOpScheduler.hpp"
#include "../RegisterSizes.hpp"

namespace CPU {
namespace Z80 {

/*
	The list of registers that can be accessed via @c set_value_of_register and @c set_value_of_register.
*/
enum Register {
	ProgramCounter,
	StackPointer,

	A,		Flags,	AF,
	B,		C,		BC,
	D,		E,		DE,
	H,		L,		HL,

	ADash,		FlagsDash,	AFDash,
	BDash,		CDash,		BCDash,
	DDash,		EDash,		DEDash,
	HDash,		LDash,		HLDash,

	IXh,	IXl,	IX,
	IYh,	IYl,	IY,
	R,		I,
};

/*
	Flags as defined on the Z80; can be used to decode the result of @c get_flags or to form a value for @c set_flags.
*/
enum Flag: uint8_t {
	Sign		= 0x80,
	Zero		= 0x40,
	Bit5		= 0x20,
	HalfCarry	= 0x10,
	Bit3		= 0x08,
	Parity		= 0x04,
	Overflow	= 0x04,
	Subtract	= 0x02,
	Carry		= 0x01
};

/*!
	Subclasses will be given the task of performing bus operations, allowing them to provide whatever interface they like
	between a Z80 and the rest of the system. @c BusOperation lists the types of bus operation that may be requested.

	@c None is reserved for internal use. It will never be requested from a subclass.
*/
enum BusOperation {
	ReadOpcode,
	Read, Write,
	Input, Output,
	Interrupt,
	BusRequest, BusAcknowledge,
	None
};

struct MicroOp {
	enum {
	} type;
	void *source;
	void *destination;
};

/*!
	@abstact An abstract base class for emulation of a 6502 processor via the curiously recurring template pattern/f-bounded polymorphism.

	@discussion Subclasses should implement @c perform_bus_operation(BusOperation operation, uint16_t address, uint8_t *value) in
	order to provide the bus on which the 6502 operates and @c flush(), which is called upon completion of a continuous run
	of cycles to allow a subclass to bring any on-demand activities up to date.

	Additional functionality can be provided by the host machine by providing a jam handler and inserting jam opcodes where appropriate;
	that will cause call outs when the program counter reaches those addresses. @c return_from_subroutine can be used to exit from a
	jammed state.
*/
template <class T> class Processor: public MicroOpScheduler<MicroOp> {
	private:
		uint8_t a_, i_, r_;
		RegisterPair bc_, de_, hl_;
		RegisterPair afDash_, bcDash_, deDash_, hlDash_;
		RegisterPair ix_, iy_, pc_, sp_;
		uint8_t carry_flag_, sign_result_, bit5_result_, half_carry_flag_, bit3_result_, parity_overflow_flag_, subtract_flag_;

	public:
		/*!
			Runs the Z80 for a supplied number of cycles.

			@discussion Subclasses must implement @c perform_bus_operation(BusOperation operation, uint16_t address, uint8_t *value) .
			The Z80 will call that method for all bus accesses.

			If it is a read operation then @c value will be seeded with the value 0xff.

			@param number_of_cycles The number of cycles to run the Z80 for.
		*/
		void run_for_cycles(int number_of_cycles) {
			// TODO (!)
		}

		/*!
			Called to announce the end of a run_for_cycles period, allowing deferred work to take place.

			Users of the Z80 template may override this.
		*/
		void flush() {}

		/*!
			Gets the flags register.

			@see set_flags

			@returns The current value of the flags register.
		*/
		uint8_t get_flags() {
			return
				carry_flag_ |
				(sign_result_ & Flag::Sign) |
				(bit5_result_ & Flag::Bit5) |
				half_carry_flag_ |
				(bit3_result_ & Flag::Bit3) |
				parity_overflow_flag_ |
				subtract_flag_;
		}

		/*!
			Sets the flags register.

			@see set_flags

			@param flags The new value of the flags register.
		*/
		void set_flags(uint8_t flags) {
			carry_flag_				= flags & Flag::Carry;
			sign_result_			= flags;
			bit5_result_			= flags;
			half_carry_flag_		= flags & Flag::HalfCarry;
			bit3_result_			= flags;
			parity_overflow_flag_	= flags & Flag::Parity;
			subtract_flag_			= flags & Flag::Subtract;
		}

		/*!
			Gets the value of a register.

			@see set_value_of_register

			@param r The register to set.
			@returns The value of the register. 8-bit registers will be returned as unsigned.
		*/
		uint16_t get_value_of_register(Register r) {
			switch (r) {
				case Register::ProgramCounter:			return pc_.full;
				case Register::StackPointer:			return sp_.full;

				case Register::A:						return a_;
				case Register::Flags:					return get_flags();
				case Register::AF:						return (uint16_t)((a_ << 8) | get_flags());
				case Register::B:						return bc_.bytes.high;
				case Register::C:						return bc_.bytes.low;
				case Register::BC:						return bc_.full;
				case Register::D:						return de_.bytes.high;
				case Register::E:						return de_.bytes.low;
				case Register::DE:						return de_.full;
				case Register::H:						return hl_.bytes.high;
				case Register::L:						return hl_.bytes.low;
				case Register::HL:						return hl_.full;

				case Register::ADash:					return afDash_.bytes.high;
				case Register::FlagsDash:				return afDash_.bytes.low;
				case Register::AFDash:					return afDash_.full;
				case Register::BDash:					return bcDash_.bytes.high;
				case Register::CDash:					return bcDash_.bytes.low;
				case Register::BCDash:					return bcDash_.full;
				case Register::DDash:					return deDash_.bytes.high;
				case Register::EDash:					return deDash_.bytes.low;
				case Register::DEDash:					return deDash_.full;
				case Register::HDash:					return hlDash_.bytes.high;
				case Register::LDash:					return hlDash_.bytes.low;
				case Register::HLDash:					return hlDash_.full;

				case Register::IXh:						return ix_.bytes.high;
				case Register::IXl:						return ix_.bytes.low;
				case Register::IX:						return ix_.full;
				case Register::IYh:						return iy_.bytes.high;
				case Register::IYl:						return iy_.bytes.low;
				case Register::IY:						return iy_.full;

				case Register::R:						return r_;
				case Register::I:						return i_;

				default: return 0;
			}
		}

		/*!
			Sets the value of a register.

			@see get_value_of_register

			@param r The register to set.
			@param value The value to set. If the register is only 8 bit, the value will be truncated.
		*/
		void set_value_of_register(Register r, uint16_t value) {
			switch (r) {
				case Register::ProgramCounter:	pc_.full = value;				break;
				case Register::StackPointer:	sp_.full = value;				break;

				case Register::A:				a_ = (uint8_t)value;			break;
				case Register::AF:				a_ = (uint8_t)(value >> 8);		// deliberate fallthrough...
				case Register::Flags:			set_flags((uint8_t)value);		break;

				case Register::B:				bc_.bytes.high = (uint8_t)value;		break;
				case Register::C:				bc_.bytes.low = (uint8_t)value;			break;
				case Register::BC:				bc_.full = value;						break;
				case Register::D:				de_.bytes.high = (uint8_t)value;		break;
				case Register::E:				de_.bytes.low = (uint8_t)value;			break;
				case Register::DE:				de_.full = value;						break;
				case Register::H:				hl_.bytes.high = (uint8_t)value;		break;
				case Register::L:				hl_.bytes.low = (uint8_t)value;			break;
				case Register::HL:				hl_.full = value;						break;

				case Register::ADash:			afDash_.bytes.high = (uint8_t)value;	break;
				case Register::FlagsDash:		afDash_.bytes.low = (uint8_t)value;		break;
				case Register::AFDash:			afDash_.full = value;					break;
				case Register::BDash:			bcDash_.bytes.high = (uint8_t)value;	break;
				case Register::CDash:			bcDash_.bytes.low = (uint8_t)value;		break;
				case Register::BCDash:			bcDash_.full = value;					break;
				case Register::DDash:			deDash_.bytes.high = (uint8_t)value;	break;
				case Register::EDash:			deDash_.bytes.low = (uint8_t)value;		break;
				case Register::DEDash:			deDash_.full = value;					break;
				case Register::HDash:			hlDash_.bytes.high = (uint8_t)value;	break;
				case Register::LDash:			hlDash_.bytes.low = (uint8_t)value;		break;
				case Register::HLDash:			hlDash_.full = value;					break;

				case Register::IXh:				ix_.bytes.high = (uint8_t)value;		break;
				case Register::IXl:				ix_.bytes.low = (uint8_t)value;			break;
				case Register::IX:				ix_.full = value;						break;
				case Register::IYh:				iy_.bytes.high = (uint8_t)value;		break;
				case Register::IYl:				iy_.bytes.low = (uint8_t)value;			break;
				case Register::IY:				iy_.full = value;						break;

				case Register::R:				r_ = (uint8_t)value;					break;
				case Register::I:				i_ = (uint8_t)value;					break;

				default: break;
			}
		}
};

}
}

#endif /* Z80_hpp */
<|endoftext|>


<commit_before>#include "stack.h"
<commit_msg>feat: add string expr_ for BigInteger<commit_after>#include "stack.h"
class BigInteger
{
private:
	string expr_;
};
<|endoftext|>


<commit_before>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/lite/python/interpreter_wrapper/python_utils.h"

#include <memory>

#include "tensorflow/lite/python/interpreter_wrapper/numpy.h"

namespace tflite {
namespace python_utils {

struct PyObjectDereferencer {
  void operator()(PyObject* py_object) const { Py_DECREF(py_object); }
};

using UniquePyObjectRef = std::unique_ptr<PyObject, PyObjectDereferencer>;

int TfLiteTypeToPyArrayType(TfLiteType tf_lite_type) {
  switch (tf_lite_type) {
    case kTfLiteFloat32:
      return NPY_FLOAT32;
    case kTfLiteInt32:
      return NPY_INT32;
    case kTfLiteInt16:
      return NPY_INT16;
    case kTfLiteUInt8:
      return NPY_UINT8;
    case kTfLiteInt8:
      return NPY_INT8;
    case kTfLiteInt64:
      return NPY_INT64;
    case kTfLiteString:
      return NPY_STRING;
    case kTfLiteBool:
      return NPY_BOOL;
    case kTfLiteComplex64:
      return NPY_COMPLEX64;
    case kTfLiteNoType:
      return NPY_NOTYPE;
      // Avoid default so compiler errors created when new types are made.
  }
  return NPY_NOTYPE;
}

TfLiteType TfLiteTypeFromPyArray(PyArrayObject* array) {
  int pyarray_type = PyArray_TYPE(array);
  switch (pyarray_type) {
    case NPY_FLOAT32:
      return kTfLiteFloat32;
    case NPY_INT32:
      return kTfLiteInt32;
    case NPY_INT16:
      return kTfLiteInt16;
    case NPY_UINT8:
      return kTfLiteUInt8;
    case NPY_INT8:
      return kTfLiteInt8;
    case NPY_INT64:
      return kTfLiteInt64;
    case NPY_BOOL:
      return kTfLiteBool;
    case NPY_OBJECT:
    case NPY_STRING:
    case NPY_UNICODE:
      return kTfLiteString;
    case NPY_COMPLEX64:
      return kTfLiteComplex64;
      // Avoid default so compiler errors created when new types are made.
  }
  return kTfLiteNoType;
}

#if PY_VERSION_HEX >= 0x03030000
bool FillStringBufferFromPyUnicode(PyObject* value,
                                   DynamicBuffer* dynamic_buffer) {
  Py_ssize_t len = -1;
  char* buf = PyUnicode_AsUTF8AndSize(value, &len);
  if (buf == NULL) {
    PyErr_SetString(PyExc_ValueError, "PyUnicode_AsUTF8AndSize() failed.");
    return false;
  }
  dynamic_buffer->AddString(buf, len);
  return true;
}
#else
bool FillStringBufferFromPyUnicode(PyObject* value,
                                   DynamicBuffer* dynamic_buffer) {
  UniquePyObjectRef utemp(PyUnicode_AsUTF8String(value));
  if (!utemp) {
    PyErr_SetString(PyExc_ValueError, "PyUnicode_AsUTF8String() failed.");
    return false;
  }
  char* buf = nullptr;
  Py_ssize_t len = -1;
  if (PyBytes_AsStringAndSize(utemp.get(), &buf, &len) == -1) {
    PyErr_SetString(PyExc_ValueError, "PyBytes_AsStringAndSize() failed.");
    return false;
  }
  dynamic_buffer->AddString(buf, len);
  return true;
}
#endif

bool FillStringBufferFromPyString(PyObject* value,
                                  DynamicBuffer* dynamic_buffer) {
  if (PyUnicode_Check(value)) {
    return FillStringBufferFromPyUnicode(value, dynamic_buffer);
  }

  char* buf = nullptr;
  Py_ssize_t len = -1;
  if (PyBytes_AsStringAndSize(value, &buf, &len) == -1) {
    PyErr_SetString(PyExc_ValueError, "PyBytes_AsStringAndSize() failed.");
    return false;
  }
  dynamic_buffer->AddString(buf, len);
  return true;
}

bool FillStringBufferWithPyArray(PyObject* value,
                                 DynamicBuffer* dynamic_buffer) {
  PyArrayObject* array = reinterpret_cast<PyArrayObject*>(value);
  switch (PyArray_TYPE(array)) {
    case NPY_OBJECT:
    case NPY_STRING:
    case NPY_UNICODE: {
      UniquePyObjectRef iter(PyArray_IterNew(value));
      while (PyArray_ITER_NOTDONE(iter.get())) {
        UniquePyObjectRef item(PyArray_GETITEM(
            array, reinterpret_cast<char*>(PyArray_ITER_DATA(iter.get()))));

        if (!FillStringBufferFromPyString(item.get(), dynamic_buffer)) {
          return false;
        }

        PyArray_ITER_NEXT(iter.get());
      }
      return true;
    }
    default:
      break;
  }

  PyErr_Format(PyExc_ValueError,
               "Cannot use numpy array of type %d for string tensor.",
               PyArray_TYPE(array));
  return false;
}

}  // namespace python_utils
}  // namespace tflite
<commit_msg>Fix build: PyUnicode_AsUTF8AndSize returns a const char* in Python 3.7<commit_after>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/lite/python/interpreter_wrapper/python_utils.h"

#include <memory>

#include "tensorflow/lite/python/interpreter_wrapper/numpy.h"

namespace tflite {
namespace python_utils {

struct PyObjectDereferencer {
  void operator()(PyObject* py_object) const { Py_DECREF(py_object); }
};

using UniquePyObjectRef = std::unique_ptr<PyObject, PyObjectDereferencer>;

int TfLiteTypeToPyArrayType(TfLiteType tf_lite_type) {
  switch (tf_lite_type) {
    case kTfLiteFloat32:
      return NPY_FLOAT32;
    case kTfLiteInt32:
      return NPY_INT32;
    case kTfLiteInt16:
      return NPY_INT16;
    case kTfLiteUInt8:
      return NPY_UINT8;
    case kTfLiteInt8:
      return NPY_INT8;
    case kTfLiteInt64:
      return NPY_INT64;
    case kTfLiteString:
      return NPY_STRING;
    case kTfLiteBool:
      return NPY_BOOL;
    case kTfLiteComplex64:
      return NPY_COMPLEX64;
    case kTfLiteNoType:
      return NPY_NOTYPE;
      // Avoid default so compiler errors created when new types are made.
  }
  return NPY_NOTYPE;
}

TfLiteType TfLiteTypeFromPyArray(PyArrayObject* array) {
  int pyarray_type = PyArray_TYPE(array);
  switch (pyarray_type) {
    case NPY_FLOAT32:
      return kTfLiteFloat32;
    case NPY_INT32:
      return kTfLiteInt32;
    case NPY_INT16:
      return kTfLiteInt16;
    case NPY_UINT8:
      return kTfLiteUInt8;
    case NPY_INT8:
      return kTfLiteInt8;
    case NPY_INT64:
      return kTfLiteInt64;
    case NPY_BOOL:
      return kTfLiteBool;
    case NPY_OBJECT:
    case NPY_STRING:
    case NPY_UNICODE:
      return kTfLiteString;
    case NPY_COMPLEX64:
      return kTfLiteComplex64;
      // Avoid default so compiler errors created when new types are made.
  }
  return kTfLiteNoType;
}

#if PY_VERSION_HEX >= 0x03030000
bool FillStringBufferFromPyUnicode(PyObject* value,
                                   DynamicBuffer* dynamic_buffer) {
  Py_ssize_t len = -1;
  const char* buf = PyUnicode_AsUTF8AndSize(value, &len);
  if (buf == NULL) {
    PyErr_SetString(PyExc_ValueError, "PyUnicode_AsUTF8AndSize() failed.");
    return false;
  }
  dynamic_buffer->AddString(buf, len);
  return true;
}
#else
bool FillStringBufferFromPyUnicode(PyObject* value,
                                   DynamicBuffer* dynamic_buffer) {
  UniquePyObjectRef utemp(PyUnicode_AsUTF8String(value));
  if (!utemp) {
    PyErr_SetString(PyExc_ValueError, "PyUnicode_AsUTF8String() failed.");
    return false;
  }
  char* buf = nullptr;
  Py_ssize_t len = -1;
  if (PyBytes_AsStringAndSize(utemp.get(), &buf, &len) == -1) {
    PyErr_SetString(PyExc_ValueError, "PyBytes_AsStringAndSize() failed.");
    return false;
  }
  dynamic_buffer->AddString(buf, len);
  return true;
}
#endif

bool FillStringBufferFromPyString(PyObject* value,
                                  DynamicBuffer* dynamic_buffer) {
  if (PyUnicode_Check(value)) {
    return FillStringBufferFromPyUnicode(value, dynamic_buffer);
  }

  char* buf = nullptr;
  Py_ssize_t len = -1;
  if (PyBytes_AsStringAndSize(value, &buf, &len) == -1) {
    PyErr_SetString(PyExc_ValueError, "PyBytes_AsStringAndSize() failed.");
    return false;
  }
  dynamic_buffer->AddString(buf, len);
  return true;
}

bool FillStringBufferWithPyArray(PyObject* value,
                                 DynamicBuffer* dynamic_buffer) {
  PyArrayObject* array = reinterpret_cast<PyArrayObject*>(value);
  switch (PyArray_TYPE(array)) {
    case NPY_OBJECT:
    case NPY_STRING:
    case NPY_UNICODE: {
      UniquePyObjectRef iter(PyArray_IterNew(value));
      while (PyArray_ITER_NOTDONE(iter.get())) {
        UniquePyObjectRef item(PyArray_GETITEM(
            array, reinterpret_cast<char*>(PyArray_ITER_DATA(iter.get()))));

        if (!FillStringBufferFromPyString(item.get(), dynamic_buffer)) {
          return false;
        }

        PyArray_ITER_NEXT(iter.get());
      }
      return true;
    }
    default:
      break;
  }

  PyErr_Format(PyExc_ValueError,
               "Cannot use numpy array of type %d for string tensor.",
               PyArray_TYPE(array));
  return false;
}

}  // namespace python_utils
}  // namespace tflite
<|endoftext|>