<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/android/process_utils.h"

#include <vector>

#include "base/lazy_instance.h"
#include "base/logging.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/render_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "jni/ProcessUtils_jni.h"
#include "net/http/http_network_session.h"
#include "net/http/http_transaction_factory.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"

namespace {

void CloseIdleConnectionsForProfile(
    scoped_refptr<net::URLRequestContextGetter> context_getter) {
  DCHECK(context_getter.get());
  if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)) {
    content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
                           base::Bind(&CloseIdleConnectionsForProfile,
                                      context_getter));
    return;
  }

  net::URLRequestContext* context = context_getter->GetURLRequestContext();
  DCHECK(context->http_transaction_factory());
  net::HttpNetworkSession* session =
      context->http_transaction_factory()->GetSession();
  DCHECK(session);
  session->CloseIdleConnections();
}

// Only accessed from the JNI thread by ToggleWebKitSharedTimers() which is
// implemented below.
base::LazyInstance<std::vector<int /* process id */> > g_suspended_processes =
    LAZY_INSTANCE_INITIALIZER;

// Suspends timers in all current render processes.
void SuspendWebKitSharedTimers(std::vector<int>* suspended_processes) {
  for (content::RenderProcessHost::iterator i(
          content::RenderProcessHost::AllHostsIterator());
       !i.IsAtEnd(); i.Advance()) {
    content::RenderProcessHost* host = i.GetCurrentValue();
    suspended_processes->push_back(host->GetID());
    host->Send(new ChromeViewMsg_ToggleWebKitSharedTimer(true));
  }
}

void ResumeWebkitSharedTimers(const std::vector<int>& suspended_processes) {
  for (std::vector<int>::const_iterator it = suspended_processes.begin();
       it != suspended_processes.end(); ++it) {
    content::RenderProcessHost* host = content::RenderProcessHost::FromID(*it);
    if (host)
      host->Send(new ChromeViewMsg_ToggleWebKitSharedTimer(false));
  }
}

}  // namespace

static void ToggleWebKitSharedTimers(JNIEnv* env,
                                     jclass obj,
                                     jboolean suspend) {
  std::vector<int>* suspended_processes = &g_suspended_processes.Get();
  if (suspend) {
    DCHECK(suspended_processes->empty());
    SuspendWebKitSharedTimers(suspended_processes);
  } else {
    ResumeWebkitSharedTimers(*suspended_processes);
    suspended_processes->clear();
  }
}

static void CloseIdleConnections(JNIEnv* env, jclass obj) {
  // Iterate through all loaded profiles (and their associated incognito
  // profiles if created), and close the idle connections associated with each
  // one.
  std::vector<Profile*> profiles(
      g_browser_process->profile_manager()->GetLoadedProfiles());
  for (std::vector<Profile*>::iterator i = profiles.begin();
      i != profiles.end(); i++) {
    Profile* profile = *i;
    CloseIdleConnectionsForProfile(profile->GetRequestContext());
    if (profile->HasOffTheRecordProfile()) {
      CloseIdleConnectionsForProfile(
          profile->GetOffTheRecordProfile()->GetRequestContext());
    }
  }
}

bool RegisterProcessUtils(JNIEnv* env) {
  return RegisterNativesImpl(env);
}
<commit_msg>Check whether HttpNetworkSession is valid before closing idle connections.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/android/process_utils.h"

#include <vector>

#include "base/lazy_instance.h"
#include "base/logging.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/render_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "jni/ProcessUtils_jni.h"
#include "net/http/http_network_session.h"
#include "net/http/http_transaction_factory.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"

namespace {

void CloseIdleConnectionsForProfile(
    scoped_refptr<net::URLRequestContextGetter> context_getter) {
  DCHECK(context_getter.get());
  if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)) {
    content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
                           base::Bind(&CloseIdleConnectionsForProfile,
                                      context_getter));
    return;
  }

  net::URLRequestContext* context = context_getter->GetURLRequestContext();
  if (!context)
    return;
  net::HttpNetworkSession* session =
      context->http_transaction_factory()->GetSession();
  if (session)
    session->CloseIdleConnections();
}

// Only accessed from the JNI thread by ToggleWebKitSharedTimers() which is
// implemented below.
base::LazyInstance<std::vector<int /* process id */> > g_suspended_processes =
    LAZY_INSTANCE_INITIALIZER;

// Suspends timers in all current render processes.
void SuspendWebKitSharedTimers(std::vector<int>* suspended_processes) {
  for (content::RenderProcessHost::iterator i(
          content::RenderProcessHost::AllHostsIterator());
       !i.IsAtEnd(); i.Advance()) {
    content::RenderProcessHost* host = i.GetCurrentValue();
    suspended_processes->push_back(host->GetID());
    host->Send(new ChromeViewMsg_ToggleWebKitSharedTimer(true));
  }
}

void ResumeWebkitSharedTimers(const std::vector<int>& suspended_processes) {
  for (std::vector<int>::const_iterator it = suspended_processes.begin();
       it != suspended_processes.end(); ++it) {
    content::RenderProcessHost* host = content::RenderProcessHost::FromID(*it);
    if (host)
      host->Send(new ChromeViewMsg_ToggleWebKitSharedTimer(false));
  }
}

}  // namespace

static void ToggleWebKitSharedTimers(JNIEnv* env,
                                     jclass obj,
                                     jboolean suspend) {
  std::vector<int>* suspended_processes = &g_suspended_processes.Get();
  if (suspend) {
    DCHECK(suspended_processes->empty());
    SuspendWebKitSharedTimers(suspended_processes);
  } else {
    ResumeWebkitSharedTimers(*suspended_processes);
    suspended_processes->clear();
  }
}

static void CloseIdleConnections(JNIEnv* env, jclass obj) {
  // Iterate through all loaded profiles (and their associated incognito
  // profiles if created), and close the idle connections associated with each
  // one.
  std::vector<Profile*> profiles(
      g_browser_process->profile_manager()->GetLoadedProfiles());
  for (std::vector<Profile*>::iterator i = profiles.begin();
      i != profiles.end(); i++) {
    Profile* profile = *i;
    CloseIdleConnectionsForProfile(profile->GetRequestContext());
    if (profile->HasOffTheRecordProfile()) {
      CloseIdleConnectionsForProfile(
          profile->GetOffTheRecordProfile()->GetRequestContext());
    }
  }
}

bool RegisterProcessUtils(JNIEnv* env) {
  return RegisterNativesImpl(env);
}
<|endoftext|>


<commit_before>#ifndef BUFFERED_ISTREAM_HPP
#define BUFFERED_ISTREAM_HPP

#include <fstream>
#include <sstream>

namespace flags {
  enum buffered_istream_flags { none = 0, sharp_comment = 1 };
}

class buffered_istream {
protected:
  std::istream* ist;
  std::stringstream*  str;
  flags::buffered_istream_flags flag;
public:
  buffered_istream(std::istream* i = 0, flags::buffered_istream_flags f = flags::none);
  virtual ~buffered_istream();
  buffered_istream& open(std::istream* i);
  buffered_istream& close();

  std::string next();
  std::string current() const;
  buffered_istream& rewind();
  template <typename T> buffered_istream& operator>> (T& val);

  inline bool good() const { return ist->good(); }
  inline bool fail() const { return ist->fail(); }
  inline bool eof () const { return ist->eof(); }
  buffered_istream& set_flags(flags::buffered_istream_flags f = flags::none);
};

buffered_istream::buffered_istream(std::istream* i, flags::buffered_istream_flags f){
  if(i) open(i);
  str = new std::stringstream(std::stringstream::in | std::stringstream::out);
  str->setstate(std::ios::eofbit);
  set_flags(f);
}

buffered_istream::~buffered_istream(){
  if(str)   delete str;
}

buffered_istream& buffered_istream::open(std::istream* ist_in){
  ist = ist_in;
  return *this;
}

buffered_istream& buffered_istream::close(){
  ist = 0;
  str->clear();
  str->str("");
  return *this;
}

std::string buffered_istream::next(){
  str->clear();
  str->str("");
  char s;
  bool ignore = false;
  while(true){
    s = ist->get();
    if(ist->eof()) break;
    if((flag & flags::sharp_comment)){
      if(s == '#'){
        ignore = true;
      }else if(s == 10 or s == 13){
        ignore = false; // to put CR/LF
      }
    }
    if(not ignore) str->put(s);
    if(s == 10 or s == 13) break; // CR or LF
  }
  return str->str();
}

std::string buffered_istream::current() const {
  return str->str();
}

buffered_istream& buffered_istream::rewind() {
  str->clear();
  str->seekg(0, str->beg);
  return *this;
}

template <typename T> buffered_istream& buffered_istream::operator>> (T& val) {
  *str >> val;
  if(str->eof()){
    next();
    if(ist->eof()){ // next fails and everything is done.
      return *this;
    }
    return *this >> val;
  }
  return *this;
}

buffered_istream& buffered_istream::set_flags(flags::buffered_istream_flags f){
  flag = f;
  return *this;
}

class buffered_ifstream : public buffered_istream{
private:
  std::ifstream* file;
public:
  buffered_ifstream(const char *filename, flags::buffered_istream_flags f = flags::none);
  virtual ~buffered_ifstream();
  buffered_ifstream& open(const char* filename);
  buffered_ifstream& close();
};

buffered_ifstream::buffered_ifstream(const char *filename, flags::buffered_istream_flags f){
  open(filename);
  set_flags(f);
}

buffered_ifstream::~buffered_ifstream(){
  if(file){
    file->close();
    delete file;
  }
}

buffered_ifstream& buffered_ifstream::open(const char* filename){
  file = new std::ifstream(filename, std::ios::in);
  buffered_istream::open(file);
  return *this;
}

buffered_ifstream& buffered_ifstream::close(){
  file->close();
  delete file;
  file = 0;
  buffered_istream::close();
  return *this;
}

#endif
<commit_msg>supress conversion<commit_after>#ifndef BUFFERED_ISTREAM_HPP
#define BUFFERED_ISTREAM_HPP

#include <fstream>
#include <sstream>

namespace flags {
  enum buffered_istream_flags { none = 0, sharp_comment = 1 };
}

class buffered_istream {
protected:
  std::istream* ist;
  std::stringstream*  str;
  flags::buffered_istream_flags flag;
public:
  buffered_istream(std::istream* i = 0, flags::buffered_istream_flags f = flags::none);
  virtual ~buffered_istream();
  buffered_istream& open(std::istream* i);
  buffered_istream& close();

  std::string next();
  std::string current() const;
  buffered_istream& rewind();
  template <typename T> buffered_istream& operator>> (T& val);

  inline bool good() const { return ist->good(); }
  inline bool fail() const { return ist->fail(); }
  inline bool eof () const { return ist->eof(); }
  buffered_istream& set_flags(flags::buffered_istream_flags f = flags::none);
};

buffered_istream::buffered_istream(std::istream* i, flags::buffered_istream_flags f){
  if(i) open(i);
  str = new std::stringstream(std::stringstream::in | std::stringstream::out);
  str->setstate(std::ios::eofbit);
  set_flags(f);
}

buffered_istream::~buffered_istream(){
  if(str)   delete str;
}

buffered_istream& buffered_istream::open(std::istream* ist_in){
  ist = ist_in;
  return *this;
}

buffered_istream& buffered_istream::close(){
  ist = 0;
  str->clear();
  str->str("");
  return *this;
}

std::string buffered_istream::next(){
  str->clear();
  str->str("");
  char s;
  bool ignore = false;
  while(true){
    ist->get(s);
    if(ist->eof()) break;
    if((flag & flags::sharp_comment)){
      if(s == '#'){
        ignore = true;
      }else if(s == 10 or s == 13){
        ignore = false; // to put CR/LF
      }
    }
    if(not ignore) str->put(s);
    if(s == 10 or s == 13) break; // CR or LF
  }
  return str->str();
}

std::string buffered_istream::current() const {
  return str->str();
}

buffered_istream& buffered_istream::rewind() {
  str->clear();
  str->seekg(0, str->beg);
  return *this;
}

template <typename T> buffered_istream& buffered_istream::operator>> (T& val) {
  *str >> val;
  if(str->eof()){
    next();
    if(ist->eof()){ // next fails and everything is done.
      return *this;
    }
    return *this >> val;
  }
  return *this;
}

buffered_istream& buffered_istream::set_flags(flags::buffered_istream_flags f){
  flag = f;
  return *this;
}

class buffered_ifstream : public buffered_istream{
private:
  std::ifstream* file;
public:
  buffered_ifstream(const char *filename, flags::buffered_istream_flags f = flags::none);
  virtual ~buffered_ifstream();
  buffered_ifstream& open(const char* filename);
  buffered_ifstream& close();
};

buffered_ifstream::buffered_ifstream(const char *filename, flags::buffered_istream_flags f){
  open(filename);
  set_flags(f);
}

buffered_ifstream::~buffered_ifstream(){
  if(file){
    file->close();
    delete file;
  }
}

buffered_ifstream& buffered_ifstream::open(const char* filename){
  file = new std::ifstream(filename, std::ios::in);
  buffered_istream::open(file);
  return *this;
}

buffered_ifstream& buffered_ifstream::close(){
  file->close();
  delete file;
  file = 0;
  buffered_istream::close();
  return *this;
}

#endif
<|endoftext|>


<commit_before>/**
 * 	Result.cpp
 *
 * 	Class representing a MySQL result set
 *
 * 	@copyright 2014 Copernica BV
 */

/**
 *  Dependencies
 */
#include "result.h"
#include <iostream>

/**
 *  Set up namespace
 */
namespace ReactPhp {

/**
 *  Retrieve row at given offset
 */
void Result::fetchRow(Php::Parameters &params)
{
	// retrieve the parameter
	int index = params[0];

	// check for valid input
	if(index > (int)_result.size() || index < 0) throw Php::Exception("Invalid result object");

	for (auto field : _result[index])
	{
		// print the rows to the screen
		std::cout << field.first << " => " << field.second << std::endl;
	}
}

/**
 *  Is this a valid result?
 */
Php::Value Result::valid()
{
	_result.valid();

	return true;
}

/**
 *  The number of rows affected
 */
size_t Result::affectedRows()
{
	return (int)_result.affectedRows();
}

/**
 *  Get the number of rows in this result
 */
Php::Value Result::size()
{
	return (int)_result.size();
}

/**
 *  Retrieve iterator for first row
 */
Php::Value Result::begin()
{
	_result.begin();

	return true;
}

/**
 *  Retrieve iterator past the end
 */
Php::Value Result::end()
{
	_result.end();

	return true;
}

/**
 *   End of namespace
 */
}
<commit_msg>Class representing a MySQL result set<commit_after>/**
 *  Result.cpp
 *
 *  Class representing a MySQL result set
 *
 *  @copyright 2014 Copernica BV
 */

/**
 *  Dependencies
 */
#include "result.h"
#include <iostream>

/**
 *  Set up namespace
 */
namespace ReactPhp {

/**
 *  Retrieve row at given offset
 */
void Result::fetchRow(Php::Parameters &params)
{
	// retrieve the parameter
	int index = params[0];

	// check for valid input
	if(index > (int)_result.size() || index < 0) throw Php::Exception("Invalid result object");

	for (auto field : _result[index])
	{
		// print the rows to the screen
		std::cout << field.first << " => " << field.second << std::endl;
	}
}

/**
 *  Is this a valid result?
 */
Php::Value Result::valid()
{
	_result.valid();

	return true;
}

/**
 *  The number of rows affected
 */
size_t Result::affectedRows()
{
	return (int)_result.affectedRows();
}

/**
 *  Get the number of rows in this result
 */
Php::Value Result::size()
{
	return (int)_result.size();
}

/**
 *  Retrieve iterator for first row
 */
Php::Value Result::begin()
{
	_result.begin();

	return true;
}

/**
 *  Retrieve iterator past the end
 */
Php::Value Result::end()
{
	_result.end();

	return true;
}

/**
 *   End of namespace
 */
}
<|endoftext|>


<commit_before>#include "FrequencyInModule.h"
#include "ModularSynth.h"

FrequencyInModule::FrequencyInModule(ModularSynth& synth)
	:SynthModule(synth, moduleId, 0, 1, 0)
{
}

void FrequencyInModule::cycle()
{
	setOutput(0, mSynth.getFrequency());
}

const char * FrequencyInModule::getInputName(int input) const
{
	return "FrequencyIn";
}

const char * FrequencyInModule::getOutputName(int output) const
{
	return "Output";
}

const char * FrequencyInModule::getName() const
{
	return "FrequencyIn";
}

SynthModule * FrequencyInModule::createModule(ModularSynth& synth)
{
	return new FrequencyInModule(synth);
}
<commit_msg>Absolute frequency output for FrequencyIn<commit_after>#include "FrequencyInModule.h"
#include "ModularSynth.h"

FrequencyInModule::FrequencyInModule(ModularSynth& synth)
	:SynthModule(synth, moduleId, 0, 2, 0)
{
}

void FrequencyInModule::cycle()
{
	setOutput(0, mSynth.getFrequency());
	setOutput(1, mSynth.getFrequency() * mSampleRate);
}

const char * FrequencyInModule::getInputName(int input) const
{
	return "FrequencyIn";
}

const char * FrequencyInModule::getOutputName(int output) const
{
	static const char *names[] = {"Output", "SOutput"};
	return names[output];
}

const char * FrequencyInModule::getName() const
{
	return "FrequencyIn";
}

SynthModule * FrequencyInModule::createModule(ModularSynth& synth)
{
	return new FrequencyInModule(synth);
}
<|endoftext|>


<commit_before>#include "types.h"
#include "stat.h"
#include "user.h"
#include "mtrace.h"

#define NCHILD 2
#define NDEPTH 5

void
forktree(void)
{
  int depth = 0;

  fprintf(1, "%d: fork tree\n", getpid());
  mtenable("xv6-forktree");

 next_level:
  //printf(1, "pid %d, depth %d\n", getpid(), depth);
  if (depth >= NDEPTH)
    exit();

  for (int i = 0; i < NCHILD; i++) {
    int pid = fork(0);
    if (pid < 0) {
      fprintf(1, "fork error\n");
      exit();
    }

    if (pid == 0) {
      depth++;
      goto next_level;
    }
  }

  for (int i = 0; i < NCHILD; i++) {
    if (wait() < 0) {
      fprintf(1, "wait stopped early\n");
      exit();
    }
  }

  if (wait() != -1) {
    fprintf(1, "wait got too many\n");
    exit();
  }

  if (depth > 0)
    exit();

  mtops(0);
  mtdisable("xv6-forktree");

  fprintf(1, "%d: fork tree OK\n", getpid());
  // halt();
}

int
main(void)
{
  forktree();
  exit();
}
<commit_msg>Remove mtrace enable/disable<commit_after>#include "types.h"
#include "stat.h"
#include "user.h"

#define NCHILD 2
#define NDEPTH 5

void
forktree(void)
{
  int depth = 0;

  fprintf(1, "%d: fork tree\n", getpid());

 next_level:
  //printf(1, "pid %d, depth %d\n", getpid(), depth);
  if (depth >= NDEPTH)
    exit();

  for (int i = 0; i < NCHILD; i++) {
    int pid = fork(0);
    if (pid < 0) {
      fprintf(1, "fork error\n");
      exit();
    }

    if (pid == 0) {
      depth++;
      goto next_level;
    }
  }

  for (int i = 0; i < NCHILD; i++) {
    if (wait() < 0) {
      fprintf(1, "wait stopped early\n");
      exit();
    }
  }

  if (wait() != -1) {
    fprintf(1, "wait got too many\n");
    exit();
  }

  if (depth > 0)
    exit();

  fprintf(1, "%d: fork tree OK\n", getpid());
  // halt();
}

int
main(void)
{
  forktree();
  exit();
}
<|endoftext|>


<commit_before>/*
Copyright DaiMysha (c) 2015, All rights reserved.
DaiMysha@gmail.com
https://github.com/DaiMysha

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

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

Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

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

*/

#include <iostream>

#include <SFML/OpenGL.hpp>

#include <DMUtils/sfml.hpp>

#include <LightSystem/LightSystem.hpp>

namespace DMGDVT {
namespace LS {

    const sf::RenderStates LightSystem::_multiplyState(sf::BlendMultiply);
    const sf::RenderStates LightSystem::_addState(sf::BlendAdd);
    //const sf::RenderStates LightSystem::_subtractState(sf::BlendMode(sf::BlendMode::One, sf::BlendMode::One, sf::BlendMode::ReverseSubtract));
    const sf::RenderStates LightSystem::_subtractState(sf::BlendMode(sf::BlendMode::Zero, sf::BlendMode::OneMinusSrcColor, sf::BlendMode::Add));

    LightSystem::LightSystem(bool isometric) : _ambiant(sf::Color::Black), _isometric(isometric), _autoDelete(true) {
        //this will be loaded from internal memory when lib is created
        //or loaded external crypted
        //the idea is not to allow the user to modify it
        if(!_lightAttenuationShader.loadFromFile("shaders/lightAttenuation.frag",sf::Shader::Fragment)) {
            std::cerr << "Missing light attenuation Shader. System won't work" << std::endl;
        }

    }

    LightSystem::~LightSystem() {
        reset();
    }

    void LightSystem::addLight(Light* l) {
        l->preRender(&_lightAttenuationShader);
        l->setIsometric(_isometric);//ignore what user set before
        if(l->isNegative()) _negativeLights.emplace_back(l);
        else _lights.emplace_back(l);

        std::cout << "neg size : " << _negativeLights.size() << " ; pos size : " << _lights.size() << std::endl;
    }

    void LightSystem::removeLight(Light* l) {
        if(l->isNegative()) _negativeLights.remove(l);
        else _lights.remove(l);
    }

    void LightSystem::reset() {
        if(_autoDelete) for(Light* l : _lights) delete l;

        _lights.empty();
    }

    void LightSystem::render(const sf::View& screenView, sf::RenderTarget& target) {
        debugRender(screenView,target,LightSystem::DEBUG_FLAGS::DEFAULT);
    }

    void LightSystem::debugRender(const sf::View& screenView, sf::RenderTarget& target, int flags) {
        sf::IntRect screen = DMUtils::sfml::getViewInWorldAABB(screenView);

        _sprite.setPosition(screen.left,screen.top);

        _renderTexture.clear(_ambiant);
        sf::RenderStates stAdd(_addState);
        sf::RenderStates stRm(_subtractState);
        sf::Transform t;
        t.translate(-_sprite.getPosition());
        stAdd.transform = t;
        stRm.transform = t;
        for(Light* l : _lights) {
            if(l->getAABB().intersects(screen)) {
                if(flags & DEBUG_FLAGS::SHADER_OFF) l->debugRender(_renderTexture,(stAdd));
                else l->render(screen,_renderTexture,&_lightAttenuationShader,(stAdd));
            }
        }
        for(Light* l : _negativeLights) {
            if(l->getAABB().intersects(screen)) {
                if(flags & DEBUG_FLAGS::SHADER_OFF) l->debugRender(_renderTexture,(stRm));
                else l->render(screen,_renderTexture,&_lightAttenuationShader,(stRm));
            }
        }

        _renderTexture.display();

        if(flags & DEBUG_FLAGS::LIGHTMAP_ONLY) target.clear(sf::Color::White);
    }

    void LightSystem::draw(const sf::View& screenView, sf::RenderTarget& target) {
        target.draw(_sprite,_multiplyState);
    }

    void LightSystem::drawAABB(const sf::View& screen, sf::RenderTarget& target) {
        drawAABB(DMUtils::sfml::getViewInWorldAABB(screen),target);
    }

    void LightSystem::drawAABB(const sf::IntRect& screen, sf::RenderTarget& target) {
        for(Light* l : _lights) {
            if(l->getAABB().intersects(screen)) l->drawAABB(screen,target);
        }
    }

    void LightSystem::update() {
        for(Light* l : _lights) update(l);
    }

    void LightSystem::update(Light* l) {
        bool wasNegative = l->isNegative();
        l->preRender(&_lightAttenuationShader);
        bool isNegative = l->isNegative();
        if(wasNegative xor isNegative) {
            if(isNegative) {
                _lights.remove(l);
                _negativeLights.emplace_back(l);
            } else {
                _negativeLights.remove(l);
                _lights.emplace_back(l);
            }
        }
    }

    size_t LightSystem::getLightsCount() const {
        return getNormalLightsCount() + getNegativeLightsCount();
    }

    size_t LightSystem::getNormalLightsCount() const {
        return _lights.size();
    }

    size_t LightSystem::getNegativeLightsCount() const {
        return _negativeLights.size();
    }

    sf::Image LightSystem::getLightMap() const {
        return _renderTexture.getTexture().copyToImage();
    }

    sf::Color LightSystem::getLightMapPixel(int x, int y) const {
        return getLightMap().getPixel(x,y);
    }

    sf::Color LightSystem::getLightMapPixel(sf::Vector2f p) const {
        return getLightMapPixel(p.x,p.y);
    }

    void LightSystem::setAmbiantLight(sf::Color c) {
        _ambiant = c;
    }

    sf::Color LightSystem::getAmbiantLight() const {
        return _ambiant;
    }

    void LightSystem::setIsometric(bool i) {
        _isometric = i;
        for(Light* l : _lights) {
            l->setIsometric(_isometric);
            update(l);
        }
    }

    bool LightSystem::isIsometric() const {
        return _isometric;
    }

    void LightSystem::setAutoDelete(bool ad) {
        _autoDelete = ad;
    }

    void LightSystem::setView(const sf::View& view) {
        _renderTexture.create(view.getSize().x,view.getSize().y);
        _sprite.setTexture(_renderTexture.getTexture());
    }
}
}
<commit_msg>Removed debug output<commit_after>/*
Copyright DaiMysha (c) 2015, All rights reserved.
DaiMysha@gmail.com
https://github.com/DaiMysha

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

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

Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

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

*/

#include <iostream>

#include <SFML/OpenGL.hpp>

#include <DMUtils/sfml.hpp>

#include <LightSystem/LightSystem.hpp>

namespace DMGDVT {
namespace LS {

    const sf::RenderStates LightSystem::_multiplyState(sf::BlendMultiply);
    const sf::RenderStates LightSystem::_addState(sf::BlendAdd);
    //const sf::RenderStates LightSystem::_subtractState(sf::BlendMode(sf::BlendMode::One, sf::BlendMode::One, sf::BlendMode::ReverseSubtract));
    const sf::RenderStates LightSystem::_subtractState(sf::BlendMode(sf::BlendMode::Zero, sf::BlendMode::OneMinusSrcColor, sf::BlendMode::Add));

    LightSystem::LightSystem(bool isometric) : _ambiant(sf::Color::Black), _isometric(isometric), _autoDelete(true) {
        //this will be loaded from internal memory when lib is created
        //or loaded external crypted
        //the idea is not to allow the user to modify it
        if(!_lightAttenuationShader.loadFromFile("shaders/lightAttenuation.frag",sf::Shader::Fragment)) {
            std::cerr << "Missing light attenuation Shader. System won't work" << std::endl;
        }

    }

    LightSystem::~LightSystem() {
        reset();
    }

    void LightSystem::addLight(Light* l) {
        l->preRender(&_lightAttenuationShader);
        l->setIsometric(_isometric);//ignore what user set before
        if(l->isNegative()) _negativeLights.emplace_back(l);
        else _lights.emplace_back(l);
    }

    void LightSystem::removeLight(Light* l) {
        if(l->isNegative()) _negativeLights.remove(l);
        else _lights.remove(l);
    }

    void LightSystem::reset() {
        if(_autoDelete) for(Light* l : _lights) delete l;

        _lights.empty();
    }

    void LightSystem::render(const sf::View& screenView, sf::RenderTarget& target) {
        debugRender(screenView,target,LightSystem::DEBUG_FLAGS::DEFAULT);
    }

    void LightSystem::debugRender(const sf::View& screenView, sf::RenderTarget& target, int flags) {
        sf::IntRect screen = DMUtils::sfml::getViewInWorldAABB(screenView);

        _sprite.setPosition(screen.left,screen.top);

        _renderTexture.clear(_ambiant);
        sf::RenderStates stAdd(_addState);
        sf::RenderStates stRm(_subtractState);
        sf::Transform t;
        t.translate(-_sprite.getPosition());
        stAdd.transform = t;
        stRm.transform = t;
        for(Light* l : _lights) {
            if(l->getAABB().intersects(screen)) {
                if(flags & DEBUG_FLAGS::SHADER_OFF) l->debugRender(_renderTexture,(stAdd));
                else l->render(screen,_renderTexture,&_lightAttenuationShader,(stAdd));
            }
        }
        for(Light* l : _negativeLights) {
            if(l->getAABB().intersects(screen)) {
                if(flags & DEBUG_FLAGS::SHADER_OFF) l->debugRender(_renderTexture,(stRm));
                else l->render(screen,_renderTexture,&_lightAttenuationShader,(stRm));
            }
        }

        _renderTexture.display();

        if(flags & DEBUG_FLAGS::LIGHTMAP_ONLY) target.clear(sf::Color::White);
    }

    void LightSystem::draw(const sf::View& screenView, sf::RenderTarget& target) {
        target.draw(_sprite,_multiplyState);
    }

    void LightSystem::drawAABB(const sf::View& screen, sf::RenderTarget& target) {
        drawAABB(DMUtils::sfml::getViewInWorldAABB(screen),target);
    }

    void LightSystem::drawAABB(const sf::IntRect& screen, sf::RenderTarget& target) {
        for(Light* l : _lights) {
            if(l->getAABB().intersects(screen)) l->drawAABB(screen,target);
        }
    }

    void LightSystem::update() {
        for(Light* l : _lights) update(l);
    }

    void LightSystem::update(Light* l) {
        bool wasNegative = l->isNegative();
        l->preRender(&_lightAttenuationShader);
        bool isNegative = l->isNegative();
        if(wasNegative xor isNegative) {
            if(isNegative) {
                _lights.remove(l);
                _negativeLights.emplace_back(l);
            } else {
                _negativeLights.remove(l);
                _lights.emplace_back(l);
            }
        }
    }

    size_t LightSystem::getLightsCount() const {
        return getNormalLightsCount() + getNegativeLightsCount();
    }

    size_t LightSystem::getNormalLightsCount() const {
        return _lights.size();
    }

    size_t LightSystem::getNegativeLightsCount() const {
        return _negativeLights.size();
    }

    sf::Image LightSystem::getLightMap() const {
        return _renderTexture.getTexture().copyToImage();
    }

    sf::Color LightSystem::getLightMapPixel(int x, int y) const {
        return getLightMap().getPixel(x,y);
    }

    sf::Color LightSystem::getLightMapPixel(sf::Vector2f p) const {
        return getLightMapPixel(p.x,p.y);
    }

    void LightSystem::setAmbiantLight(sf::Color c) {
        _ambiant = c;
    }

    sf::Color LightSystem::getAmbiantLight() const {
        return _ambiant;
    }

    void LightSystem::setIsometric(bool i) {
        _isometric = i;
        for(Light* l : _lights) {
            l->setIsometric(_isometric);
            update(l);
        }
    }

    bool LightSystem::isIsometric() const {
        return _isometric;
    }

    void LightSystem::setAutoDelete(bool ad) {
        _autoDelete = ad;
    }

    void LightSystem::setView(const sf::View& view) {
        _renderTexture.create(view.getSize().x,view.getSize().y);
        _sprite.setTexture(_renderTexture.getTexture());
    }
}
}
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   https://github.com/dune-community/dune-gdt
// Copyright 2010-2018 dune-gdt developers and contributors. All rights reserved.
// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//      or  GPL-2.0+ (http://opensource.org/licenses/gpl-license)
//          with "runtime exception" (http://www.dune-project.org/license.html)
// Authors:
//   Felix Schindler (2014 - 2018)
//   René Fritze     (2016, 2018)

#ifndef DUNE_GDT_EXCEPTIONS_HH
#define DUNE_GDT_EXCEPTIONS_HH

#include <dune/xt/common/exceptions.hh>
#include <dune/xt/la/exceptions.hh>
#include <dune/xt/grid/exceptions.hh>
#include <dune/xt/functions/exceptions.hh>

namespace Dune {
namespace GDT {
namespace Exceptions {

class not_bound_to_an_element_yet : public XT::Grid::Exceptions::not_bound_to_an_element_yet
{};

class dof_vector_error : public Exception
{};

class integrand_error : public Exception
{};

class assembler_error : public Exception
{};

class functional_error : public Exception
{};

class numerical_flux_error : public Exception
{};

class operator_error : public Exception
{};

class prolongation_error : public operator_error
{};

class projection_error : public operator_error
{};

class finite_element_error : public Exception
{};

class space_error : public Exception
{};

class restricted_space_error : public space_error
{};

class mapper_error : public space_error
{};

class basis_error : public space_error
{};

class discrete_function_error : public Exception
{};

class newton_error : public Exception
{};

} // namespace Exceptions
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_EXCEPTIONS_HH
<commit_msg>[exceptions] add interpolation_error<commit_after>// This file is part of the dune-gdt project:
//   https://github.com/dune-community/dune-gdt
// Copyright 2010-2018 dune-gdt developers and contributors. All rights reserved.
// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//      or  GPL-2.0+ (http://opensource.org/licenses/gpl-license)
//          with "runtime exception" (http://www.dune-project.org/license.html)
// Authors:
//   Felix Schindler (2014 - 2018)
//   René Fritze     (2016, 2018)

#ifndef DUNE_GDT_EXCEPTIONS_HH
#define DUNE_GDT_EXCEPTIONS_HH

#include <dune/xt/common/exceptions.hh>
#include <dune/xt/la/exceptions.hh>
#include <dune/xt/grid/exceptions.hh>
#include <dune/xt/functions/exceptions.hh>

namespace Dune {
namespace GDT {
namespace Exceptions {

class not_bound_to_an_element_yet : public XT::Grid::Exceptions::not_bound_to_an_element_yet
{};

class dof_vector_error : public Exception
{};

class integrand_error : public Exception
{};

class assembler_error : public Exception
{};

class functional_error : public Exception
{};

class numerical_flux_error : public Exception
{};

class operator_error : public Exception
{};

class interpolation_error : public operator_error
{};

class prolongation_error : public operator_error
{};

class projection_error : public operator_error
{};

class finite_element_error : public Exception
{};

class space_error : public Exception
{};

class restricted_space_error : public space_error
{};

class mapper_error : public space_error
{};

class basis_error : public space_error
{};

class discrete_function_error : public Exception
{};

class newton_error : public Exception
{};

} // namespace Exceptions
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_EXCEPTIONS_HH
<|endoftext|>


<commit_before>#include <QtTest>
#include <QtWidgets>
#include <DO/Graphics/DerivedQObjects/PaintingWindow.hpp>

Q_DECLARE_METATYPE(DO::Event);

using namespace DO;

class TestPaintingWindowConstructors: public QObject
{
  Q_OBJECT

private slots:
  void test_construction_of_PaintingWindow_with_small_size()
  {
    int width = 50;
    int height = 50;
    QString windowName = "painting window";
    int x = 200;
    int y = 300;

    PaintingWindow *window = new PaintingWindow(width, height,
                                                windowName,
                                                x, y);

    QCOMPARE(window->width(), width);
    QCOMPARE(window->height(), height);
    QCOMPARE(window->windowTitle(), windowName);
#ifndef __APPLE__
    // Strangely, when we have 2 monitor screens, this fails on Mac OS X...
    QCOMPARE(window->x(), x);
    QCOMPARE(window->y(), y);
#endif
    QVERIFY(window->isVisible());

    window->deleteLater();
  }

  void test_construction_of_PaintingWindow_with_size_larger_than_desktop()
  {
    int width = qApp->desktop()->width();
    int height = qApp->desktop()->height();

    PaintingWindow *window = new PaintingWindow(width, height);

    QVERIFY(window->scrollArea()->isMaximized());
    QVERIFY(window->isVisible());

    window->deleteLater();
  }
};

class TestPaintingWindowDrawMethods: public QObject
{
  Q_OBJECT

private: // data members
  PaintingWindow *test_window_;
  QImage true_image_;
  QPainter painter_;

private: // methods
  QImage get_image_from_window()
  {
    QImage image(test_window_->size(), QImage::Format_RGB32);
    test_window_->render(&image, QPoint(), QRegion(QRect(QPoint(),
                         test_window_->size())));
    return image;
  }

private slots:
  void initTestCase()
  {
    test_window_ = new PaintingWindow(300, 300);
    true_image_ =  QImage(test_window_->size(), QImage::Format_RGB32);
  }

  void init()
  {
    test_window_->clear();
    true_image_.fill(Qt::white);
    painter_.begin(&true_image_);
  }

  void cleanup()
  {
    painter_.end();
  }

  void cleanupTestCase()
  {
    test_window_->deleteLater();
  }

  void test_drawPoint_using_integer_coordinates()
  {
    int x = 150, y = 100;
    QColor color(255, 0, 0);

    test_window_->drawPoint(x, y, color);

    painter_.setPen(color);
    painter_.drawPoint(QPoint(x, y));

    QCOMPARE(get_image_from_window(), true_image_);
  }

  void test_drawPoint_using_QPointF()
  {
    double x = 150.95, y = 100.3333;
    QColor color(0, 225, 0);

    test_window_->drawPoint(QPointF(x, y), color);

    painter_.setPen(color);
    painter_.drawPoint(QPointF(x, y));

    QCOMPARE(get_image_from_window(), true_image_);
  }

  void test_drawLine_using_integer_coordinates()
  {
    int x1 = 100, y1 = 100;
    int x2 = 200, y2 = 240;
    QColor color(0, 255, 0);
    int thickness = 3;

    test_window_->drawLine(x1, y1, x2, y2, color, thickness);

    painter_.setPen(QPen(color, thickness));
    painter_.drawLine(x1, y1, x2, y2);

    QCOMPARE(get_image_from_window(), true_image_);
  }

  void test_drawLine_using_QPointF()
  {
    QPointF p1(100.350, 100.699);
    QPointF p2(203.645, 240.664);
    QColor color(0, 255, 123);
    int thickness = 4;

    test_window_->drawLine(p1, p2, color, thickness);

    painter_.setPen(QPen(color, thickness));
    painter_.drawLine(p1, p2);

    QCOMPARE(get_image_from_window(), true_image_);
  }

  void test_drawCircle_using_integer_coordinates()
  {
    int xc = 150, yc = 123;
    int r = 39;
    QColor color(0, 255, 123);
    int thickness = 4;

    test_window_->drawCircle(xc, yc, r, color, thickness);

    painter_.setPen(QPen(color, thickness));
    painter_.drawEllipse(QPoint(xc, yc), r, r);

    QCOMPARE(get_image_from_window(), true_image_);
  }

  void test_drawCircle_using_Circle_using_QPointF()
  {
    QPointF c(150.999, 123.231);
    int r = 39;
    QColor color(0, 255, 123);
    int thickness = 4;

    test_window_->drawCircle(c, r, color, thickness);

    painter_.setPen(QPen(color, thickness));
    painter_.drawEllipse(c, r, r);

    QCOMPARE(get_image_from_window(), true_image_);
  }

  void test_drawEllipse_using_axis_aligned_bounding_box()
  {
    // Axis-aligned ellipse defined by the following axis-aligned bounding box.
    int x = 150, y = 123;
    int w = 39, h = 100;
    QColor color(0, 255, 123);
    int thickness = 4;

    test_window_->drawEllipse(x, y, w, h, color, thickness);

    painter_.setPen(QPen(color, thickness));
    painter_.drawEllipse(x, y, w, h);

    QCOMPARE(get_image_from_window(), true_image_);
  }

  void test_drawEllipse_with_center_and_semi_axes_and_orientation()
  {
    QPointF center(123.123, 156.123);
    qreal r1 = 100.13, r2 = 40.12;
    qreal oriDegree = 48.65;
    QColor color(0, 255, 123);
    int thickness = 4;

    test_window_->drawEllipse(center, r1, r2, oriDegree, color, thickness);

    painter_.setPen(QPen(color, thickness));
    painter_.translate(center);
    painter_.rotate(oriDegree);
    painter_.translate(-r1, -r2);
    painter_.drawEllipse(QRectF(0, 0, 2*r1, 2*r2));

    QCOMPARE(get_image_from_window(), true_image_);
  }

  void test_drawRect()
  {
    int x = 150, y = 123;
    int w = 39, h = 100;
    QColor color(0, 255, 123);
    int thickness = 4;

    test_window_->clear();
    test_window_->drawRect(x, y, w, h, color, thickness);

    painter_.setPen(QPen(color, thickness));
    painter_.drawRect(x, y, w, h);

    QCOMPARE(get_image_from_window(), true_image_);
  }

  void test_drawPoly()
  {
    QPolygonF polygon;
    polygon << QPointF(10, 10) << QPointF(250, 20) << QPointF(150, 258);

    QColor color(0, 255, 123);
    int thickness = 4;

    test_window_->drawPoly(polygon, color, thickness);

    painter_.setPen(QPen(color, thickness));
    painter_.drawPolygon(polygon);

    QCOMPARE(get_image_from_window(), true_image_);
  }

  void test_drawText()
  {
    // What text.
    QString text("DO-CV is awesome!");
    // Where.
    int x = 130, y = 150;
    double orientation = 36.6;
    // Style.
    QColor color(0, 255, 123);
    int fontSize = 15;
    bool italic = true;
    bool bold = true;
    bool underline = true;

    test_window_->drawText(x, y, text, color, fontSize, orientation, italic,
                           bold, underline);

    painter_.setPen(color);

    QFont font;
    font.setPointSize(fontSize);
    font.setItalic(italic);
    font.setBold(bold);
    font.setUnderline(underline);
    painter_.setFont(font);

    painter_.translate(x, y);
    painter_.rotate(orientation);
    painter_.drawText(0, 0, text);

    QCOMPARE(get_image_from_window(), true_image_);
  }

  // TODO: make this test more exhaustive.
  void test_drawArrow()
  {
    int x1 = 150, y1 = 150;
    int x2 = 200, y2 = 200;

    QColor color(0, 255, 123);
    int arrowWidth = 3, arrowHeight = 5;
    int style = 0;
    int width = 3;

    test_window_->drawArrow(x1, y1, x2, y2, color, arrowWidth, arrowHeight,
                            style, width);

    QImage image(get_image_from_window());
    for (int x = 150; x < 200; ++x)
      QCOMPARE(image.pixel(x,x), color.rgb());
  }

  void test_display()
  {
    int w = 20, h = 20;
    QImage patch(QSize(w, h), QImage::Format_RGB32);
    patch.fill(Qt::red);
    int x_offset = 20, y_offset = 30;
    double zoom_factor = 2.;

    test_window_->display(patch, x_offset, y_offset, zoom_factor);

    QImage image(get_image_from_window());
    for (int y = 0; y < image.height(); ++y)
      for (int x = 0; x < image.width(); ++x)
        if ( x >= x_offset && x < x_offset+zoom_factor*w &&
             y >= y_offset && y < y_offset+zoom_factor*h )
          QCOMPARE(image.pixel(x, y), QColor(Qt::red).rgb());
        else
          QCOMPARE(image.pixel(x, y), QColor(Qt::white).rgb());
  }
};

class TestPaintingWindowEvents: public QObject
{
  Q_OBJECT

private:
  PaintingWindow *test_window_;
  QPoint mouse_pos_;
  Qt::Key key_;
  int mouse_buttons_type_id_;
  int event_type_id_;

  void compare_spied_mouse_event_arguments(QSignalSpy& spy) const
  {
    QCOMPARE(spy.count(), 1);

    QList<QVariant> arguments = spy.takeFirst();
    QCOMPARE(arguments.at(0).toInt(), mouse_pos_.x());
    QCOMPARE(arguments.at(1).toInt(), mouse_pos_.y());
    QCOMPARE(static_cast<Qt::MouseButtons>(arguments.at(2).toInt()),
             Qt::NoButton);
  }

  void compare_spied_key_event_arguments(QSignalSpy& spy) const
  {
    QCOMPARE(spy.count(), 1);

    QList<QVariant> arguments = spy.takeFirst();
    QCOMPARE(static_cast<Qt::Key>(arguments.at(0).toInt()), key_);
  }

private slots:
  void initTestCase()
  {
    mouse_buttons_type_id_ = qRegisterMetaType<Qt::MouseButtons>(
      "Qt::MouseButtons"
    );
    event_type_id_ = qRegisterMetaType<Event>("Event");
    test_window_ = new PaintingWindow(300, 300);
    mouse_pos_ = QPoint(10, 10);
    key_ = Qt::Key_A;
  }

  void cleanupTestCase()
  {
    test_window_->deleteLater();
  }

  void test_mouse_move_event()
  {
    test_window_->setMouseTracking(true);
    QSignalSpy spy(test_window_,
                   SIGNAL(movedMouse(int, int, Qt::MouseButtons)));
    QVERIFY(spy.isValid());

    QTestEventList events;
    int x = 10, y = 10;
#ifndef _WIN32
    events.addMouseMove(QPoint(x-1, y-1));
#endif
    events.addMouseMove(QPoint(x, y));
    events.simulate(test_window_);

    QTest::mouseMove(test_window_, mouse_pos_);
    compare_spied_mouse_event_arguments(spy);
  }

  void test_mouse_press_event()
  {
    QSignalSpy spy(test_window_,
                   SIGNAL(pressedMouseButtons(int, int, Qt::MouseButtons)));
    QVERIFY(spy.isValid());

    QTest::mousePress(test_window_, Qt::LeftButton, Qt::NoModifier,
                      mouse_pos_);
    compare_spied_mouse_event_arguments(spy);
  }

  void test_mouse_release_event()
  {
    QSignalSpy spy(test_window_,
                   SIGNAL(releasedMouseButtons(int, int, Qt::MouseButtons)));
    QVERIFY(spy.isValid());

    QTest::mouseRelease(test_window_, Qt::LeftButton, Qt::NoModifier,
                        mouse_pos_);
    compare_spied_mouse_event_arguments(spy);
  }

  void test_key_press_event()
  {
    QSignalSpy spy(test_window_, SIGNAL(pressedKey(int)));
    QVERIFY(spy.isValid());

    QTest::keyPress(test_window_, key_, Qt::NoModifier);
    compare_spied_key_event_arguments(spy);
  }

  void test_key_release_event()
  {
    QSignalSpy spy(test_window_, SIGNAL(releasedKey(int)));
    QVERIFY(spy.isValid());

    QTest::keyRelease(test_window_, key_, Qt::NoModifier);
    compare_spied_key_event_arguments(spy);
  }

  void test_send_event()
  {
    QSignalSpy spy(test_window_, SIGNAL(sendEvent(Event)));
    QVERIFY(spy.isValid());

    QMetaObject::invokeMethod(test_window_, "waitForEvent",
                              Qt::AutoConnection, Q_ARG(int, 1));

    // Nothing happens.
    QVERIFY(spy.wait(10));
    QCOMPARE(spy.count(), 1);
    QList<QVariant> arguments = spy.takeFirst();
    QVariant arg = arguments.at(0);
    arg.convert(event_type_id_);
    Event event(arguments.at(0).value<Event>());
    QCOMPARE(event.type, DO::NO_EVENT);
  }

};

int main(int argc, char *argv[])
{
  QApplication app(argc, argv);
  app.setAttribute(Qt::AA_Use96Dpi, true);
  QTEST_DISABLE_KEYPAD_NAVIGATION;

  int num_failed_tests = 0;

  TestPaintingWindowConstructors test_painting_window_constructors;
  num_failed_tests += QTest::qExec(&test_painting_window_constructors);

  TestPaintingWindowDrawMethods test_painting_window_draw_methods;
  num_failed_tests += QTest::qExec(&test_painting_window_draw_methods);

#ifndef DISABLE_IN_TRAVIS_CI
  // TODO: this test suite does not seem to work with Travis CI. We probably
  // need to tweak .travis.yml to make it work.
  // For now, this is disabled in travis CI.
  TestPaintingWindowEvents test_painting_window_events;
  num_failed_tests += QTest::qExec(&test_painting_window_events);
#endif

  return num_failed_tests;
}

#include "test_painting_window.moc"
<commit_msg>MAINT: renamed test case name.<commit_after>#include <QtTest>
#include <QtWidgets>
#include <DO/Graphics/DerivedQObjects/PaintingWindow.hpp>

Q_DECLARE_METATYPE(DO::Event);

using namespace DO;

class TestPaintingWindowConstructors: public QObject
{
  Q_OBJECT

private slots:
  void test_construction_of_PaintingWindow_with_small_size()
  {
    int width = 50;
    int height = 50;
    QString windowName = "painting window";
    int x = 200;
    int y = 300;

    PaintingWindow *window = new PaintingWindow(width, height,
                                                windowName,
                                                x, y);

    QCOMPARE(window->width(), width);
    QCOMPARE(window->height(), height);
    QCOMPARE(window->windowTitle(), windowName);
#ifndef __APPLE__
    // Strangely, when we have 2 monitor screens, this fails on Mac OS X...
    QCOMPARE(window->x(), x);
    QCOMPARE(window->y(), y);
#endif
    QVERIFY(window->isVisible());

    window->deleteLater();
  }

  void test_construction_of_PaintingWindow_with_size_larger_than_desktop()
  {
    int width = qApp->desktop()->width();
    int height = qApp->desktop()->height();

    PaintingWindow *window = new PaintingWindow(width, height);

    QVERIFY(window->scrollArea()->isMaximized());
    QVERIFY(window->isVisible());

    window->deleteLater();
  }
};

class TestPaintingWindowDrawingMethods: public QObject
{
  Q_OBJECT

private: // data members
  PaintingWindow *test_window_;
  QImage true_image_;
  QPainter painter_;

private: // methods
  QImage get_image_from_window()
  {
    QImage image(test_window_->size(), QImage::Format_RGB32);
    test_window_->render(&image, QPoint(), QRegion(QRect(QPoint(),
                         test_window_->size())));
    return image;
  }

private slots:
  void initTestCase()
  {
    test_window_ = new PaintingWindow(300, 300);
    true_image_ =  QImage(test_window_->size(), QImage::Format_RGB32);
  }

  void init()
  {
    test_window_->clear();
    true_image_.fill(Qt::white);
    painter_.begin(&true_image_);
  }

  void cleanup()
  {
    painter_.end();
  }

  void cleanupTestCase()
  {
    test_window_->deleteLater();
  }

  void test_drawPoint_using_integer_coordinates()
  {
    int x = 150, y = 100;
    QColor color(255, 0, 0);

    test_window_->drawPoint(x, y, color);

    painter_.setPen(color);
    painter_.drawPoint(QPoint(x, y));

    QCOMPARE(get_image_from_window(), true_image_);
  }

  void test_drawPoint_using_QPointF()
  {
    double x = 150.95, y = 100.3333;
    QColor color(0, 225, 0);

    test_window_->drawPoint(QPointF(x, y), color);

    painter_.setPen(color);
    painter_.drawPoint(QPointF(x, y));

    QCOMPARE(get_image_from_window(), true_image_);
  }

  void test_drawLine_using_integer_coordinates()
  {
    int x1 = 100, y1 = 100;
    int x2 = 200, y2 = 240;
    QColor color(0, 255, 0);
    int thickness = 3;

    test_window_->drawLine(x1, y1, x2, y2, color, thickness);

    painter_.setPen(QPen(color, thickness));
    painter_.drawLine(x1, y1, x2, y2);

    QCOMPARE(get_image_from_window(), true_image_);
  }

  void test_drawLine_using_QPointF()
  {
    QPointF p1(100.350, 100.699);
    QPointF p2(203.645, 240.664);
    QColor color(0, 255, 123);
    int thickness = 4;

    test_window_->drawLine(p1, p2, color, thickness);

    painter_.setPen(QPen(color, thickness));
    painter_.drawLine(p1, p2);

    QCOMPARE(get_image_from_window(), true_image_);
  }

  void test_drawCircle_using_integer_coordinates()
  {
    int xc = 150, yc = 123;
    int r = 39;
    QColor color(0, 255, 123);
    int thickness = 4;

    test_window_->drawCircle(xc, yc, r, color, thickness);

    painter_.setPen(QPen(color, thickness));
    painter_.drawEllipse(QPoint(xc, yc), r, r);

    QCOMPARE(get_image_from_window(), true_image_);
  }

  void test_drawCircle_using_Circle_using_QPointF()
  {
    QPointF c(150.999, 123.231);
    int r = 39;
    QColor color(0, 255, 123);
    int thickness = 4;

    test_window_->drawCircle(c, r, color, thickness);

    painter_.setPen(QPen(color, thickness));
    painter_.drawEllipse(c, r, r);

    QCOMPARE(get_image_from_window(), true_image_);
  }

  void test_drawEllipse_using_axis_aligned_bounding_box()
  {
    // Axis-aligned ellipse defined by the following axis-aligned bounding box.
    int x = 150, y = 123;
    int w = 39, h = 100;
    QColor color(0, 255, 123);
    int thickness = 4;

    test_window_->drawEllipse(x, y, w, h, color, thickness);

    painter_.setPen(QPen(color, thickness));
    painter_.drawEllipse(x, y, w, h);

    QCOMPARE(get_image_from_window(), true_image_);
  }

  void test_drawEllipse_with_center_and_semi_axes_and_orientation()
  {
    QPointF center(123.123, 156.123);
    qreal r1 = 100.13, r2 = 40.12;
    qreal oriDegree = 48.65;
    QColor color(0, 255, 123);
    int thickness = 4;

    test_window_->drawEllipse(center, r1, r2, oriDegree, color, thickness);

    painter_.setPen(QPen(color, thickness));
    painter_.translate(center);
    painter_.rotate(oriDegree);
    painter_.translate(-r1, -r2);
    painter_.drawEllipse(QRectF(0, 0, 2*r1, 2*r2));

    QCOMPARE(get_image_from_window(), true_image_);
  }

  void test_drawRect()
  {
    int x = 150, y = 123;
    int w = 39, h = 100;
    QColor color(0, 255, 123);
    int thickness = 4;

    test_window_->clear();
    test_window_->drawRect(x, y, w, h, color, thickness);

    painter_.setPen(QPen(color, thickness));
    painter_.drawRect(x, y, w, h);

    QCOMPARE(get_image_from_window(), true_image_);
  }

  void test_drawPoly()
  {
    QPolygonF polygon;
    polygon << QPointF(10, 10) << QPointF(250, 20) << QPointF(150, 258);

    QColor color(0, 255, 123);
    int thickness = 4;

    test_window_->drawPoly(polygon, color, thickness);

    painter_.setPen(QPen(color, thickness));
    painter_.drawPolygon(polygon);

    QCOMPARE(get_image_from_window(), true_image_);
  }

  void test_drawText()
  {
    // What text.
    QString text("DO-CV is awesome!");
    // Where.
    int x = 130, y = 150;
    double orientation = 36.6;
    // Style.
    QColor color(0, 255, 123);
    int fontSize = 15;
    bool italic = true;
    bool bold = true;
    bool underline = true;

    test_window_->drawText(x, y, text, color, fontSize, orientation, italic,
                           bold, underline);

    painter_.setPen(color);

    QFont font;
    font.setPointSize(fontSize);
    font.setItalic(italic);
    font.setBold(bold);
    font.setUnderline(underline);
    painter_.setFont(font);

    painter_.translate(x, y);
    painter_.rotate(orientation);
    painter_.drawText(0, 0, text);

    QCOMPARE(get_image_from_window(), true_image_);
  }

  // TODO: make this test more exhaustive.
  void test_drawArrow()
  {
    int x1 = 150, y1 = 150;
    int x2 = 200, y2 = 200;

    QColor color(0, 255, 123);
    int arrowWidth = 3, arrowHeight = 5;
    int style = 0;
    int width = 3;

    test_window_->drawArrow(x1, y1, x2, y2, color, arrowWidth, arrowHeight,
                            style, width);

    QImage image(get_image_from_window());
    for (int x = 150; x < 200; ++x)
      QCOMPARE(image.pixel(x,x), color.rgb());
  }

  void test_display()
  {
    int w = 20, h = 20;
    QImage patch(QSize(w, h), QImage::Format_RGB32);
    patch.fill(Qt::red);
    int x_offset = 20, y_offset = 30;
    double zoom_factor = 2.;

    test_window_->display(patch, x_offset, y_offset, zoom_factor);

    QImage image(get_image_from_window());
    for (int y = 0; y < image.height(); ++y)
      for (int x = 0; x < image.width(); ++x)
        if ( x >= x_offset && x < x_offset+zoom_factor*w &&
             y >= y_offset && y < y_offset+zoom_factor*h )
          QCOMPARE(image.pixel(x, y), QColor(Qt::red).rgb());
        else
          QCOMPARE(image.pixel(x, y), QColor(Qt::white).rgb());
  }
};

class TestPaintingWindowEvents: public QObject
{
  Q_OBJECT

private:
  PaintingWindow *test_window_;
  QPoint mouse_pos_;
  Qt::Key key_;
  int mouse_buttons_type_id_;
  int event_type_id_;

  void compare_spied_mouse_event_arguments(QSignalSpy& spy) const
  {
    QCOMPARE(spy.count(), 1);

    QList<QVariant> arguments = spy.takeFirst();
    QCOMPARE(arguments.at(0).toInt(), mouse_pos_.x());
    QCOMPARE(arguments.at(1).toInt(), mouse_pos_.y());
    QCOMPARE(static_cast<Qt::MouseButtons>(arguments.at(2).toInt()),
             Qt::NoButton);
  }

  void compare_spied_key_event_arguments(QSignalSpy& spy) const
  {
    QCOMPARE(spy.count(), 1);

    QList<QVariant> arguments = spy.takeFirst();
    QCOMPARE(static_cast<Qt::Key>(arguments.at(0).toInt()), key_);
  }

private slots:
  void initTestCase()
  {
    mouse_buttons_type_id_ = qRegisterMetaType<Qt::MouseButtons>(
      "Qt::MouseButtons"
    );
    event_type_id_ = qRegisterMetaType<Event>("Event");
    test_window_ = new PaintingWindow(300, 300);
    mouse_pos_ = QPoint(10, 10);
    key_ = Qt::Key_A;
  }

  void cleanupTestCase()
  {
    test_window_->deleteLater();
  }

  void test_mouse_move_event()
  {
    test_window_->setMouseTracking(true);
    QSignalSpy spy(test_window_,
                   SIGNAL(movedMouse(int, int, Qt::MouseButtons)));
    QVERIFY(spy.isValid());

    QTestEventList events;
    int x = 10, y = 10;
#ifndef _WIN32
    events.addMouseMove(QPoint(x-1, y-1));
#endif
    events.addMouseMove(QPoint(x, y));
    events.simulate(test_window_);

    QTest::mouseMove(test_window_, mouse_pos_);
    compare_spied_mouse_event_arguments(spy);
  }

  void test_mouse_press_event()
  {
    QSignalSpy spy(test_window_,
                   SIGNAL(pressedMouseButtons(int, int, Qt::MouseButtons)));
    QVERIFY(spy.isValid());

    QTest::mousePress(test_window_, Qt::LeftButton, Qt::NoModifier,
                      mouse_pos_);
    compare_spied_mouse_event_arguments(spy);
  }

  void test_mouse_release_event()
  {
    QSignalSpy spy(test_window_,
                   SIGNAL(releasedMouseButtons(int, int, Qt::MouseButtons)));
    QVERIFY(spy.isValid());

    QTest::mouseRelease(test_window_, Qt::LeftButton, Qt::NoModifier,
                        mouse_pos_);
    compare_spied_mouse_event_arguments(spy);
  }

  void test_key_press_event()
  {
    QSignalSpy spy(test_window_, SIGNAL(pressedKey(int)));
    QVERIFY(spy.isValid());

    QTest::keyPress(test_window_, key_, Qt::NoModifier);
    compare_spied_key_event_arguments(spy);
  }

  void test_key_release_event()
  {
    QSignalSpy spy(test_window_, SIGNAL(releasedKey(int)));
    QVERIFY(spy.isValid());

    QTest::keyRelease(test_window_, key_, Qt::NoModifier);
    compare_spied_key_event_arguments(spy);
  }

  void test_send_event()
  {
    QSignalSpy spy(test_window_, SIGNAL(sendEvent(Event)));
    QVERIFY(spy.isValid());

    QMetaObject::invokeMethod(test_window_, "waitForEvent",
                              Qt::AutoConnection, Q_ARG(int, 1));

    // Nothing happens.
    QVERIFY(spy.wait(10));
    QCOMPARE(spy.count(), 1);
    QList<QVariant> arguments = spy.takeFirst();
    QVariant arg = arguments.at(0);
    arg.convert(event_type_id_);
    Event event(arguments.at(0).value<Event>());
    QCOMPARE(event.type, DO::NO_EVENT);
  }

};

int main(int argc, char *argv[])
{
  QApplication app(argc, argv);
  app.setAttribute(Qt::AA_Use96Dpi, true);
  QTEST_DISABLE_KEYPAD_NAVIGATION;

  int num_failed_tests = 0;

  TestPaintingWindowConstructors test_painting_window_constructors;
  num_failed_tests += QTest::qExec(&test_painting_window_constructors);

  TestPaintingWindowDrawingMethods test_painting_window_drawing_methods;
  num_failed_tests += QTest::qExec(&test_painting_window_draw_methods);

#ifndef DISABLE_IN_TRAVIS_CI
  // TODO: this test suite does not seem to work with Travis CI. We probably
  // need to tweak .travis.yml to make it work.
  // For now, this is disabled in travis CI.
  TestPaintingWindowEvents test_painting_window_events;
  num_failed_tests += QTest::qExec(&test_painting_window_events);
#endif

  return num_failed_tests;
}

#include "test_painting_window.moc"
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

/*!
 * \file quantized_elemwise_mul.cc
 * \brief CPU Implementation of basic elementwise binary mul operators
 */
#include <mxnet/op_attr_types.h>
#include "../tensor/elemwise_binary_op-inl.h"
#include "./quantized_elemwise_mul-inl.h"
#include "./quantization_utils.h"

namespace mxnet {
namespace op {

DMLC_REGISTER_PARAMETER(QuantizeElemwiseMulParam);

inline bool QuantizedElemwiseMulOpShape(const nnvm::NodeAttrs& attrs,
                                        mxnet::ShapeVector* in_attrs,
                                        mxnet::ShapeVector* out_attrs) {
  using namespace mshadow;
  const QuantizeElemwiseMulParam& params = nnvm::get<QuantizeElemwiseMulParam>(attrs.parsed);
  const mxnet::TShape& lshape            = (*in_attrs)[quantized_elemwise_mul::kLhs];
  const mxnet::TShape& rshape            = (*in_attrs)[quantized_elemwise_mul::kRhs];
  if (!ndim_is_known(lshape) || !ndim_is_known(rshape))
    return false;
  CHECK_EQ(lshape.ndim(), rshape.ndim())
      << "Currently, quantized elemwise multiply doesn't support broadcast.";
  for (int i = 0; i < lshape.ndim(); ++i) {
    CHECK_EQ(lshape[i], rshape[i]);
  }
  SHAPE_ASSIGN_CHECK(*in_attrs, quantized_elemwise_mul::kLhsMin, mxnet::TShape(1, 1));
  SHAPE_ASSIGN_CHECK(*in_attrs, quantized_elemwise_mul::kLhsMax, mxnet::TShape(1, 1));
  SHAPE_ASSIGN_CHECK(*in_attrs, quantized_elemwise_mul::kRhsMin, mxnet::TShape(1, 1));
  SHAPE_ASSIGN_CHECK(*in_attrs, quantized_elemwise_mul::kRhsMax, mxnet::TShape(1, 1));

  SHAPE_ASSIGN_CHECK(*out_attrs, quantized_elemwise_mul::kOut, lshape);
  if (!params.enable_float_output) {
    SHAPE_ASSIGN_CHECK(*out_attrs, quantized_elemwise_mul::kOutMin, mxnet::TShape(1, 1));
    SHAPE_ASSIGN_CHECK(*out_attrs, quantized_elemwise_mul::kOutMax, mxnet::TShape(1, 1));
  }
  return true;
}

inline bool QuantizedElemwiseMulOpType(const nnvm::NodeAttrs& attrs,
                                       std::vector<int>* in_type,
                                       std::vector<int>* out_type) {
  const QuantizeElemwiseMulParam& params = nnvm::get<QuantizeElemwiseMulParam>(attrs.parsed);
  for (int i = 0; i < 2; ++i) {
    if (in_type->at(i) == mshadow::kInt8) {
      TYPE_ASSIGN_CHECK(*in_type, i, mshadow::kInt8);
    } else {
      LOG(ERROR) << "currently, quantized elemwise mul only support int8 inputs.";
    }
  }
  TYPE_ASSIGN_CHECK(*in_type, quantized_elemwise_mul::kLhsMin, mshadow::kFloat32);
  TYPE_ASSIGN_CHECK(*in_type, quantized_elemwise_mul::kLhsMax, mshadow::kFloat32);
  TYPE_ASSIGN_CHECK(*in_type, quantized_elemwise_mul::kRhsMin, mshadow::kFloat32);
  TYPE_ASSIGN_CHECK(*in_type, quantized_elemwise_mul::kRhsMax, mshadow::kFloat32);

  int dtype = mshadow::kInt32;
  if (params.max_calib_range.has_value() && params.min_calib_range.has_value()) {
    dtype = mshadow::kInt8;
  }
  if (!params.enable_float_output) {
    TYPE_ASSIGN_CHECK(*out_type, quantized_elemwise_mul::kOut, dtype);
    TYPE_ASSIGN_CHECK(*out_type, quantized_elemwise_mul::kOutMin, mshadow::kFloat32);
    TYPE_ASSIGN_CHECK(*out_type, quantized_elemwise_mul::kOutMax, mshadow::kFloat32);
  } else {
    TYPE_ASSIGN_CHECK(*out_type, quantized_elemwise_mul::kOut, mshadow::kFloat32);
  }
  return true;
}

inline bool QuantizedElemwiseMulOpStorageType(const nnvm::NodeAttrs& attrs,
                                              int dev_mask,
                                              DispatchMode* dispatch_mode,
                                              std::vector<int>* in_attrs,
                                              std::vector<int>* out_attrs) {
  using namespace common;
  *dispatch_mode = DispatchMode::kFCompute;

  for (auto& v : *out_attrs) {
    v = kDefaultStorage;
    if (common::stype_string(v).compare("unknown") == 0) {
      return false;
    }
  }

  for (auto& v : *in_attrs) {
    v = kDefaultStorage;
    if (common::stype_string(v).compare("unknown") == 0) {
      return false;
    }
  }
  return true;
}

void QuantizedElemwiseMulOpForward(const nnvm::NodeAttrs& attrs,
                                   const OpContext& ctx,
                                   const std::vector<TBlob>& inputs,
                                   const std::vector<OpReqType>& req,
                                   const std::vector<TBlob>& outputs) {
  const QuantizeElemwiseMulParam& params = nnvm::get<QuantizeElemwiseMulParam>(attrs.parsed);
  using namespace mxnet_op;

  float lhs_min = inputs[quantized_elemwise_mul::kLhsMin].dptr<float>()[0];
  float lhs_max = inputs[quantized_elemwise_mul::kLhsMax].dptr<float>()[0];
  float rhs_min = inputs[quantized_elemwise_mul::kRhsMin].dptr<float>()[0];
  float rhs_max = inputs[quantized_elemwise_mul::kRhsMax].dptr<float>()[0];

  float cached_output_min_ = 0.f;
  float cached_output_max_ = 0.f;
  float out_data_scale     = 1.f;
  float out_scale          = 1.f;
  if (!params.enable_float_output) {
    double output_data_range;
    // dataA && dataB are int8
    if (outputs[quantized_elemwise_mul::kOut].type_flag_ == mshadow::kInt8) {
      output_data_range = kInt8Range;
    } else {
      output_data_range = kInt32Range;
    }
    if (params.max_calib_range.has_value() && params.min_calib_range.has_value()) {
      cached_output_min_ = params.min_calib_range.value();
      cached_output_max_ = params.max_calib_range.value();
      out_data_scale     = output_data_range / MaxAbs(cached_output_min_, cached_output_max_);
      auto lhs_scale     = kInt8Range / MaxAbs(lhs_min, lhs_max);
      auto rhs_scale     = kInt8Range / MaxAbs(rhs_min, rhs_max);
      out_scale          = out_data_scale / lhs_scale / rhs_scale;
    } else {
      Stream<cpu>* s = ctx.get_stream<cpu>();
      if (inputs[quantized_elemwise_mul::kLhs].type_flag_ == mshadow::kInt8 &&
          inputs[quantized_elemwise_mul::kRhs].type_flag_ == mshadow::kInt8) {
        mxnet_op::Kernel<QuantizationRangeForS8S8MultiplicationStruct, cpu>::Launch(
            s, 1, &cached_output_min_, &cached_output_max_, &lhs_min, &lhs_max, &rhs_min, &rhs_max);
      } else {
        LOG(ERROR) << "lhs and rhs only support iny8 dtype.";
      }
    }
  } else {
    auto lhs_scale = kInt8Range / MaxAbs(lhs_min, lhs_max);
    auto rhs_scale = kInt8Range / MaxAbs(rhs_min, rhs_max);
    out_scale      = 1.0 / lhs_scale / rhs_scale;
  }

  size_t out_size = outputs[quantized_elemwise_mul::kOut].Size();
  auto* input_l   = inputs[quantized_elemwise_mul::kLhs].dptr<int8_t>();
  auto* input_r   = inputs[quantized_elemwise_mul::kRhs].dptr<int8_t>();
  // TODO(Xinyu): a temp solution to enable Elemwise INT8 computation,
  // will be refactored after the DNNL primitive is done.
  if (!params.enable_float_output) {
    if (params.max_calib_range.has_value() && params.min_calib_range.has_value()) {
      typedef int8_t out_type;
      auto* out_data = outputs[quantized_elemwise_mul::kOut].dptr<out_type>();
#if !defined(_MSC_VER)
#pragma omp simd
#endif
      for (size_t i = 0; i < out_size; ++i) {
        const int8_t a = input_l[i];
        const int8_t b = input_r[i];
        out_data[i]    = static_cast<out_type>(a * b * out_scale);
      }
    } else {
      using out_type = int32_t;
      auto* out_data = outputs[quantized_elemwise_mul::kOut].dptr<out_type>();
#if !defined(_MSC_VER)
#pragma omp simd
#endif
      for (size_t i = 0; i < out_size; ++i) {
        const int8_t a = input_l[i];
        const int8_t b = input_r[i];
        out_data[i]    = static_cast<out_type>(a * b * out_scale);
      }
    }
  } else {
    using out_type = float_t;
    auto* out_data = outputs[quantized_elemwise_mul::kOut].dptr<out_type>();
#if !defined(_MSC_VER)
#pragma omp simd
#endif
    for (size_t i = 0; i < out_size; ++i) {
      const int8_t a = input_l[i];
      const int8_t b = input_r[i];
      out_data[i]    = static_cast<out_type>(a * b * out_scale);
    }
  }

  if (!params.enable_float_output) {
    outputs[quantized_elemwise_mul::kOutMin].dptr<float>()[0] = cached_output_min_;
    outputs[quantized_elemwise_mul::kOutMax].dptr<float>()[0] = cached_output_max_;
  }
}

NNVM_REGISTER_OP(_contrib_quantized_elemwise_mul)
    .add_alias("_npx_quantized_elemwise_mul")
    .describe(R"code(Multiplies arguments int8 element-wise.
)code" ADD_FILELINE)
    .set_num_inputs(6)
    .set_num_outputs([](const NodeAttrs& attrs) {
      const QuantizeElemwiseMulParam& params = nnvm::get<QuantizeElemwiseMulParam>(attrs.parsed);
      return (!params.enable_float_output) ? 3 : 1;
    })
    .set_attr<nnvm::FListInputNames>(
        "FListInputNames",
        [](const NodeAttrs& attrs) {
          return std::vector<std::string>{"lhs", "rhs", "lhs_min", "lhs_max", "rhs_min", "rhs_max"};
        })
    .set_attr<mxnet::FInferShape>("FInferShape", QuantizedElemwiseMulOpShape)
    .set_attr<nnvm::FInferType>("FInferType", QuantizedElemwiseMulOpType)
    .set_attr<FInferStorageType>("FInferStorageType", QuantizedElemwiseMulOpStorageType)
    .set_attr<FResourceRequest>("FResourceRequest",
                                [](const NodeAttrs& attrs) {
                                  return std::vector<ResourceRequest>{ResourceRequest::kTempSpace};
                                })
    .set_attr<FCompute>("FCompute<cpu>", QuantizedElemwiseMulOpForward)
    // TODO(Xinyu): a temp solution to enable GluonCV INT8 flow,
    // will be reverted after the improvement of CachedOP is done.
    .set_attr<nnvm::FGradient>("FGradient", MakeZeroGradNodes)
    .set_attr<FNeedRequantize>("FNeedRequantize", [](const NodeAttrs& attrs) { return true; })
    .add_argument("lhs", "NDArray-or-Symbol", "first input")
    .add_argument("rhs", "NDArray-or-Symbol", "second input")
    .add_argument("lhs_min", "NDArray-or-Symbol", "Minimum value of first input.")
    .add_argument("lhs_max", "NDArray-or-Symbol", "Maximum value of first input.")
    .add_argument("rhs_min", "NDArray-or-Symbol", "Minimum value of second input.")
    .add_argument("rhs_max", "NDArray-or-Symbol", "Maximum value of second input.")
    .set_attr_parser(ParamParser<QuantizeElemwiseMulParam>)
    .add_arguments(QuantizeElemwiseMulParam::__FIELDS__());

NNVM_REGISTER_OP(elemwise_mul).set_attr<FQuantizedOp>("FQuantizedOp", [](const NodeAttrs& attrs) {
  nnvm::ObjectPtr node = nnvm::Node::Create();
  node->attrs.op       = Op::Get("_contrib_quantized_elemwise_mul");
  node->attrs.name     = "quantized_" + attrs.name;
  node->attrs.dict     = attrs.dict;
  if (node->op()->attr_parser != nullptr) {
    node->op()->attr_parser(&(node->attrs));
  }
  return node;
});

}  // namespace op
}  // namespace mxnet
<commit_msg>port #20926 to master (#20949)<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

/*!
 * \file quantized_elemwise_mul.cc
 * \brief CPU Implementation of basic elementwise binary mul operators
 */
#include <mxnet/op_attr_types.h>
#include "../tensor/elemwise_binary_op-inl.h"
#include "./quantized_elemwise_mul-inl.h"
#include "./quantization_utils.h"

namespace mxnet {
namespace op {

DMLC_REGISTER_PARAMETER(QuantizeElemwiseMulParam);

inline bool QuantizedElemwiseMulOpShape(const nnvm::NodeAttrs& attrs,
                                        mxnet::ShapeVector* in_attrs,
                                        mxnet::ShapeVector* out_attrs) {
  using namespace mshadow;
  const QuantizeElemwiseMulParam& params = nnvm::get<QuantizeElemwiseMulParam>(attrs.parsed);
  const mxnet::TShape& lshape            = (*in_attrs)[quantized_elemwise_mul::kLhs];
  const mxnet::TShape& rshape            = (*in_attrs)[quantized_elemwise_mul::kRhs];
  if (!ndim_is_known(lshape) || !ndim_is_known(rshape))
    return false;
  CHECK_EQ(lshape.ndim(), rshape.ndim())
      << "Currently, quantized elemwise multiply doesn't support broadcast.";
  for (int i = 0; i < lshape.ndim(); ++i) {
    CHECK_EQ(lshape[i], rshape[i]);
  }
  SHAPE_ASSIGN_CHECK(*in_attrs, quantized_elemwise_mul::kLhsMin, mxnet::TShape(1, 1));
  SHAPE_ASSIGN_CHECK(*in_attrs, quantized_elemwise_mul::kLhsMax, mxnet::TShape(1, 1));
  SHAPE_ASSIGN_CHECK(*in_attrs, quantized_elemwise_mul::kRhsMin, mxnet::TShape(1, 1));
  SHAPE_ASSIGN_CHECK(*in_attrs, quantized_elemwise_mul::kRhsMax, mxnet::TShape(1, 1));

  SHAPE_ASSIGN_CHECK(*out_attrs, quantized_elemwise_mul::kOut, lshape);
  if (!params.enable_float_output) {
    SHAPE_ASSIGN_CHECK(*out_attrs, quantized_elemwise_mul::kOutMin, mxnet::TShape(1, 1));
    SHAPE_ASSIGN_CHECK(*out_attrs, quantized_elemwise_mul::kOutMax, mxnet::TShape(1, 1));
  }
  return true;
}

inline bool QuantizedElemwiseMulOpType(const nnvm::NodeAttrs& attrs,
                                       std::vector<int>* in_type,
                                       std::vector<int>* out_type) {
  const QuantizeElemwiseMulParam& params = nnvm::get<QuantizeElemwiseMulParam>(attrs.parsed);
  for (int i = 0; i < 2; ++i) {
    if (in_type->at(i) == mshadow::kInt8) {
      TYPE_ASSIGN_CHECK(*in_type, i, mshadow::kInt8);
    } else {
      LOG(ERROR) << "currently, quantized elemwise mul only support int8 inputs.";
    }
  }
  TYPE_ASSIGN_CHECK(*in_type, quantized_elemwise_mul::kLhsMin, mshadow::kFloat32);
  TYPE_ASSIGN_CHECK(*in_type, quantized_elemwise_mul::kLhsMax, mshadow::kFloat32);
  TYPE_ASSIGN_CHECK(*in_type, quantized_elemwise_mul::kRhsMin, mshadow::kFloat32);
  TYPE_ASSIGN_CHECK(*in_type, quantized_elemwise_mul::kRhsMax, mshadow::kFloat32);

  int dtype = mshadow::kInt32;
  if (params.max_calib_range.has_value() && params.min_calib_range.has_value()) {
    dtype = mshadow::kInt8;
  }
  if (!params.enable_float_output) {
    TYPE_ASSIGN_CHECK(*out_type, quantized_elemwise_mul::kOut, dtype);
    TYPE_ASSIGN_CHECK(*out_type, quantized_elemwise_mul::kOutMin, mshadow::kFloat32);
    TYPE_ASSIGN_CHECK(*out_type, quantized_elemwise_mul::kOutMax, mshadow::kFloat32);
  } else {
    TYPE_ASSIGN_CHECK(*out_type, quantized_elemwise_mul::kOut, mshadow::kFloat32);
  }
  return true;
}

inline bool QuantizedElemwiseMulOpStorageType(const nnvm::NodeAttrs& attrs,
                                              int dev_mask,
                                              DispatchMode* dispatch_mode,
                                              std::vector<int>* in_attrs,
                                              std::vector<int>* out_attrs) {
  using namespace common;
  *dispatch_mode = DispatchMode::kFCompute;

  for (auto& v : *out_attrs) {
    v = kDefaultStorage;
    if (common::stype_string(v).compare("unknown") == 0) {
      return false;
    }
  }

  for (auto& v : *in_attrs) {
    v = kDefaultStorage;
    if (common::stype_string(v).compare("unknown") == 0) {
      return false;
    }
  }
  return true;
}

void QuantizedElemwiseMulOpForward(const nnvm::NodeAttrs& attrs,
                                   const OpContext& ctx,
                                   const std::vector<TBlob>& inputs,
                                   const std::vector<OpReqType>& req,
                                   const std::vector<TBlob>& outputs) {
  const QuantizeElemwiseMulParam& params = nnvm::get<QuantizeElemwiseMulParam>(attrs.parsed);
  using namespace mxnet_op;

  float lhs_min = inputs[quantized_elemwise_mul::kLhsMin].dptr<float>()[0];
  float lhs_max = inputs[quantized_elemwise_mul::kLhsMax].dptr<float>()[0];
  float rhs_min = inputs[quantized_elemwise_mul::kRhsMin].dptr<float>()[0];
  float rhs_max = inputs[quantized_elemwise_mul::kRhsMax].dptr<float>()[0];

  float cached_output_min_ = 0.f;
  float cached_output_max_ = 0.f;
  float out_data_scale     = 1.f;
  float out_scale          = 1.f;
  if (!params.enable_float_output) {
    double output_data_range;
    // dataA && dataB are int8
    if (outputs[quantized_elemwise_mul::kOut].type_flag_ == mshadow::kInt8) {
      output_data_range = kInt8Range;
    } else {
      output_data_range = kInt32Range;
    }
    if (params.max_calib_range.has_value() && params.min_calib_range.has_value()) {
      cached_output_min_ = params.min_calib_range.value();
      cached_output_max_ = params.max_calib_range.value();
      out_data_scale     = output_data_range / MaxAbs(cached_output_min_, cached_output_max_);
      auto lhs_scale     = kInt8Range / MaxAbs(lhs_min, lhs_max);
      auto rhs_scale     = kInt8Range / MaxAbs(rhs_min, rhs_max);
      out_scale          = out_data_scale / lhs_scale / rhs_scale;
    } else {
      Stream<cpu>* s = ctx.get_stream<cpu>();
      if (inputs[quantized_elemwise_mul::kLhs].type_flag_ == mshadow::kInt8 &&
          inputs[quantized_elemwise_mul::kRhs].type_flag_ == mshadow::kInt8) {
        mxnet_op::Kernel<QuantizationRangeForS8S8MultiplicationStruct, cpu>::Launch(
            s, 1, &cached_output_min_, &cached_output_max_, &lhs_min, &lhs_max, &rhs_min, &rhs_max);
      } else {
        LOG(ERROR) << "lhs and rhs only support iny8 dtype.";
      }
    }
  } else {
    auto lhs_scale = kInt8Range / MaxAbs(lhs_min, lhs_max);
    auto rhs_scale = kInt8Range / MaxAbs(rhs_min, rhs_max);
    out_scale      = 1.0 / lhs_scale / rhs_scale;
  }

  size_t out_size = outputs[quantized_elemwise_mul::kOut].Size();
  auto* input_l   = inputs[quantized_elemwise_mul::kLhs].dptr<int8_t>();
  auto* input_r   = inputs[quantized_elemwise_mul::kRhs].dptr<int8_t>();
  // TODO(Xinyu): a temp solution to enable Elemwise INT8 computation,
  // will be refactored after the DNNL primitive is done.
  if (!params.enable_float_output) {
    if (params.max_calib_range.has_value() && params.min_calib_range.has_value()) {
      typedef int8_t out_type;
      auto* out_data = outputs[quantized_elemwise_mul::kOut].dptr<out_type>();
#if !defined(_MSC_VER)
#pragma omp simd
#endif
      for (size_t i = 0; i < out_size; ++i) {
        const int8_t a = input_l[i];
        const int8_t b = input_r[i];
        out_data[i]    = static_cast<out_type>(a * b * out_scale);
      }
    } else {
      using out_type = int32_t;
      auto* out_data = outputs[quantized_elemwise_mul::kOut].dptr<out_type>();
#if !defined(_MSC_VER)
#pragma omp simd
#endif
      for (size_t i = 0; i < out_size; ++i) {
        const int8_t a = input_l[i];
        const int8_t b = input_r[i];
        out_data[i]    = static_cast<out_type>(a * b * out_scale);
      }
    }
  } else {
    using out_type = float;
    auto* out_data = outputs[quantized_elemwise_mul::kOut].dptr<out_type>();
#if !defined(_MSC_VER)
#pragma omp simd
#endif
    for (size_t i = 0; i < out_size; ++i) {
      const int8_t a = input_l[i];
      const int8_t b = input_r[i];
      out_data[i]    = static_cast<out_type>(a * b * out_scale);
    }
  }

  if (!params.enable_float_output) {
    outputs[quantized_elemwise_mul::kOutMin].dptr<float>()[0] = cached_output_min_;
    outputs[quantized_elemwise_mul::kOutMax].dptr<float>()[0] = cached_output_max_;
  }
}

NNVM_REGISTER_OP(_contrib_quantized_elemwise_mul)
    .add_alias("_npx_quantized_elemwise_mul")
    .describe(R"code(Multiplies arguments int8 element-wise.
)code" ADD_FILELINE)
    .set_num_inputs(6)
    .set_num_outputs([](const NodeAttrs& attrs) {
      const QuantizeElemwiseMulParam& params = nnvm::get<QuantizeElemwiseMulParam>(attrs.parsed);
      return (!params.enable_float_output) ? 3 : 1;
    })
    .set_attr<nnvm::FListInputNames>(
        "FListInputNames",
        [](const NodeAttrs& attrs) {
          return std::vector<std::string>{"lhs", "rhs", "lhs_min", "lhs_max", "rhs_min", "rhs_max"};
        })
    .set_attr<mxnet::FInferShape>("FInferShape", QuantizedElemwiseMulOpShape)
    .set_attr<nnvm::FInferType>("FInferType", QuantizedElemwiseMulOpType)
    .set_attr<FInferStorageType>("FInferStorageType", QuantizedElemwiseMulOpStorageType)
    .set_attr<FResourceRequest>("FResourceRequest",
                                [](const NodeAttrs& attrs) {
                                  return std::vector<ResourceRequest>{ResourceRequest::kTempSpace};
                                })
    .set_attr<FCompute>("FCompute<cpu>", QuantizedElemwiseMulOpForward)
    // TODO(Xinyu): a temp solution to enable GluonCV INT8 flow,
    // will be reverted after the improvement of CachedOP is done.
    .set_attr<nnvm::FGradient>("FGradient", MakeZeroGradNodes)
    .set_attr<FNeedRequantize>("FNeedRequantize", [](const NodeAttrs& attrs) { return true; })
    .add_argument("lhs", "NDArray-or-Symbol", "first input")
    .add_argument("rhs", "NDArray-or-Symbol", "second input")
    .add_argument("lhs_min", "NDArray-or-Symbol", "Minimum value of first input.")
    .add_argument("lhs_max", "NDArray-or-Symbol", "Maximum value of first input.")
    .add_argument("rhs_min", "NDArray-or-Symbol", "Minimum value of second input.")
    .add_argument("rhs_max", "NDArray-or-Symbol", "Maximum value of second input.")
    .set_attr_parser(ParamParser<QuantizeElemwiseMulParam>)
    .add_arguments(QuantizeElemwiseMulParam::__FIELDS__());

NNVM_REGISTER_OP(elemwise_mul).set_attr<FQuantizedOp>("FQuantizedOp", [](const NodeAttrs& attrs) {
  nnvm::ObjectPtr node = nnvm::Node::Create();
  node->attrs.op       = Op::Get("_contrib_quantized_elemwise_mul");
  node->attrs.name     = "quantized_" + attrs.name;
  node->attrs.dict     = attrs.dict;
  if (node->op()->attr_parser != nullptr) {
    node->op()->attr_parser(&(node->attrs));
  }
  return node;
});

}  // namespace op
}  // namespace mxnet
<|endoftext|>


<commit_before><commit_msg>fdo#42785 fix crashing again with this doc in 4-4 series<commit_after><|endoftext|>


<commit_before><commit_msg>Sketcher: Fix block constraint with several dependency groups<commit_after><|endoftext|>