<commit_before>/*
    Title:  Bitmap.  Generally used by the garbage collector to indicate allocated words

    Copyright (c) 2006  David C.J. Matthews
       Based on original code in garbage_collect.c.

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

*/

/*
   Bitmaps are used particularly in the garbage collector to indicate allocated
   words.  The efficiency of this code is crucial for the speed of the garbage
   collector.
*/

#ifdef _WIN32_WCE
#include "winceconfig.h"
#include "wincelib.h"
#else
#ifdef WIN32
#include "winconfig.h"
#else
#include "config.h"
#endif
#endif

#ifdef HAVE_ASSERT_H
#include <assert.h>
#define ASSERT(h) assert(h)
#else
#define ASSERT(h)
#endif

#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif

#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif

#include "bitmap.h"
#include "globals.h"

Bitmap::Bitmap(POLYUNSIGNED bits)
{
    POLYUNSIGNED words = (bits+BITS_PER_WORD-1) / BITS_PER_WORD;
    m_bits = (POLYUNSIGNED *)calloc(words, sizeof(POLYUNSIGNED));
}

bool Bitmap::Create(POLYUNSIGNED bits)
{
    free(m_bits);
    POLYUNSIGNED words = (bits+BITS_PER_WORD-1) / BITS_PER_WORD;
    m_bits = (POLYUNSIGNED *)calloc(words, sizeof(POLYUNSIGNED));
    return m_bits != 0;
}

Bitmap::~Bitmap()
{
    free(m_bits);
}

// Set a range of bits in a bitmap.  This checks that the bits are not already set.
void Bitmap::SetBits(POLYUNSIGNED bitno, POLYUNSIGNED length)
{
    POLYUNSIGNED word_index = bitno / BITS_PER_WORD;

    ASSERT (0 < length);

    /* Set the first part word */
    POLYUNSIGNED start_bit_index = bitno % BITS_PER_WORD;
    POLYUNSIGNED stop_bit_index  = start_bit_index + length;
    /* Do we need to change more than one word? */
    if (stop_bit_index < BITS_PER_WORD)
    {
        /* N.B.  On some machines shifts of the number of bits per word can mean
           no shift at all. */
        const POLYUNSIGNED mask1 = ((~ (POLYUNSIGNED)0)) << start_bit_index;
        const POLYUNSIGNED mask2 = ((~ (POLYUNSIGNED)0)) << stop_bit_index;
        const POLYUNSIGNED mask  = mask1 & ~mask2;

        ASSERT((m_bits[word_index] & mask) == 0);
        m_bits[word_index] |= mask;
        return;
    }
    else /* Set all the bits we can in the first word */
    {
        const POLYUNSIGNED mask  = ((POLYUNSIGNED)(~ 0)) << start_bit_index;

        ASSERT((m_bits[word_index] & mask) == 0);
        m_bits[word_index] |= mask;

        /* length = length - (BITS_PER_WORD - start_bit_index); */
        length = stop_bit_index - BITS_PER_WORD;
    }

    /* Invariant: 0 <= length */

    /* Set as many full words as possible */
    while (BITS_PER_WORD <= length)
    {
        /* Invariant: BITS_PER_WORD <= length */
        word_index ++;
        ASSERT(m_bits[word_index] == 0);
        m_bits[word_index] = ~ (POLYUNSIGNED)0;
        length -= BITS_PER_WORD;
        /* Invariant: 0 <= length */
    }

    /* Invariant: 0 <= length < BITS_PER_WORD */
    if (length == 0) return;

    /* Invariant: 0 < length < BITS_PER_WORD */

    /* Set the final part word */
    word_index ++;

    const POLYUNSIGNED mask1 = (~ (POLYUNSIGNED)0) << 0;
    const POLYUNSIGNED mask2 = (~ (POLYUNSIGNED)0) << length;
    const POLYUNSIGNED mask  = mask1 & ~mask2;

    ASSERT((m_bits[word_index] & mask) == 0);
    m_bits[word_index] |= mask;
}

void Bitmap::ClearBits(POLYUNSIGNED bitno, POLYUNSIGNED length)
{
    POLYUNSIGNED word_index = bitno / BITS_PER_WORD;

    ASSERT (0 < length);

    // Clear the first part word
    POLYUNSIGNED start_bit_index = bitno % BITS_PER_WORD;
    POLYUNSIGNED stop_bit_index  = start_bit_index + length;
    /* Do we need to change more than one word? */
    if (stop_bit_index < BITS_PER_WORD)
    {
        const POLYUNSIGNED mask1 = ((~ (POLYUNSIGNED)0)) << start_bit_index;
        const POLYUNSIGNED mask2 = ((~ (POLYUNSIGNED)0)) << stop_bit_index;
        const POLYUNSIGNED mask  = mask1 & ~mask2;
        m_bits[word_index] &= ~mask;
        return;
    }
    else /* Clear all the bits we can in the first word */
    {
        const POLYUNSIGNED mask  = ((POLYUNSIGNED)(~ 0)) << start_bit_index;
        m_bits[word_index] &= ~mask;
        length = stop_bit_index - BITS_PER_WORD;
    }

    /* Invariant: 0 <= length */

    // Clear as many full words as possible.
    while (BITS_PER_WORD <= length)
    {
        /* Invariant: BITS_PER_WORD <= length */
        word_index ++;
        m_bits[word_index] = 0;
        length -= BITS_PER_WORD;
        /* Invariant: 0 <= length */
    }

    /* Invariant: 0 <= length < BITS_PER_WORD */
    if (length == 0)
        return;

    /* Invariant: 0 < length < BITS_PER_WORD */

    // Clear the final part word
    word_index ++;

    const POLYUNSIGNED mask1 = (~ (POLYUNSIGNED)0) << 0;
    const POLYUNSIGNED mask2 = (~ (POLYUNSIGNED)0) << length;
    const POLYUNSIGNED mask  = mask1 & ~mask2;
    m_bits[word_index] &= ~mask;
}

// How many zero bits (maximum n) are there in the bitmap, starting at location start? */
POLYUNSIGNED Bitmap::CountZeroBits(POLYUNSIGNED bitno, POLYUNSIGNED n)
{
    POLYUNSIGNED *bitmap = m_bits;
    /* Less naive version */
    POLYUNSIGNED word_index = bitno / BITS_PER_WORD;
    POLYUNSIGNED bit_index  = bitno % BITS_PER_WORD;
    POLYUNSIGNED bits  = bitmap[word_index];
    POLYUNSIGNED mask  = (POLYUNSIGNED)1 << bit_index;
    POLYUNSIGNED zero_bits  = 0;
    ASSERT (0 < n);

    /* Check the first part word */
    while (mask != 0)
    {
        /* zero_bits < n */
        if ((bits & mask) != 0) return zero_bits;
        zero_bits ++;
        if (zero_bits == n) return zero_bits;
        mask <<= 1;
        /* zero_bits < n */
    }

    /* zero_bits < n */

    /* Check as many full words as possible */
    word_index ++;
    bits = bitmap[word_index];
    while (zero_bits < n && bits == 0)
    {
        zero_bits += BITS_PER_WORD;
        word_index ++;
        if (zero_bits < n) // Be careful not to go over the end
            bits = bitmap[word_index];
    }

    /* Check the final part word */
    mask = 1;
    while (zero_bits < n && ((bits & mask) == 0))
    {
        zero_bits ++;
        mask <<= 1;
    }

    return zero_bits;
}

/* search the bitmap from the high end down looking for n contiguous zeros */
POLYUNSIGNED Bitmap::FindFree
(
  POLYUNSIGNED   limit,  /* The highest numbered bit that's too small to use */
  POLYUNSIGNED   bitno,  /* The lowest numbered bit that's too large to use */
  POLYUNSIGNED   n       /* The number of consecutive zero bits required */
)
{
    if (limit + n >= bitno)
        return 0;

    POLYUNSIGNED candidate = bitno - n;
    ASSERT (bitno > limit);

    while (1)
    {
        POLYUNSIGNED bits_free = CountZeroBits(candidate, n);

        if (n <= bits_free)
            return candidate;

        if (candidate < n - bits_free + limit)
            return 0;

        candidate -= (n - bits_free);
    }
}
<commit_msg>A heap segment may possibly be completely full in which case the length for ClearBits could be zero.<commit_after>/*
    Title:  Bitmap.  Generally used by the garbage collector to indicate allocated words

    Copyright (c) 2006  David C.J. Matthews
       Based on original code in garbage_collect.c.

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

*/

/*
   Bitmaps are used particularly in the garbage collector to indicate allocated
   words.  The efficiency of this code is crucial for the speed of the garbage
   collector.
*/

#ifdef _WIN32_WCE
#include "winceconfig.h"
#include "wincelib.h"
#else
#ifdef WIN32
#include "winconfig.h"
#else
#include "config.h"
#endif
#endif

#ifdef HAVE_ASSERT_H
#include <assert.h>
#define ASSERT(h) assert(h)
#else
#define ASSERT(h)
#endif

#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif

#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif

#include "bitmap.h"
#include "globals.h"

Bitmap::Bitmap(POLYUNSIGNED bits)
{
    POLYUNSIGNED words = (bits+BITS_PER_WORD-1) / BITS_PER_WORD;
    m_bits = (POLYUNSIGNED *)calloc(words, sizeof(POLYUNSIGNED));
}

bool Bitmap::Create(POLYUNSIGNED bits)
{
    free(m_bits);
    POLYUNSIGNED words = (bits+BITS_PER_WORD-1) / BITS_PER_WORD;
    m_bits = (POLYUNSIGNED *)calloc(words, sizeof(POLYUNSIGNED));
    return m_bits != 0;
}

Bitmap::~Bitmap()
{
    free(m_bits);
}

// Set a range of bits in a bitmap.  This checks that the bits are not already set.
void Bitmap::SetBits(POLYUNSIGNED bitno, POLYUNSIGNED length)
{
    POLYUNSIGNED word_index = bitno / BITS_PER_WORD;

    ASSERT (0 < length);

    /* Set the first part word */
    POLYUNSIGNED start_bit_index = bitno % BITS_PER_WORD;
    POLYUNSIGNED stop_bit_index  = start_bit_index + length;
    /* Do we need to change more than one word? */
    if (stop_bit_index < BITS_PER_WORD)
    {
        /* N.B.  On some machines shifts of the number of bits per word can mean
           no shift at all. */
        const POLYUNSIGNED mask1 = ((~ (POLYUNSIGNED)0)) << start_bit_index;
        const POLYUNSIGNED mask2 = ((~ (POLYUNSIGNED)0)) << stop_bit_index;
        const POLYUNSIGNED mask  = mask1 & ~mask2;

        ASSERT((m_bits[word_index] & mask) == 0);
        m_bits[word_index] |= mask;
        return;
    }
    else /* Set all the bits we can in the first word */
    {
        const POLYUNSIGNED mask  = ((POLYUNSIGNED)(~ 0)) << start_bit_index;

        ASSERT((m_bits[word_index] & mask) == 0);
        m_bits[word_index] |= mask;

        /* length = length - (BITS_PER_WORD - start_bit_index); */
        length = stop_bit_index - BITS_PER_WORD;
    }

    /* Invariant: 0 <= length */

    /* Set as many full words as possible */
    while (BITS_PER_WORD <= length)
    {
        /* Invariant: BITS_PER_WORD <= length */
        word_index ++;
        ASSERT(m_bits[word_index] == 0);
        m_bits[word_index] = ~ (POLYUNSIGNED)0;
        length -= BITS_PER_WORD;
        /* Invariant: 0 <= length */
    }

    /* Invariant: 0 <= length < BITS_PER_WORD */
    if (length == 0) return;

    /* Invariant: 0 < length < BITS_PER_WORD */

    /* Set the final part word */
    word_index ++;

    const POLYUNSIGNED mask1 = (~ (POLYUNSIGNED)0) << 0;
    const POLYUNSIGNED mask2 = (~ (POLYUNSIGNED)0) << length;
    const POLYUNSIGNED mask  = mask1 & ~mask2;

    ASSERT((m_bits[word_index] & mask) == 0);
    m_bits[word_index] |= mask;
}

void Bitmap::ClearBits(POLYUNSIGNED bitno, POLYUNSIGNED length)
{
    POLYUNSIGNED word_index = bitno / BITS_PER_WORD;

    if (length == 0)
        return;

    // Clear the first part word
    POLYUNSIGNED start_bit_index = bitno % BITS_PER_WORD;
    POLYUNSIGNED stop_bit_index  = start_bit_index + length;
    /* Do we need to change more than one word? */
    if (stop_bit_index < BITS_PER_WORD)
    {
        const POLYUNSIGNED mask1 = ((~ (POLYUNSIGNED)0)) << start_bit_index;
        const POLYUNSIGNED mask2 = ((~ (POLYUNSIGNED)0)) << stop_bit_index;
        const POLYUNSIGNED mask  = mask1 & ~mask2;
        m_bits[word_index] &= ~mask;
        return;
    }
    else /* Clear all the bits we can in the first word */
    {
        const POLYUNSIGNED mask  = ((POLYUNSIGNED)(~ 0)) << start_bit_index;
        m_bits[word_index] &= ~mask;
        length = stop_bit_index - BITS_PER_WORD;
    }

    /* Invariant: 0 <= length */

    // Clear as many full words as possible.
    while (BITS_PER_WORD <= length)
    {
        /* Invariant: BITS_PER_WORD <= length */
        word_index ++;
        m_bits[word_index] = 0;
        length -= BITS_PER_WORD;
        /* Invariant: 0 <= length */
    }

    /* Invariant: 0 <= length < BITS_PER_WORD */
    if (length == 0)
        return;

    /* Invariant: 0 < length < BITS_PER_WORD */

    // Clear the final part word
    word_index ++;

    const POLYUNSIGNED mask1 = (~ (POLYUNSIGNED)0) << 0;
    const POLYUNSIGNED mask2 = (~ (POLYUNSIGNED)0) << length;
    const POLYUNSIGNED mask  = mask1 & ~mask2;
    m_bits[word_index] &= ~mask;
}

// How many zero bits (maximum n) are there in the bitmap, starting at location start? */
POLYUNSIGNED Bitmap::CountZeroBits(POLYUNSIGNED bitno, POLYUNSIGNED n)
{
    POLYUNSIGNED *bitmap = m_bits;
    /* Less naive version */
    POLYUNSIGNED word_index = bitno / BITS_PER_WORD;
    POLYUNSIGNED bit_index  = bitno % BITS_PER_WORD;
    POLYUNSIGNED bits  = bitmap[word_index];
    POLYUNSIGNED mask  = (POLYUNSIGNED)1 << bit_index;
    POLYUNSIGNED zero_bits  = 0;
    ASSERT (0 < n);

    /* Check the first part word */
    while (mask != 0)
    {
        /* zero_bits < n */
        if ((bits & mask) != 0) return zero_bits;
        zero_bits ++;
        if (zero_bits == n) return zero_bits;
        mask <<= 1;
        /* zero_bits < n */
    }

    /* zero_bits < n */

    /* Check as many full words as possible */
    word_index ++;
    bits = bitmap[word_index];
    while (zero_bits < n && bits == 0)
    {
        zero_bits += BITS_PER_WORD;
        word_index ++;
        if (zero_bits < n) // Be careful not to go over the end
            bits = bitmap[word_index];
    }

    /* Check the final part word */
    mask = 1;
    while (zero_bits < n && ((bits & mask) == 0))
    {
        zero_bits ++;
        mask <<= 1;
    }

    return zero_bits;
}

/* search the bitmap from the high end down looking for n contiguous zeros */
POLYUNSIGNED Bitmap::FindFree
(
  POLYUNSIGNED   limit,  /* The highest numbered bit that's too small to use */
  POLYUNSIGNED   bitno,  /* The lowest numbered bit that's too large to use */
  POLYUNSIGNED   n       /* The number of consecutive zero bits required */
)
{
    if (limit + n >= bitno)
        return 0;

    POLYUNSIGNED candidate = bitno - n;
    ASSERT (bitno > limit);

    while (1)
    {
        POLYUNSIGNED bits_free = CountZeroBits(candidate, n);

        if (n <= bits_free)
            return candidate;

        if (candidate < n - bits_free + limit)
            return 0;

        candidate -= (n - bits_free);
    }
}
<|endoftext|>


<commit_before>//! \file **************************************************************
//! \brief Source ressource.
//!
//! - Compilateur : GCC,MinGW
//!
//! \author Antoine Maleyrie
//! \version 0.19
//! \date 30.03.2013
//!
//! ********************************************************************

/*
*	Copyright © 2013 - Antoine Maleyrie.
*/

#include "resource.hpp"

#include <wx/jsonval.h>
#include <wx/jsonreader.h>

#include <wx/clipbrd.h>
#include <wx/sstream.h>
#include <wx/intl.h>
#include <wx/url.h>
#include <wx/log.h>

#if defined(__WXMSW__)
#include <windows.h>
#endif

//TEST
#include <iostream>

// *********************************************************************
// Class Resource
// *********************************************************************

Resource::Resource()
{
	#if defined(__UNIX__)
	#elif defined(__WXMSW__)
	#endif

	//Le menu doit être afficher (par défaut)
	_showMenu = true;

	//Volume 100%
	_ttsVolume = 1.0;

	//Par défaut on ne démarre pas l'application au démarrage.
	_powerOn = false;

	//Liste des langues
	_languages["af"] = _("Afrikaans");
	_languages["sq"] = _("Albanian");
	_languages["ar"] = _("Arabic");
	_languages["hy"] = _("Armenian");
	_languages["az"] = _("Azerbaijani");
	_languages["eu"] = _("Basque");
	_languages["be"] = _("Belarusian");
	_languages["bn"] = _("Bengali");
	_languages["bg"] = _("Bulgarian");
	_languages["ca"] = _("Catalan");
	_languages["zh-CN"] = _("Chinese");
	_languages["hr"] = _("Croatian");
	_languages["sr"] = _("Czech");
	_languages["da"] = _("Danish");
	_languages["nl"] = _("Dutch");
	_languages["en"] = _("English");
	_languages["eo"] = _("Esperanto");
	_languages["et"] = _("Estonian");
	_languages["tl"] = _("Filipino");
	_languages["fi"] = _("Finnish");
	_languages["fr"] = _("French");
	_languages["gl"] = _("Galician");
	_languages["ka"] = _("Georgian");
	_languages["de"] = _("German");
	_languages["el"] = _("Greek");
	_languages["gu"] = _("Gujarati");
	_languages["ht"] = _("Haitian Creole");
	_languages["iw"] = _("Hebrew");
	_languages["hi"] = _("Hindi");
	_languages["hu"] = _("Hungarian");
	_languages["is"] = _("Icelandic");
	_languages["id"] = _("Indonesian");
	_languages["ga"] = _("Irish");
	_languages["it"] = _("Italian");
	_languages["ja"] = _("Japanese");
	_languages["kn"] = _("Kannada");
	_languages["ko"] = _("Korean");
	_languages["lo"] = _("Lao");
	_languages["la"] = _("Latin");
	_languages["lv"] = _("Latvian");
	_languages["it"] = _("Lithuanian");
	_languages["mk"] = _("Macedonian");
	_languages["ms"] = _("Malay");
	_languages["mt"] = _("Maltese");
	_languages["no"] = _("Norwegian");
	_languages["fa"] = _("Persian");
	_languages["pl"] = _("Polish");
	_languages["pt"] = _("Portuguese");
	_languages["ro"] = _("Romanian");
	_languages["ru"] = _("Russian");
	_languages["sr"] = _("Serbian");
	_languages["sk"] = _("Slovak");
	_languages["sl"] = _("Slovenian");
	_languages["es"] = _("Spanish");
	_languages["sw"] = _("Swahili");
	_languages["sv"] = _("Swedish");
	_languages["ta"] = _("Tamil");
	_languages["te"] = _("Telugu");
	_languages["th"] = _("Thai");
	_languages["tr"] = _("Turkish");
	_languages["uk"] = _("Ukrainian");
	_languages["ur"] = _("Urdu");
	_languages["vi"] = _("Vietnamese");
	_languages["cy"] = _("Welsh");
	_languages["yi"] = _("Yiddish");

	//Liste des actions
	_actions[_("Translation")] = "ActTranslation";
	_actions[_("Translation to list")] = "ActTranslationToList";
	_actions[_("Learn a list")] = "ActLearn";
}

Resource::~Resource()
{
	#if defined(__UNIX__)
	#elif defined(__WXMSW__)
	#endif
}

std::map<wxString, wxString> const& Resource::getLanguages()const
{
	return _languages;
}

wxString Resource::abbreviationToLanguage(wxString const& abbreviation)const
{
	return _languages.at(abbreviation);
}

wxString Resource::languageToAbbreviation(wxString const& language)const
{
	for(auto &it: _languages)
	{
		if(it.second == language)
			return it.first;
	}

	return wxEmptyString;
}

std::map<wxString, wxString> const& Resource::getActions()const
{
	return _actions;
}

wxString Resource::typeToAction(wxString const& actTypeName)const
{
	for(auto &it: _actions)
	{
		if(it.second == actTypeName)
			return it.first;
	}

	return wxEmptyString;
}

wxString Resource::actionsToType(wxString const& actionName)const
{
	return _actions.at(actionName);
}

wxString Resource::getClipboard()
{
	wxString text;

	#if defined(__WXMSW__)
	//buffer ...
	INPUT input[32];
	int iinput = 0;

	//Relacher tout les tocuhes.
	for(int i = 0; i != 0xff; i++)
	{
		if(GetAsyncKeyState(i))
		{
			input[iinput].type = INPUT_KEYBOARD;
			input[iinput].ki.wVk = i;
			input[iinput].ki.wScan = 0;
			input[iinput].ki.dwFlags = KEYEVENTF_KEYUP;//released
			input[iinput].ki.time = 0;
			input[iinput].ki.dwExtraInfo = 0;
			iinput++;
		}
	}

	//Presser ctrl
	input[iinput].type = INPUT_KEYBOARD;
	input[iinput].ki.wVk = VK_CONTROL;
	input[iinput].ki.wScan = MapVirtualKey( VK_CONTROL, MAPVK_VK_TO_VSC );
	input[iinput].ki.dwFlags = 0;//pressed
	input[iinput].ki.time = 0;
	input[iinput].ki.dwExtraInfo = 0;
	iinput++;

	//Presser 'c'
	input[iinput].type = INPUT_KEYBOARD;
	input[iinput].ki.wVk =  0x43;//C key
	input[iinput].ki.wScan = 0;
	input[iinput].ki.dwFlags = 0;//pressed
	input[iinput].ki.time = 0;
	input[iinput].ki.dwExtraInfo = 0;
	iinput++;

	//Relacher 'c'
	input[iinput].type = INPUT_KEYBOARD;
	input[iinput].ki.wVk =  0x43;//C key
	input[iinput].ki.wScan = 0;
	input[iinput].ki.dwFlags = KEYEVENTF_KEYUP;//released
	input[iinput].ki.time = 0;
	input[iinput].ki.dwExtraInfo = 0;
	iinput++;

	//Relacher ctrl
	input[iinput].type = INPUT_KEYBOARD;
	input[iinput].ki.wVk = VK_CONTROL;
	input[iinput].ki.wScan = 0;
	input[iinput].ki.dwFlags = KEYEVENTF_KEYUP;//released
	input[iinput].ki.time = 0;
	input[iinput].ki.dwExtraInfo = 0;
	iinput++;

	//Simule l'appuie sur ctrl+c
	SendInput(iinput, input, sizeof(INPUT));
	Sleep(40);
	#endif

	//Lire le text de la presse papier
	if (wxTheClipboard->Open())
	{
		#if defined(__UNIX__)
		//Lire le text qui ce trouvent dans la presse papier primére.
		wxTheClipboard->UsePrimarySelection(true);
		#endif
		if (wxTheClipboard->IsSupported(wxDF_TEXT))
		{
			wxTextDataObject data;
			wxTheClipboard->GetData( data );
			text = data.GetText();
		}
		wxTheClipboard->Close();
	}

	//On enlève les éventuelle retour à la ligne en début et fin du texte.
	text.StartsWith('\n', &text);
	text.EndsWith('\n', &text);
	//On enlève les éventuelle espace en début et fin du texte.
	text.StartsWith(' ', &text);
	text.EndsWith(' ', &text);
	//On enlève les éventuelle (2eme fois) retour à la ligne en début et fin du texte.
	text.StartsWith('\n', &text);
	text.EndsWith('\n', &text);

	return text;
}

wxString Resource::getTranslations(
						std::map<wxString, wxArrayString>* translations,
						wxString const& text,
						wxString const& lgsrc,
						wxString const& lgto)
{
	//Représentent la traduction au forma json
	wxString jsonText;

	//Si il y a un texte à traduire.
	if(!text.IsEmpty())
	{
		//Télécharger la raiponce de google
		wxMemoryBuffer buffer;
		if(!Resource::getInstance()->downloadFromUrl(&buffer,"http://translate.google.com/translate_a/t?ie=UTF-8&oe=UTF-8&client=x&text="+text+"&hl="+lgto+"&sl="+lgsrc+"&tl="+lgto))
			return wxEmptyString;
		//ajouter au jsonText
		jsonText.Append(wxString::FromUTF8((const char *)buffer.GetData(), buffer.GetDataLen()));
	}
	else
		return wxEmptyString;

	//std::cout << jsonText << std::endl << std::endl;

	//Variable qui va contenir la traduction.
	wxString trans;

	//Variable pour la lecture du JSON
	wxJSONValue root;
	wxJSONReader reader;

	//Lecture du JSON
	if(reader.Parse(jsonText, &root))
	{
		wxLogError(_("The reading the JSON document was failed."));
		return wxEmptyString;
	}

	//std::cout << root.GetInfo() << std::endl;
	//wxJSONValue& sentences = root["sentences"];
	//std::cout << sentences.GetInfo() << std::endl;

	//for(int i = 0; i < sentences.Size(); i++)
		//std::cout << sentences[0]["trans"].AsString() << std::endl;

	//std::cout << root["wxWidgets"]["Version"].GetInfo() << std::endl;

	//Récupère la phrase.
	wxJSONValue& sentences = root["sentences"];

	//Récupère la traduction (principale)
	for(int i = 0; i < sentences.Size(); i++)
		trans << sentences[i]["trans"].AsString();

	////Analyser du forma jSON provenant de google (Code fonctionnelle ...)
	//wxString mainTranslate;
	//bool inSentences = false;
	//bool inSentencesTrans = false;

	//bool inDict = false;
	//bool inDictPos = false;
	//bool inDictTerms = false;

	//wxString parseText;
	//wxString proposal;
	//unsigned int accolade = 0;
	//unsigned int quote = 0;

	//for(size_t i = 0; i<jsonText.Len(); i++)
	//{
		//if(jsonText[i] == '{')
			//accolade++;
		//else if(jsonText[i] == '}')
			//accolade--;
		//else if(jsonText[i] == ':')
		//{
			//if(!parseText.IsEmpty())
			//{
				//if((accolade-1) == 0)
				//{
					//inSentences = false;
					//inDict = false;
					//if(parseText == "sentences")
						//inSentences = true;
					//else if(parseText == "dict")
						//inDict = true;
				//}
				//else if((accolade-1) == 1)
				//{
					//if(inSentences)
					//{
						//inSentencesTrans = false;
						//if(parseText == "trans")
							//inSentencesTrans = true;
					//}
					//else if(inDict)
					//{
						//inDictPos = false;
						//inDictTerms = false;
						//if(parseText == "pos")
							//inDictPos = true;
						//else if(parseText == "terms")
							//inDictTerms = true;
					//}
				//}
			//}
		//}
		//else if(jsonText[i] == ',')
		//{
			//if(!parseText.IsEmpty())
			//{
				//if(inSentencesTrans)
				//{
					////ici parseText est la traduction du text
					//mainTranslate = parseText;
				//}
				//else if(inDictPos)
				//{
					////ici parseText est la proposition
					//proposal = parseText;
					//(*translations)[proposal] = wxArrayString();
				//}
				//else if(inDictTerms)
				//{
					////ici parseText est un terme de la proposition
					//(*translations)[proposal].Add(parseText);
				//}
			//}
		//}
		//else if(jsonText[i] == '"')
		//{
			//if(quote == 0)
			//{
				//parseText.Empty();
				//quote = 1;
			//}
			//else
				//quote = 0;
		//}
		//else if(quote == 1)
		//{
			//parseText << jsonText[i];
		//}
	//}

	//return mainTranslate;

	//On retour la traduction du texte.
	return trans;
}

//! \todo ajouter une timeout
bool Resource::downloadFromUrl(wxMemoryBuffer* buffer, wxString const& sUrl)
{
	wxURL url(sUrl);

	//Erreur ?
	if (url.GetError() == wxURL_NOERR)
	{
		//Récupération des données.
		wxInputStream *urlStream = url.GetInputStream();

		if(!urlStream)
			return false;

		//Erreur ?
		if(urlStream->IsOk())
		{
			//data temporaire.
			uint8_t tmpData[1024];

			//Lie des données temps qu'il y en a.
			while(urlStream->CanRead() && !urlStream->Eof())
			{
				urlStream->Read(tmpData, 1024);
				buffer->AppendData(tmpData, urlStream->LastRead());
			}
		}
		delete urlStream;
	}

	return true;
}

void Resource::setShowMenu(bool showMenu)
{
	_showMenu = showMenu;
}

bool Resource::getShowMenu()
{
	return _showMenu;
}

//! \todo a compléter pour réellement le prendre en compte coter os.
void Resource::setPowerOn(bool powerOn)
{
	_powerOn = powerOn;
}

bool Resource::getPowerOn()
{
	return _powerOn;
}

void Resource::load(wxFileConfig& fileConfig)
{
	fileConfig.Read("show_menu", &_showMenu);
	fileConfig.Read("power_on", &_powerOn);
}

void Resource::save(wxFileConfig& fileConfig)const
{
	fileConfig.Write("show_menu", _showMenu);
	fileConfig.Write("power_on", _powerOn);
}
<commit_msg>reimplement getTranslations with wxJSON<commit_after>//! \file **************************************************************
//! \brief Source ressource.
//!
//! - Compilateur : GCC,MinGW
//!
//! \author Antoine Maleyrie
//! \version 0.19
//! \date 30.03.2013
//!
//! ********************************************************************

/*
*	Copyright © 2013 - Antoine Maleyrie.
*/

#include "resource.hpp"

#include <wx/jsonval.h>
#include <wx/jsonreader.h>

#include <wx/clipbrd.h>
#include <wx/sstream.h>
#include <wx/intl.h>
#include <wx/url.h>
#include <wx/log.h>

#if defined(__WXMSW__)
#include <windows.h>
#endif

//TEST
#include <iostream>

// *********************************************************************
// Class Resource
// *********************************************************************

Resource::Resource()
{
	#if defined(__UNIX__)
	#elif defined(__WXMSW__)
	#endif

	//Le menu doit être afficher (par défaut)
	_showMenu = true;

	//Volume 100%
	_ttsVolume = 1.0;

	//Par défaut on ne démarre pas l'application au démarrage.
	_powerOn = false;

	//Liste des langues
	_languages["af"] = _("Afrikaans");
	_languages["sq"] = _("Albanian");
	_languages["ar"] = _("Arabic");
	_languages["hy"] = _("Armenian");
	_languages["az"] = _("Azerbaijani");
	_languages["eu"] = _("Basque");
	_languages["be"] = _("Belarusian");
	_languages["bn"] = _("Bengali");
	_languages["bg"] = _("Bulgarian");
	_languages["ca"] = _("Catalan");
	_languages["zh-CN"] = _("Chinese");
	_languages["hr"] = _("Croatian");
	_languages["sr"] = _("Czech");
	_languages["da"] = _("Danish");
	_languages["nl"] = _("Dutch");
	_languages["en"] = _("English");
	_languages["eo"] = _("Esperanto");
	_languages["et"] = _("Estonian");
	_languages["tl"] = _("Filipino");
	_languages["fi"] = _("Finnish");
	_languages["fr"] = _("French");
	_languages["gl"] = _("Galician");
	_languages["ka"] = _("Georgian");
	_languages["de"] = _("German");
	_languages["el"] = _("Greek");
	_languages["gu"] = _("Gujarati");
	_languages["ht"] = _("Haitian Creole");
	_languages["iw"] = _("Hebrew");
	_languages["hi"] = _("Hindi");
	_languages["hu"] = _("Hungarian");
	_languages["is"] = _("Icelandic");
	_languages["id"] = _("Indonesian");
	_languages["ga"] = _("Irish");
	_languages["it"] = _("Italian");
	_languages["ja"] = _("Japanese");
	_languages["kn"] = _("Kannada");
	_languages["ko"] = _("Korean");
	_languages["lo"] = _("Lao");
	_languages["la"] = _("Latin");
	_languages["lv"] = _("Latvian");
	_languages["it"] = _("Lithuanian");
	_languages["mk"] = _("Macedonian");
	_languages["ms"] = _("Malay");
	_languages["mt"] = _("Maltese");
	_languages["no"] = _("Norwegian");
	_languages["fa"] = _("Persian");
	_languages["pl"] = _("Polish");
	_languages["pt"] = _("Portuguese");
	_languages["ro"] = _("Romanian");
	_languages["ru"] = _("Russian");
	_languages["sr"] = _("Serbian");
	_languages["sk"] = _("Slovak");
	_languages["sl"] = _("Slovenian");
	_languages["es"] = _("Spanish");
	_languages["sw"] = _("Swahili");
	_languages["sv"] = _("Swedish");
	_languages["ta"] = _("Tamil");
	_languages["te"] = _("Telugu");
	_languages["th"] = _("Thai");
	_languages["tr"] = _("Turkish");
	_languages["uk"] = _("Ukrainian");
	_languages["ur"] = _("Urdu");
	_languages["vi"] = _("Vietnamese");
	_languages["cy"] = _("Welsh");
	_languages["yi"] = _("Yiddish");

	//Liste des actions
	_actions[_("Translation")] = "ActTranslation";
	_actions[_("Translation to list")] = "ActTranslationToList";
	_actions[_("Learn a list")] = "ActLearn";
}

Resource::~Resource()
{
	#if defined(__UNIX__)
	#elif defined(__WXMSW__)
	#endif
}

std::map<wxString, wxString> const& Resource::getLanguages()const
{
	return _languages;
}

wxString Resource::abbreviationToLanguage(wxString const& abbreviation)const
{
	return _languages.at(abbreviation);
}

wxString Resource::languageToAbbreviation(wxString const& language)const
{
	for(auto &it: _languages)
	{
		if(it.second == language)
			return it.first;
	}

	return wxEmptyString;
}

std::map<wxString, wxString> const& Resource::getActions()const
{
	return _actions;
}

wxString Resource::typeToAction(wxString const& actTypeName)const
{
	for(auto &it: _actions)
	{
		if(it.second == actTypeName)
			return it.first;
	}

	return wxEmptyString;
}

wxString Resource::actionsToType(wxString const& actionName)const
{
	return _actions.at(actionName);
}

wxString Resource::getClipboard()
{
	wxString text;

	#if defined(__WXMSW__)
	//buffer ...
	INPUT input[32];
	int iinput = 0;

	//Relacher tout les tocuhes.
	for(int i = 0; i != 0xff; i++)
	{
		if(GetAsyncKeyState(i))
		{
			input[iinput].type = INPUT_KEYBOARD;
			input[iinput].ki.wVk = i;
			input[iinput].ki.wScan = 0;
			input[iinput].ki.dwFlags = KEYEVENTF_KEYUP;//released
			input[iinput].ki.time = 0;
			input[iinput].ki.dwExtraInfo = 0;
			iinput++;
		}
	}

	//Presser ctrl
	input[iinput].type = INPUT_KEYBOARD;
	input[iinput].ki.wVk = VK_CONTROL;
	input[iinput].ki.wScan = MapVirtualKey( VK_CONTROL, MAPVK_VK_TO_VSC );
	input[iinput].ki.dwFlags = 0;//pressed
	input[iinput].ki.time = 0;
	input[iinput].ki.dwExtraInfo = 0;
	iinput++;

	//Presser 'c'
	input[iinput].type = INPUT_KEYBOARD;
	input[iinput].ki.wVk =  0x43;//C key
	input[iinput].ki.wScan = 0;
	input[iinput].ki.dwFlags = 0;//pressed
	input[iinput].ki.time = 0;
	input[iinput].ki.dwExtraInfo = 0;
	iinput++;

	//Relacher 'c'
	input[iinput].type = INPUT_KEYBOARD;
	input[iinput].ki.wVk =  0x43;//C key
	input[iinput].ki.wScan = 0;
	input[iinput].ki.dwFlags = KEYEVENTF_KEYUP;//released
	input[iinput].ki.time = 0;
	input[iinput].ki.dwExtraInfo = 0;
	iinput++;

	//Relacher ctrl
	input[iinput].type = INPUT_KEYBOARD;
	input[iinput].ki.wVk = VK_CONTROL;
	input[iinput].ki.wScan = 0;
	input[iinput].ki.dwFlags = KEYEVENTF_KEYUP;//released
	input[iinput].ki.time = 0;
	input[iinput].ki.dwExtraInfo = 0;
	iinput++;

	//Simule l'appuie sur ctrl+c
	SendInput(iinput, input, sizeof(INPUT));
	Sleep(40);
	#endif

	//Lire le text de la presse papier
	if (wxTheClipboard->Open())
	{
		#if defined(__UNIX__)
		//Lire le text qui ce trouvent dans la presse papier primére.
		wxTheClipboard->UsePrimarySelection(true);
		#endif
		if (wxTheClipboard->IsSupported(wxDF_TEXT))
		{
			wxTextDataObject data;
			wxTheClipboard->GetData( data );
			text = data.GetText();
		}
		wxTheClipboard->Close();
	}

	//On enlève les éventuelle retour à la ligne en début et fin du texte.
	text.StartsWith('\n', &text);
	text.EndsWith('\n', &text);
	//On enlève les éventuelle espace en début et fin du texte.
	text.StartsWith(' ', &text);
	text.EndsWith(' ', &text);
	//On enlève les éventuelle (2eme fois) retour à la ligne en début et fin du texte.
	text.StartsWith('\n', &text);
	text.EndsWith('\n', &text);

	return text;
}

wxString Resource::getTranslations(
						std::map<wxString, wxArrayString>* translations,
						wxString const& text,
						wxString const& lgsrc,
						wxString const& lgto)
{
	//Représentent la traduction au forma json
	wxString jsonText;

	//Si il y a un texte à traduire.
	if(!text.IsEmpty())
	{
		//Télécharger la raiponce de google
		wxMemoryBuffer buffer;
		if(!Resource::getInstance()->downloadFromUrl(&buffer,"http://translate.google.com/translate_a/t?ie=UTF-8&oe=UTF-8&client=x&text="+text+"&hl="+lgto+"&sl="+lgsrc+"&tl="+lgto))
			return wxEmptyString;
		//ajouter au jsonText
		jsonText.Append(wxString::FromUTF8((const char *)buffer.GetData(), buffer.GetDataLen()));
	}
	else
		return wxEmptyString;

	//Variable qui va contenir la traduction.
	wxString trans;

	//Variable pour la lecture du JSON
	wxJSONValue root;
	wxJSONReader reader;

	//Lecture du JSON
	if(reader.Parse(jsonText, &root))
	{
		wxLogError(_("The reading the JSON document was failed."));
		return wxEmptyString;
	}

	//Récupère la phrase.
	wxJSONValue& sentences = root["sentences"];

	//Récupère la traduction (principale).
	for(int i = 0; i < sentences.Size(); i++)
		trans << sentences[i]["trans"].AsString();

	//Récupère le dictionnaire (Les autres traductions).
	wxJSONValue& dict = root["dict"];

	for(int i = 0; i < dict.Size(); i++)
	{
		wxString pos = dict[i]["pos"].AsString();
		wxJSONValue& terms = dict[i]["terms"];

		for(int i = 0; i < terms.Size(); i++)
		{
			(*translations)[pos].Add(terms[i].AsString());
		}
	}

	return trans;
}

//! \todo ajouter une timeout
bool Resource::downloadFromUrl(wxMemoryBuffer* buffer, wxString const& sUrl)
{
	wxURL url(sUrl);

	//Erreur ?
	if (url.GetError() == wxURL_NOERR)
	{
		//Récupération des données.
		wxInputStream *urlStream = url.GetInputStream();

		if(!urlStream)
			return false;

		//Erreur ?
		if(urlStream->IsOk())
		{
			//data temporaire.
			uint8_t tmpData[1024];

			//Lie des données temps qu'il y en a.
			while(urlStream->CanRead() && !urlStream->Eof())
			{
				urlStream->Read(tmpData, 1024);
				buffer->AppendData(tmpData, urlStream->LastRead());
			}
		}
		delete urlStream;
	}

	return true;
}

void Resource::setShowMenu(bool showMenu)
{
	_showMenu = showMenu;
}

bool Resource::getShowMenu()
{
	return _showMenu;
}

//! \todo a compléter pour réellement le prendre en compte coter os.
void Resource::setPowerOn(bool powerOn)
{
	_powerOn = powerOn;
}

bool Resource::getPowerOn()
{
	return _powerOn;
}

void Resource::load(wxFileConfig& fileConfig)
{
	fileConfig.Read("show_menu", &_showMenu);
	fileConfig.Read("power_on", &_powerOn);
}

void Resource::save(wxFileConfig& fileConfig)const
{
	fileConfig.Write("show_menu", _showMenu);
	fileConfig.Write("power_on", _powerOn);
}
<|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/compiler/mlir/lite/python/graphdef_to_tfl_flatbuffer.h"

#include <ostream>
#include <utility>

#include "llvm/Support/ToolOutputFile.h"
#include "mlir/IR/MLIRContext.h"  // TF:local_config_mlir
#include "mlir/IR/Module.h"  // TF:local_config_mlir
#include "mlir/Pass/Pass.h"  // TF:local_config_mlir
#include "mlir/Support/FileUtilities.h"  // TF:local_config_mlir
#include "mlir/Transforms/ViewOpGraph.h"  // TF:local_config_mlir
#include "tensorflow/compiler/mlir/lite/common/tfl_pass_config.h"
#include "tensorflow/compiler/mlir/lite/tf_tfl_passes.h"
#include "tensorflow/compiler/mlir/lite/tf_to_tfl_flatbuffer.h"
#include "tensorflow/compiler/mlir/tensorflow/translate/import_model.h"
#include "tensorflow/compiler/mlir/tensorflow/translate/mlir_roundtrip_flags.h"
#include "tensorflow/core/framework/graph.pb.h"
#include "tensorflow/core/framework/types.pb.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/protobuf/graph_debug_info.pb.h"
#include "tensorflow/lite/toco/model_flags.pb.h"
#include "tensorflow/lite/toco/toco_flags.pb.h"
#include "tensorflow/lite/toco/types.pb.h"
#include "tensorflow/stream_executor/lib/statusor.h"

using stream_executor::port::StatusOr;

namespace tensorflow {

namespace {
// Op def string for TFLite_Detection_PostProcess Op.
const char kDetectionPostProcessOp[] =
    "name: 'TFLite_Detection_PostProcess' input_arg: { name: "
    "'raw_outputs/box_encodings' type: DT_FLOAT } input_arg: { name: "
    "'raw_outputs/class_predictions' type: DT_FLOAT } input_arg: { name: "
    "'anchors' type: DT_FLOAT } output_arg: { name: "
    "'TFLite_Detection_PostProcess' type: DT_FLOAT } output_arg: { name: "
    "'TFLite_Detection_PostProcess:1' type: DT_FLOAT } output_arg: { name: "
    "'TFLite_Detection_PostProcess:2' type: DT_FLOAT } output_arg: { name: "
    "'TFLite_Detection_PostProcess:3' type: DT_FLOAT } attr : { name: "
    "'h_scale' type: 'float'} attr : { name: 'max_classes_per_detection' "
    "type: 'int'} attr : { name: 'max_detections' type: 'int'} attr : { "
    "name: 'nms_iou_threshold' type: 'float'} attr : { name: "
    "'nms_score_threshold' type: 'float'} attr : { name: 'num_classes' type: "
    "'int'} attr : { name: 'w_scale' type: 'float'} attr : { name: 'x_scale' "
    "type: 'float'} attr : { name: 'y_scale' type: 'float'} attr { name: "
    "'detections_per_class' type: 'int' default_value { i : 100 }} attr { "
    "name: 'use_regular_nms' type: 'bool' default_value { b : false }}";

// Converts the toco::IODataType to tensorflow::DataType. Only contains the
// conversion mapping for constants defined in TFLite Python API.
DataType ConvertIODataTypeToDataType(toco::IODataType dtype) {
  switch (dtype) {
    case toco::IODataType::FLOAT:
      return DT_FLOAT;
    case toco::IODataType::QUANTIZED_UINT8:
      return DT_QUINT8;
    case toco::IODataType::INT8:
      return DT_QINT8;
    case toco::IODataType::INT32:
      return DT_INT32;
    case toco::IODataType::INT64:
      return DT_INT64;
    case toco::IODataType::STRING:
      return DT_STRING;
    case toco::IODataType::BOOL:
      return DT_BOOL;
    default:
      return DT_INVALID;
  }
}

StatusOr<std::pair<double, double>> InputStatsToMinMax(double mean, double std,
                                                       DataType type) {
  // Only qint8 and quint8 are considered here.
  double qmin, qmax;
  if (type == DT_QUINT8) {
    qmin = 0.0;
    qmax = 255.0;
  } else if (type == DT_QINT8) {
    qmin = -128.0;
    qmax = 127.0;
  } else {
    return errors::InvalidArgument("Only int8 and uint8 are considered.");
  }
  return std::make_pair((qmin - mean) / std, (qmax - mean) / std);
}

// Give a warning for any unused flags that have been specified.
void WarningUnusedFlags(const toco::ModelFlags& model_flags,
                        const toco::TocoFlags& toco_flags) {
  if (toco_flags.output_format()) {
    LOG(WARNING) << "Ignored output_format.";
  }
  if (toco_flags.default_ranges_min() || toco_flags.default_ranges_max()) {
    LOG(WARNING) << "Ignored default_ranges_stats.";
  }
  if (toco_flags.drop_control_dependency()) {
    LOG(WARNING) << "Ignored drop_control_dependency.";
  }
  if (toco_flags.reorder_across_fake_quant()) {
    LOG(WARNING) << "Ignored reorder_across_fake_quant.";
  }
  if (model_flags.change_concat_input_ranges()) {
    LOG(WARNING) << "Ignored change_concat_input_ranges.";
  }
  if (toco_flags.dump_graphviz_include_video()) {
    LOG(WARNING) << "Ignored dump_graphviz_video.";
  }
  if (model_flags.allow_nonexistent_arrays()) {
    LOG(WARNING) << "Allow allow_nonexistent_arrays.";
  }
}

// Dumps the op graph of the `module` to `filename` in DOT format.
Status DumpOpGraphToFile(mlir::ModuleOp module, const std::string& filename) {
  std::string error_message;
  auto output = mlir::openOutputFile(filename, &error_message);
  if (!error_message.empty()) {
    return errors::InvalidArgument("Failed to open file in %s.", filename);
  }
  mlir::PassManager pm(module.getContext());
  pm.addPass(mlir::createPrintOpGraphPass(output->os()));
  if (failed(pm.run(module))) {
    return errors::Unknown("Failed to dump Op Graph from MLIR module.");
  }
  output->keep();
  return Status::OK();
}

Status RegisterCustomBuiltinOps(const std::vector<string> extra_tf_opdefs) {
  for (const auto& tf_opdefs_string : extra_tf_opdefs) {
    tensorflow::OpDef opdef;
    if (!tensorflow::protobuf::TextFormat::ParseFromString(tf_opdefs_string,
                                                           &opdef)) {
      return errors::InvalidArgument("fail to parse extra OpDef");
    }
    // Make sure the op is not already registered. If registered continue.
    const OpRegistrationData* op_reg =
        tensorflow::OpRegistry::Global()->LookUp(opdef.name());
    if (op_reg) continue;

    tensorflow::OpRegistry::Global()->Register(
        [opdef](tensorflow::OpRegistrationData* op_reg_data) -> Status {
          *op_reg_data = tensorflow::OpRegistrationData(opdef);
          return Status::OK();
        });
  }
  return Status::OK();
}

}  // namespace

Status ConvertGraphDefToTFLiteFlatBuffer(const toco::ModelFlags& model_flags,
                                         const toco::TocoFlags& toco_flags,
                                         const GraphDebugInfo& debug_info,
                                         const GraphDef& input,
                                         string* result) {
  mlir::MLIRContext context;
  GraphImportConfig specs;
  mlir::TFL::QuantizationSpecs quant_specs;

  // Parse input arrays.
  std::vector<string> node_names;
  std::vector<string> node_dtypes;
  std::vector<std::vector<int>> node_shapes;
  std::vector<double> node_mins;
  std::vector<double> node_maxs;
  quant_specs.inference_input_type =
      ConvertIODataTypeToDataType(toco_flags.inference_input_type());
  tensorflow::DataType inference_type =
      ConvertIODataTypeToDataType(toco_flags.inference_type());
  // Use non-float flag `inference_input_type` to override the `inference_type`
  // because we have to apply quantization to satisfy that.
  if (quant_specs.inference_input_type != tensorflow::DT_FLOAT) {
    inference_type = quant_specs.inference_input_type;
  }

  for (auto& flag : model_flags.input_arrays()) {
    node_names.push_back(flag.name());
    // TOCO doesn't required `data_type` to be filled for every input.
    // If it's not filled, make it an empty string so the importer will use
    // the data type in the NodeDef.
    auto toco_data_type = flag.data_type();
    if (toco_data_type == ::toco::IODataType::IO_DATA_TYPE_UNKNOWN) {
      node_dtypes.push_back("");
    } else {
      node_dtypes.push_back(
          DataType_Name(ConvertIODataTypeToDataType(toco_data_type)));
    }
    node_shapes.push_back(std::vector<int>(flag.shape().dims().begin(),
                                           flag.shape().dims().end()));
    // Currently, only UINT8 and INT8 require inputs stats
    if (inference_type == DT_QINT8 || inference_type == DT_QUINT8) {
      TF_ASSIGN_OR_RETURN(
          auto min_max, InputStatsToMinMax(flag.mean_value(), flag.std_value(),
                                           inference_type));
      node_mins.push_back(min_max.first);
      node_maxs.push_back(min_max.second);
    }
  }
  TF_RETURN_IF_ERROR(tensorflow::ParseInputArrayInfo(
      node_names, node_dtypes, node_shapes, &specs.inputs));
  if (mlir::TFL::GetInputNodeQuantSpecs(node_names, node_mins, node_maxs,
                                        inference_type, &quant_specs)) {
    return errors::InvalidArgument("Failed to get input quant spec.");
  }

  // Some extra flag related to post training quantization. If post-training
  // quantization is enabled, `inference_type` and `inference_input_type` are
  // not used by MLIR passes.
  if (toco_flags.post_training_quantize()) {
    quant_specs.weight_quantization = true;
    if (toco_flags.quantize_to_float16()) {
      quant_specs.inference_type = tensorflow::DT_HALF;
      quant_specs.inference_input_type = tensorflow::DT_HALF;
    } else {
      quant_specs.inference_type = tensorflow::DT_QINT8;
      quant_specs.inference_input_type = tensorflow::DT_QINT8;
    }
  }

  // Parse output arrays.
  std::vector<string> output_arrays(model_flags.output_arrays().begin(),
                                    model_flags.output_arrays().end());
  TF_RETURN_IF_ERROR(
      tensorflow::ParseOutputArrayInfo(output_arrays, &specs.outputs));

  // Other flags.
  bool emit_builtin_tflite_ops = !toco_flags.force_select_tf_ops();
  bool emit_select_tf_ops = toco_flags.enable_select_tf_ops();
  bool emit_custom_ops = toco_flags.allow_custom_ops();
  specs.prune_unused_nodes = true;
  specs.convert_legacy_fed_inputs = true;
  specs.graph_as_function = false;
  specs.upgrade_legacy = true;
  WarningUnusedFlags(model_flags, toco_flags);

  // Register any custom OpDefs.
  std::vector<string> extra_tf_opdefs(toco_flags.custom_opdefs().begin(),
                                      toco_flags.custom_opdefs().end());
  extra_tf_opdefs.push_back(kDetectionPostProcessOp);
  TF_RETURN_IF_ERROR(RegisterCustomBuiltinOps(extra_tf_opdefs));

  TF_ASSIGN_OR_RETURN(
      auto module, ConvertGraphdefToMlir(input, debug_info, specs, &context));

  if (toco_flags.has_dump_graphviz_dir()) {
    TF_RETURN_IF_ERROR(DumpOpGraphToFile(
        module.get(),
        // rename once we enable the new converter feature flag.
        absl::StrCat(toco_flags.dump_graphviz_dir(), "/toco_AT_IMPORT.dot")));
  }

  mlir::PassManager pm(module->getContext());
  mlir::TFL::PassConfig pass_config(quant_specs);
  pass_config.emit_builtin_tflite_ops = emit_builtin_tflite_ops;
  pass_config.lower_tensor_list_ops = true;

  tensorflow::AddTFToTFLConversionPasses(pass_config, &pm);

  auto status = ConvertTFExecutorToTFLOrFlatbuffer(
      module.get(), /*export_to_mlir=*/false, emit_builtin_tflite_ops,
      emit_select_tf_ops, emit_custom_ops, quant_specs, result, &pm);

  if (toco_flags.has_dump_graphviz_dir()) {
    TF_RETURN_IF_ERROR(DumpOpGraphToFile(
        // rename once we enable the new converter feature flag.
        module.get(), absl::StrCat(toco_flags.dump_graphviz_dir(),
                                   "/toco_AFTER_TRANSFORMATIONS.dot")));
  }

  return status;
}

}  // namespace tensorflow
<commit_msg>Fix the mnist test for keras quantization api<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/compiler/mlir/lite/python/graphdef_to_tfl_flatbuffer.h"

#include <ostream>
#include <utility>

#include "llvm/Support/ToolOutputFile.h"
#include "mlir/IR/MLIRContext.h"  // TF:local_config_mlir
#include "mlir/IR/Module.h"  // TF:local_config_mlir
#include "mlir/Pass/Pass.h"  // TF:local_config_mlir
#include "mlir/Support/FileUtilities.h"  // TF:local_config_mlir
#include "mlir/Transforms/ViewOpGraph.h"  // TF:local_config_mlir
#include "tensorflow/compiler/mlir/lite/common/tfl_pass_config.h"
#include "tensorflow/compiler/mlir/lite/tf_tfl_passes.h"
#include "tensorflow/compiler/mlir/lite/tf_to_tfl_flatbuffer.h"
#include "tensorflow/compiler/mlir/tensorflow/translate/import_model.h"
#include "tensorflow/compiler/mlir/tensorflow/translate/mlir_roundtrip_flags.h"
#include "tensorflow/core/framework/graph.pb.h"
#include "tensorflow/core/framework/types.pb.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/protobuf/graph_debug_info.pb.h"
#include "tensorflow/lite/toco/model_flags.pb.h"
#include "tensorflow/lite/toco/toco_flags.pb.h"
#include "tensorflow/lite/toco/types.pb.h"
#include "tensorflow/stream_executor/lib/statusor.h"

using stream_executor::port::StatusOr;

namespace tensorflow {

namespace {
// Op def string for TFLite_Detection_PostProcess Op.
const char kDetectionPostProcessOp[] =
    "name: 'TFLite_Detection_PostProcess' input_arg: { name: "
    "'raw_outputs/box_encodings' type: DT_FLOAT } input_arg: { name: "
    "'raw_outputs/class_predictions' type: DT_FLOAT } input_arg: { name: "
    "'anchors' type: DT_FLOAT } output_arg: { name: "
    "'TFLite_Detection_PostProcess' type: DT_FLOAT } output_arg: { name: "
    "'TFLite_Detection_PostProcess:1' type: DT_FLOAT } output_arg: { name: "
    "'TFLite_Detection_PostProcess:2' type: DT_FLOAT } output_arg: { name: "
    "'TFLite_Detection_PostProcess:3' type: DT_FLOAT } attr : { name: "
    "'h_scale' type: 'float'} attr : { name: 'max_classes_per_detection' "
    "type: 'int'} attr : { name: 'max_detections' type: 'int'} attr : { "
    "name: 'nms_iou_threshold' type: 'float'} attr : { name: "
    "'nms_score_threshold' type: 'float'} attr : { name: 'num_classes' type: "
    "'int'} attr : { name: 'w_scale' type: 'float'} attr : { name: 'x_scale' "
    "type: 'float'} attr : { name: 'y_scale' type: 'float'} attr { name: "
    "'detections_per_class' type: 'int' default_value { i : 100 }} attr { "
    "name: 'use_regular_nms' type: 'bool' default_value { b : false }}";

// Converts the toco::IODataType to tensorflow::DataType. Only contains the
// conversion mapping for constants defined in TFLite Python API.
DataType ConvertIODataTypeToDataType(toco::IODataType dtype) {
  switch (dtype) {
    case toco::IODataType::FLOAT:
      return DT_FLOAT;
    case toco::IODataType::QUANTIZED_UINT8:
      return DT_QUINT8;
    case toco::IODataType::INT8:
      return DT_QINT8;
    case toco::IODataType::INT32:
      return DT_INT32;
    case toco::IODataType::INT64:
      return DT_INT64;
    case toco::IODataType::STRING:
      return DT_STRING;
    case toco::IODataType::BOOL:
      return DT_BOOL;
    default:
      return DT_INVALID;
  }
}

StatusOr<std::pair<double, double>> InputStatsToMinMax(double mean, double std,
                                                       DataType type) {
  // Only qint8 and quint8 are considered here.
  double qmin, qmax;
  if (type == DT_QUINT8) {
    qmin = 0.0;
    qmax = 255.0;
  } else if (type == DT_QINT8) {
    qmin = -128.0;
    qmax = 127.0;
  } else {
    return errors::InvalidArgument("Only int8 and uint8 are considered.");
  }
  return std::make_pair((qmin - mean) / std, (qmax - mean) / std);
}

// Give a warning for any unused flags that have been specified.
void WarningUnusedFlags(const toco::ModelFlags& model_flags,
                        const toco::TocoFlags& toco_flags) {
  if (toco_flags.output_format()) {
    LOG(WARNING) << "Ignored output_format.";
  }
  if (toco_flags.default_ranges_min() || toco_flags.default_ranges_max()) {
    LOG(WARNING) << "Ignored default_ranges_stats.";
  }
  if (toco_flags.drop_control_dependency()) {
    LOG(WARNING) << "Ignored drop_control_dependency.";
  }
  if (toco_flags.reorder_across_fake_quant()) {
    LOG(WARNING) << "Ignored reorder_across_fake_quant.";
  }
  if (model_flags.change_concat_input_ranges()) {
    LOG(WARNING) << "Ignored change_concat_input_ranges.";
  }
  if (toco_flags.dump_graphviz_include_video()) {
    LOG(WARNING) << "Ignored dump_graphviz_video.";
  }
  if (model_flags.allow_nonexistent_arrays()) {
    LOG(WARNING) << "Allow allow_nonexistent_arrays.";
  }
}

// Dumps the op graph of the `module` to `filename` in DOT format.
Status DumpOpGraphToFile(mlir::ModuleOp module, const std::string& filename) {
  std::string error_message;
  auto output = mlir::openOutputFile(filename, &error_message);
  if (!error_message.empty()) {
    return errors::InvalidArgument("Failed to open file in %s.", filename);
  }
  mlir::PassManager pm(module.getContext());
  pm.addPass(mlir::createPrintOpGraphPass(output->os()));
  if (failed(pm.run(module))) {
    return errors::Unknown("Failed to dump Op Graph from MLIR module.");
  }
  output->keep();
  return Status::OK();
}

Status RegisterCustomBuiltinOps(const std::vector<string> extra_tf_opdefs) {
  for (const auto& tf_opdefs_string : extra_tf_opdefs) {
    tensorflow::OpDef opdef;
    if (!tensorflow::protobuf::TextFormat::ParseFromString(tf_opdefs_string,
                                                           &opdef)) {
      return errors::InvalidArgument("fail to parse extra OpDef");
    }
    // Make sure the op is not already registered. If registered continue.
    const OpRegistrationData* op_reg =
        tensorflow::OpRegistry::Global()->LookUp(opdef.name());
    if (op_reg) continue;

    tensorflow::OpRegistry::Global()->Register(
        [opdef](tensorflow::OpRegistrationData* op_reg_data) -> Status {
          *op_reg_data = tensorflow::OpRegistrationData(opdef);
          return Status::OK();
        });
  }
  return Status::OK();
}

}  // namespace

Status ConvertGraphDefToTFLiteFlatBuffer(const toco::ModelFlags& model_flags,
                                         const toco::TocoFlags& toco_flags,
                                         const GraphDebugInfo& debug_info,
                                         const GraphDef& input,
                                         string* result) {
  mlir::MLIRContext context;
  GraphImportConfig specs;
  mlir::TFL::QuantizationSpecs quant_specs;

  // Parse input arrays.
  std::vector<string> node_names;
  std::vector<string> node_dtypes;
  std::vector<std::vector<int>> node_shapes;
  std::vector<double> node_mins;
  std::vector<double> node_maxs;
  quant_specs.inference_input_type =
      ConvertIODataTypeToDataType(toco_flags.inference_input_type());
  tensorflow::DataType inference_type =
      ConvertIODataTypeToDataType(toco_flags.inference_type());
  // Use non-float flag `inference_input_type` to override the `inference_type`
  // because we have to apply quantization to satisfy that.
  if (quant_specs.inference_input_type != tensorflow::DT_FLOAT) {
    inference_type = quant_specs.inference_input_type;
  }

  for (auto& flag : model_flags.input_arrays()) {
    node_names.push_back(flag.name());
    // TOCO doesn't required `data_type` to be filled for every input.
    // If it's not filled, make it an empty string so the importer will use
    // the data type in the NodeDef.
    auto toco_data_type = flag.data_type();
    if (toco_data_type == ::toco::IODataType::IO_DATA_TYPE_UNKNOWN) {
      node_dtypes.push_back("");
    } else {
      node_dtypes.push_back(
          DataType_Name(ConvertIODataTypeToDataType(toco_data_type)));
    }
    node_shapes.push_back(std::vector<int>(flag.shape().dims().begin(),
                                           flag.shape().dims().end()));
    // Currently, only UINT8 and INT8 require inputs stats
    if (inference_type == DT_QINT8 || inference_type == DT_QUINT8) {
      TF_ASSIGN_OR_RETURN(
          auto min_max, InputStatsToMinMax(flag.mean_value(), flag.std_value(),
                                           inference_type));
      node_mins.push_back(min_max.first);
      node_maxs.push_back(min_max.second);
    }
  }
  TF_RETURN_IF_ERROR(tensorflow::ParseInputArrayInfo(
      node_names, node_dtypes, node_shapes, &specs.inputs));
  if (mlir::TFL::GetInputNodeQuantSpecs(node_names, node_mins, node_maxs,
                                        inference_type, &quant_specs)) {
    return errors::InvalidArgument("Failed to get input quant spec.");
  }

  // Some extra flag related to post training quantization. If post-training
  // quantization is enabled, `inference_type` and `inference_input_type` are
  // not used by MLIR passes.
  if (toco_flags.post_training_quantize()) {
    quant_specs.weight_quantization = true;
    if (toco_flags.quantize_to_float16()) {
      quant_specs.inference_type = tensorflow::DT_HALF;
      quant_specs.inference_input_type = tensorflow::DT_HALF;
    } else {
      quant_specs.inference_type = tensorflow::DT_QINT8;
      quant_specs.inference_input_type = tensorflow::DT_QINT8;
    }
  }

  // Parse output arrays.
  std::vector<string> output_arrays(model_flags.output_arrays().begin(),
                                    model_flags.output_arrays().end());
  TF_RETURN_IF_ERROR(
      tensorflow::ParseOutputArrayInfo(output_arrays, &specs.outputs));

  // Other flags.
  bool emit_builtin_tflite_ops = !toco_flags.force_select_tf_ops();
  bool emit_select_tf_ops = toco_flags.enable_select_tf_ops();
  bool emit_custom_ops = toco_flags.allow_custom_ops();
  specs.prune_unused_nodes = true;
  specs.convert_legacy_fed_inputs = true;
  specs.graph_as_function = false;
  specs.upgrade_legacy = true;
  WarningUnusedFlags(model_flags, toco_flags);

  // Register any custom OpDefs.
  std::vector<string> extra_tf_opdefs(toco_flags.custom_opdefs().begin(),
                                      toco_flags.custom_opdefs().end());
  extra_tf_opdefs.push_back(kDetectionPostProcessOp);
  TF_RETURN_IF_ERROR(RegisterCustomBuiltinOps(extra_tf_opdefs));

  TF_ASSIGN_OR_RETURN(
      auto module, ConvertGraphdefToMlir(input, debug_info, specs, &context));

  if (toco_flags.has_dump_graphviz_dir()) {
    TF_RETURN_IF_ERROR(DumpOpGraphToFile(
        module.get(),
        // rename once we enable the new converter feature flag.
        absl::StrCat(toco_flags.dump_graphviz_dir(), "/toco_AT_IMPORT.dot")));
  }

  mlir::PassManager pm(module->getContext());
  mlir::TFL::PassConfig pass_config(quant_specs);
  pass_config.emit_builtin_tflite_ops = emit_builtin_tflite_ops;
  pass_config.lower_tensor_list_ops = true;

  tensorflow::AddTFToTFLConversionPasses(pass_config, &pm);

  auto status = ConvertTFExecutorToTFLOrFlatbuffer(
      module.get(), /*export_to_mlir=*/false, emit_builtin_tflite_ops,
      emit_select_tf_ops, emit_custom_ops, quant_specs, result, &pm);
  if (toco_flags.has_dump_graphviz_dir()) {
    TF_RETURN_IF_ERROR(DumpOpGraphToFile(
        // rename once we enable the new converter feature flag.
        module.get(), absl::StrCat(toco_flags.dump_graphviz_dir(),
                                   "/toco_AFTER_TRANSFORMATIONS.dot")));
  }

  return status;
}

}  // namespace tensorflow
<|endoftext|>


<commit_before>/* Copyright 2021 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 <array>
#include <string>

#include "llvm/Support/FormatVariadic.h"
#include "tensorflow/compiler/mlir/tfrt/benchmarks/benchmark_mlir_function.h"

namespace tensorflow {

static const char* mlir_2d_input = R"(
func @compute(%arg0: tensor<?x?xf32>) -> tensor<?x?xf32> {{
    %0 = "tf.Const"()
         {{value = dense<[1, 0]> : tensor<2xi64>,
          device = "/job:localhost/replica:0/task:0/device:CPU:0"}
         : () -> tensor<2xi64>
    %1 = "tf.Transpose"(%arg0, %0)
         {{device = "/job:localhost/replica:0/task:0/device:CPU:0"}
         : (tensor<?x?xf32>, tensor<2xi64>) -> tensor<?x?xf32>
    return %1 : tensor<?x?xf32>
  }
)";

static const char* mlir_3d_input = R"(
func @compute(%arg0: tensor<?x?x?xf32>) -> tensor<?x?x?xf32> {{
    %0 = "tf.Const"()
         {{value = dense<[{0}, {1}, {2}]> : tensor<3xi64>,
          device = "/job:localhost/replica:0/task:0/device:CPU:0"}
         : () -> tensor<3xi64>
    %1 = "tf.Transpose"(%arg0, %0)
         {{device = "/job:localhost/replica:0/task:0/device:CPU:0"}
         : (tensor<?x?x?xf32>, tensor<3xi64>) -> tensor<?x?x?xf32>
    return %1 : tensor<?x?x?xf32>
  }
)";

static std::string Transpose2D() { return llvm::formatv(mlir_2d_input); }

static std::string Transpose3D(std::array<int32_t, 3> perm) {
  return llvm::formatv(mlir_3d_input, perm[0], perm[1], perm[2]);
}

template <int32_t size>
static auto Shuffle(std::array<int32_t, size> perm) {
  return [perm](llvm::ArrayRef<Tensor> inputs,
                llvm::Optional<Eigen::ThreadPoolDevice> device) {
    std::array<int64_t, size> shuffled;
    for (unsigned d = 0; d < size; d++)
      shuffled[d] = inputs[0].dim_size(perm[d]);

    Tensor output(DT_FLOAT, TensorShape(shuffled));

    auto in0 = inputs[0].tensor<float, size>();
    auto out0 = output.tensor<float, size>();

    if (device.hasValue()) {
      out0.device(*device) = in0.shuffle(perm);
    } else {
      out0 = in0.shuffle(perm);
    }
  };
}

static llvm::SmallVector<InputTensorSpec> Inputs(llvm::ArrayRef<ssize_t> dims) {
  return {InputTensorSpec(DT_FLOAT, dims)};
}

#define BM(FN) BM_##FN->Arg(0)->Arg(4)->Arg(8);

// Small 2D Transpose: [1, 0]
BM(Jitrt(Transpose_small_1x0, Transpose2D(), "compute", Inputs({128, 128})));
BM(JitrtV(Transpose_small_1x0, Transpose2D(), "compute", Inputs({128, 128})));
BM(Tfrt(Transpose_small_1x0, Transpose2D(), "compute", Inputs({128, 128})));
BM(Eigen(Transpose_small_1x0, Shuffle<2>({1, 0}), Inputs({128, 128})));

// Small 3D Transpose: [0, 2, 1]
BM(Jitrt(Transpose_small_0x2x1, Transpose3D({0, 2, 1}), "compute",
         Inputs({32, 32, 16})));
BM(JitrtV(Transpose_small_0x2x1, Transpose3D({0, 2, 1}), "compute",
          Inputs({32, 32, 16})));
BM(Tfrt(Transpose_small_0x2x1, Transpose3D({0, 2, 1}), "compute",
        Inputs({32, 32, 16})));
BM(Eigen(Transpose_small_0x2x1, Shuffle<3>({0, 2, 1}), Inputs({32, 32, 16})));

// Small 3D Transpose: [2, 0, 1]
BM(Jitrt(Transpose_small_2x0x1, Transpose3D({2, 0, 1}), "compute",
         Inputs({32, 32, 16})));
BM(JitrtV(Transpose_small_2x0x1, Transpose3D({2, 0, 1}), "compute",
          Inputs({32, 32, 16})));
BM(Tfrt(Transpose_small_2x0x1, Transpose3D({2, 0, 1}), "compute",
        Inputs({32, 32, 16})));
BM(Eigen(Transpose_small_2x0x1, Shuffle<3>({2, 0, 1}), Inputs({32, 32, 16})));

// Small 3D Transpose: [2, 1, 0]
BM(Jitrt(Transpose_small_2x1x0, Transpose3D({2, 1, 0}), "compute",
         Inputs({32, 32, 16})));
BM(JitrtV(Transpose_small_2x1x0, Transpose3D({2, 1, 0}), "compute",
          Inputs({32, 32, 16})));
BM(Tfrt(Transpose_small_2x1x0, Transpose3D({2, 1, 0}), "compute",
        Inputs({32, 32, 16})));
BM(Eigen(Transpose_small_2x1x0, Shuffle<3>({2, 1, 0}), Inputs({32, 32, 16})));

// Small 3D Transpose: [1, 2, 0]
BM(Jitrt(Transpose_small_1x2x0, Transpose3D({1, 2, 0}), "compute",
         Inputs({32, 32, 16})));
BM(JitrtV(Transpose_small_1x2x0, Transpose3D({1, 2, 0}), "compute",
          Inputs({32, 32, 16})));
BM(Tfrt(Transpose_small_1x2x0, Transpose3D({1, 2, 0}), "compute",
        Inputs({32, 32, 16})));
BM(Eigen(Transpose_small_1x2x0, Shuffle<3>({1, 2, 0}), Inputs({32, 32, 16})));

// 2D Transpose: [1, 0]
BM(Jitrt(Transpose_1x0, Transpose2D(), "compute", Inputs({4096, 4096})));
BM(JitrtV(Transpose_1x0, Transpose2D(), "compute", Inputs({4096, 4096})));
BM(Tfrt(Transpose_1x0, Transpose2D(), "compute", Inputs({4096, 4096})));
BM(Eigen(Transpose_1x0, Shuffle<2>({1, 0}), Inputs({4096, 4096})));

// 3D Transpose: [0, 2, 1]
BM(Jitrt(Transpose_0x2x1, Transpose3D({0, 2, 1}), "compute",
         Inputs({256, 256, 256})));
BM(JitrtV(Transpose_0x2x1, Transpose3D({0, 2, 1}), "compute",
          Inputs({256, 256, 256})));
BM(Tfrt(Transpose_0x2x1, Transpose3D({0, 2, 1}), "compute",
        Inputs({256, 256, 256})));
BM(Eigen(Transpose_0x2x1, Shuffle<3>({0, 2, 1}), Inputs({256, 256, 256})));

// 3D Transpose: [2, 0, 1]
BM(Jitrt(Transpose_2x0x1, Transpose3D({2, 0, 1}), "compute",
         Inputs({256, 256, 256})));
BM(JitrtV(Transpose_2x0x1, Transpose3D({2, 0, 1}), "compute",
          Inputs({256, 256, 256})));
BM(Tfrt(Transpose_2x0x1, Transpose3D({2, 0, 1}), "compute",
        Inputs({256, 256, 256})));
BM(Eigen(Transpose_2x0x1, Shuffle<3>({2, 0, 1}), Inputs({256, 256, 256})));

// 3D Transpose: [2, 1, 0]
BM(Jitrt(Transpose_2x1x0, Transpose3D({2, 1, 0}), "compute",
         Inputs({256, 256, 256})));
BM(JitrtV(Transpose_2x1x0, Transpose3D({2, 1, 0}), "compute",
          Inputs({256, 256, 256})));
BM(Tfrt(Transpose_2x1x0, Transpose3D({2, 1, 0}), "compute",
        Inputs({256, 256, 256})));
BM(Eigen(Transpose_2x1x0, Shuffle<3>({2, 1, 0}), Inputs({256, 256, 256})));

// 3D Transpose: [1, 2, 0]
BM(Jitrt(Transpose_1x2x0, Transpose3D({1, 2, 0}), "compute",
         Inputs({256, 256, 256})));
BM(JitrtV(Transpose_1x2x0, Transpose3D({1, 2, 0}), "compute",
          Inputs({256, 256, 256})));
BM(Tfrt(Transpose_1x2x0, Transpose3D({1, 2, 0}), "compute",
        Inputs({256, 256, 256})));
BM(Eigen(Transpose_1x2x0, Shuffle<3>({1, 2, 0}), Inputs({256, 256, 256})));

}  // namespace tensorflow
<commit_msg>[tf:tfrt] Add [1, 0, 2] case to transpose benchmarks<commit_after>/* Copyright 2021 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 <array>
#include <string>

#include "llvm/Support/FormatVariadic.h"
#include "tensorflow/compiler/mlir/tfrt/benchmarks/benchmark_mlir_function.h"

namespace tensorflow {

static const char* mlir_2d_input = R"(
func @compute(%arg0: tensor<?x?xf32>) -> tensor<?x?xf32> {{
    %0 = "tf.Const"()
         {{value = dense<[1, 0]> : tensor<2xi64>,
          device = "/job:localhost/replica:0/task:0/device:CPU:0"}
         : () -> tensor<2xi64>
    %1 = "tf.Transpose"(%arg0, %0)
         {{device = "/job:localhost/replica:0/task:0/device:CPU:0"}
         : (tensor<?x?xf32>, tensor<2xi64>) -> tensor<?x?xf32>
    return %1 : tensor<?x?xf32>
  }
)";

static const char* mlir_3d_input = R"(
func @compute(%arg0: tensor<?x?x?xf32>) -> tensor<?x?x?xf32> {{
    %0 = "tf.Const"()
         {{value = dense<[{0}, {1}, {2}]> : tensor<3xi64>,
          device = "/job:localhost/replica:0/task:0/device:CPU:0"}
         : () -> tensor<3xi64>
    %1 = "tf.Transpose"(%arg0, %0)
         {{device = "/job:localhost/replica:0/task:0/device:CPU:0"}
         : (tensor<?x?x?xf32>, tensor<3xi64>) -> tensor<?x?x?xf32>
    return %1 : tensor<?x?x?xf32>
  }
)";

static std::string Transpose2D() { return llvm::formatv(mlir_2d_input); }

static std::string Transpose3D(std::array<int32_t, 3> perm) {
  return llvm::formatv(mlir_3d_input, perm[0], perm[1], perm[2]);
}

template <int32_t size>
static auto Shuffle(std::array<int32_t, size> perm) {
  return [perm](llvm::ArrayRef<Tensor> inputs,
                llvm::Optional<Eigen::ThreadPoolDevice> device) {
    std::array<int64_t, size> shuffled;
    for (unsigned d = 0; d < size; d++)
      shuffled[d] = inputs[0].dim_size(perm[d]);

    Tensor output(DT_FLOAT, TensorShape(shuffled));

    auto in0 = inputs[0].tensor<float, size>();
    auto out0 = output.tensor<float, size>();

    if (device.hasValue()) {
      out0.device(*device) = in0.shuffle(perm);
    } else {
      out0 = in0.shuffle(perm);
    }
  };
}

static llvm::SmallVector<InputTensorSpec> Inputs(llvm::ArrayRef<ssize_t> dims) {
  return {InputTensorSpec(DT_FLOAT, dims)};
}

#define BM(FN) BM_##FN->Arg(0)->Arg(4)->Arg(8);

// Small 2D Transpose: [1, 0]
BM(Jitrt(Transpose_small_1x0, Transpose2D(), "compute", Inputs({128, 128})));
BM(JitrtV(Transpose_small_1x0, Transpose2D(), "compute", Inputs({128, 128})));
BM(Tfrt(Transpose_small_1x0, Transpose2D(), "compute", Inputs({128, 128})));
BM(Eigen(Transpose_small_1x0, Shuffle<2>({1, 0}), Inputs({128, 128})));

// Small 3D Transpose: [0, 2, 1]
BM(Jitrt(Transpose_small_0x2x1, Transpose3D({0, 2, 1}), "compute",
         Inputs({32, 32, 16})));
BM(JitrtV(Transpose_small_0x2x1, Transpose3D({0, 2, 1}), "compute",
          Inputs({32, 32, 16})));
BM(Tfrt(Transpose_small_0x2x1, Transpose3D({0, 2, 1}), "compute",
        Inputs({32, 32, 16})));
BM(Eigen(Transpose_small_0x2x1, Shuffle<3>({0, 2, 1}), Inputs({32, 32, 16})));

// Small 3D Transpose: [2, 0, 1]
BM(Jitrt(Transpose_small_2x0x1, Transpose3D({2, 0, 1}), "compute",
         Inputs({32, 32, 16})));
BM(JitrtV(Transpose_small_2x0x1, Transpose3D({2, 0, 1}), "compute",
          Inputs({32, 32, 16})));
BM(Tfrt(Transpose_small_2x0x1, Transpose3D({2, 0, 1}), "compute",
        Inputs({32, 32, 16})));
BM(Eigen(Transpose_small_2x0x1, Shuffle<3>({2, 0, 1}), Inputs({32, 32, 16})));

// Small 3D Transpose: [2, 1, 0]
BM(Jitrt(Transpose_small_2x1x0, Transpose3D({2, 1, 0}), "compute",
         Inputs({32, 32, 16})));
BM(JitrtV(Transpose_small_2x1x0, Transpose3D({2, 1, 0}), "compute",
          Inputs({32, 32, 16})));
BM(Tfrt(Transpose_small_2x1x0, Transpose3D({2, 1, 0}), "compute",
        Inputs({32, 32, 16})));
BM(Eigen(Transpose_small_2x1x0, Shuffle<3>({2, 1, 0}), Inputs({32, 32, 16})));

// Small 3D Transpose: [1, 2, 0]
BM(Jitrt(Transpose_small_1x2x0, Transpose3D({1, 2, 0}), "compute",
         Inputs({32, 32, 16})));
BM(JitrtV(Transpose_small_1x2x0, Transpose3D({1, 2, 0}), "compute",
          Inputs({32, 32, 16})));
BM(Tfrt(Transpose_small_1x2x0, Transpose3D({1, 2, 0}), "compute",
        Inputs({32, 32, 16})));
BM(Eigen(Transpose_small_1x2x0, Shuffle<3>({1, 2, 0}), Inputs({32, 32, 16})));

// Small 3D Transpose: [1, 0, 2]
BM(Jitrt(Transpose_small_1x0x2, Transpose3D({1, 0, 2}), "compute",
         Inputs({32, 32, 16})));
BM(JitrtV(Transpose_small_1x0x2, Transpose3D({1, 0, 2}), "compute",
          Inputs({32, 32, 16})));
BM(Tfrt(Transpose_small_1x0x2, Transpose3D({1, 0, 2}), "compute",
        Inputs({32, 32, 16})));
BM(Eigen(Transpose_small_1x0x2, Shuffle<3>({1, 0, 2}), Inputs({32, 32, 16})));

// 2D Transpose: [1, 0]
BM(Jitrt(Transpose_1x0, Transpose2D(), "compute", Inputs({4096, 4096})));
BM(JitrtV(Transpose_1x0, Transpose2D(), "compute", Inputs({4096, 4096})));
BM(Tfrt(Transpose_1x0, Transpose2D(), "compute", Inputs({4096, 4096})));
BM(Eigen(Transpose_1x0, Shuffle<2>({1, 0}), Inputs({4096, 4096})));

// 3D Transpose: [0, 2, 1]
BM(Jitrt(Transpose_0x2x1, Transpose3D({0, 2, 1}), "compute",
         Inputs({256, 256, 256})));
BM(JitrtV(Transpose_0x2x1, Transpose3D({0, 2, 1}), "compute",
          Inputs({256, 256, 256})));
BM(Tfrt(Transpose_0x2x1, Transpose3D({0, 2, 1}), "compute",
        Inputs({256, 256, 256})));
BM(Eigen(Transpose_0x2x1, Shuffle<3>({0, 2, 1}), Inputs({256, 256, 256})));

// 3D Transpose: [2, 0, 1]
BM(Jitrt(Transpose_2x0x1, Transpose3D({2, 0, 1}), "compute",
         Inputs({256, 256, 256})));
BM(JitrtV(Transpose_2x0x1, Transpose3D({2, 0, 1}), "compute",
          Inputs({256, 256, 256})));
BM(Tfrt(Transpose_2x0x1, Transpose3D({2, 0, 1}), "compute",
        Inputs({256, 256, 256})));
BM(Eigen(Transpose_2x0x1, Shuffle<3>({2, 0, 1}), Inputs({256, 256, 256})));

// 3D Transpose: [2, 1, 0]
BM(Jitrt(Transpose_2x1x0, Transpose3D({2, 1, 0}), "compute",
         Inputs({256, 256, 256})));
BM(JitrtV(Transpose_2x1x0, Transpose3D({2, 1, 0}), "compute",
          Inputs({256, 256, 256})));
BM(Tfrt(Transpose_2x1x0, Transpose3D({2, 1, 0}), "compute",
        Inputs({256, 256, 256})));
BM(Eigen(Transpose_2x1x0, Shuffle<3>({2, 1, 0}), Inputs({256, 256, 256})));

// 3D Transpose: [1, 2, 0]
BM(Jitrt(Transpose_1x2x0, Transpose3D({1, 2, 0}), "compute",
         Inputs({256, 256, 256})));
BM(JitrtV(Transpose_1x2x0, Transpose3D({1, 2, 0}), "compute",
          Inputs({256, 256, 256})));
BM(Tfrt(Transpose_1x2x0, Transpose3D({1, 2, 0}), "compute",
        Inputs({256, 256, 256})));
BM(Eigen(Transpose_1x2x0, Shuffle<3>({1, 2, 0}), Inputs({256, 256, 256})));

// 3D Transpose: [1, 0, 2]
BM(Jitrt(Transpose_1x0x2, Transpose3D({1, 0, 2}), "compute",
         Inputs({256, 256, 256})));
BM(JitrtV(Transpose_1x0x2, Transpose3D({1, 0, 2}), "compute",
          Inputs({256, 256, 256})));
BM(Tfrt(Transpose_1x0x2, Transpose3D({1, 0, 2}), "compute",
        Inputs({256, 256, 256})));
BM(Eigen(Transpose_1x0x2, Shuffle<3>({1, 0, 2}), Inputs({256, 256, 256})));

}  // namespace tensorflow
<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <map>
#include <node.h>

#include "PSATResult.h"
#include "calculator/EstimateFLA.h"

using namespace v8;
using namespace std;

Isolate* iso;
Local<Object> inp;

double Get(const char *nm) {
  auto rObj = inp->ToObject()->Get(String::NewFromUtf8(iso,nm));
  if (rObj->IsUndefined()) {
    cout << nm << endl;;
    assert(!"defined");
  }
  return rObj->NumberValue();
}

void Results(const FunctionCallbackInfo<Value>& args) {
  iso = args.GetIsolate();
  inp = args[0]->ToObject();
  auto r = Object::New(iso);

  auto drive = (Pump::Drive)(int)Get("drive");
  auto effCls = (Motor::EfficiencyClass)(int)Get("efficiency_class");
  Pump pump((Pump::Style)(int)Get("pump_style"),Get("pump_specified"),Get("pump_rated_speed"),drive,
      Get("viscosity"),Get("specific_gravity"),Get("stages"),(Pump::Speed)(int)(!Get("fixed_speed")));
  Motor motor((Motor::LineFrequency)(int)(!Get("line")),Get("motor_rated_power"),Get("motor_rated_speed"),
      effCls,Get("efficiency"),Get("motor_rated_voltage"),Get("motor_rated_flc"),Get("margin"));
  Financial fin(Get("fraction"),Get("cost"));
  FieldData fd(Get("flow"),Get("head"),(FieldData::LoadEstimationMethod)(Get("motor_field_power")>0?0:1),
      Get("motor_field_power"),Get("motor_field_current"),Get("motor_field_voltage"));
  PSATResult psat(pump,motor,fin,fd);
  psat.calculateExisting();
  psat.calculateOptimal();
  auto ex = psat.getExisting(), opt = psat.getOptimal();

  map<const char *,vector<double>> out = {
    {"Pump Efficiency",{ex.pumpEfficiency_*100,opt.pumpEfficiency_*100}},
    {"Motor Rated Power",{ex.motorRatedPower_,opt.motorRatedPower_}},
    {"Motor Shaft Power",{ex.motorShaftPower_,opt.motorShaftPower_}},
    {"Pump Shaft Power",{ex.pumpShaftPower_,opt.pumpShaftPower_}},
    {"Motor Efficiency",{ex.motorEfficiency_,opt.motorEfficiency_}},
    {"Motor Power Factor",{ex.motorPowerFactor_,opt.motorPowerFactor_}},
    {"Motor Current",{ex.motorCurrent_,opt.motorCurrent_}},
    {"Motor Power", {ex.motorPower_,opt.motorPower_}},
    {"Annual Energy", {ex.annualEnergy_,opt.annualEnergy_}},
    {"Annual Cost", {ex.annualCost_*1000,opt.annualCost_*1000}},
    {"Savings Potential", {psat.getAnnualSavingsPotential(),-1}},
    {"Optimization Rating", {psat.getOptimizationRating(),-1}}
  };
  for(auto p: out) {
    auto a = Array::New(iso);
    a->Set(0,Number::New(iso,p.second[0]));
    a->Set(1,Number::New(iso,p.second[1]));
    r->Set(String::NewFromUtf8(iso,p.first),a);
  }
  args.GetReturnValue().Set(r);
}

void EstFLA(const FunctionCallbackInfo<Value>& args) {
  iso = args.GetIsolate();
  inp = args[0]->ToObject();
  EstimateFLA fla(Get("motor_rated_power"),Get("motor_rated_speed"),(Motor::LineFrequency)(int)(!Get("line")),(Motor::EfficiencyClass)(int)Get("efficiency_class"),
    Get("efficiency"),Get("motor_rated_voltage"));
  fla.calculate();
  args.GetReturnValue().Set(fla.getEstimatedFLA());
}

//TODO round vs js round; loosen up to make next test case
void Check(double exp, double act, const char* nm="") {
  //cout << "e " << exp << "; a " << act << endl;
  // if (isnan(act) || (abs(exp-act)>.01*exp)) {
  auto p = 10;
  if (isnan(act) || ( (round(exp*p)/p)!=round(act*p)/p)) {
    printf("\"%s\" TEST FAILED: %f %f\n",nm,exp,act);
    assert(!"equal");
  }
}

void Check100(double exp, double act, const char* nm="") {
  Check(exp,act*100,nm);
}

void Test(const FunctionCallbackInfo<Value>& args) {
  MotorEfficiency mef(Motor::LineFrequency::FREQ60,1780,Motor::EfficiencyClass::ENERGY_EFFICIENT,0,200,.75);
  Check100(95.69,mef.calculate());

  EstimateFLA fla(200,1780,(Motor::LineFrequency)1,(Motor::EfficiencyClass)(1),0,460);
  fla.calculate();
  Check(225.8,fla.getEstimatedFLA());

  #define BASE \
    Pump pump(Pump::Style::END_SUCTION_ANSI_API,0,1780,Pump::Drive::DIRECT_DRIVE,\
      1,1,1,Pump::Speed::NOT_FIXED_SPEED);\
    Motor motor(Motor::LineFrequency::FREQ60,200,1780,\
        Motor::EfficiencyClass::ENERGY_EFFICIENT,0,460,225.8,0);\
    Financial fin(1,.05);\
    FieldData fd(2000,277,FieldData::LoadEstimationMethod::POWER,\
        150,0,460);

  #define CALC \
    PSATResult psat(pump,motor,fin,fd);\
    psat.calculateExisting();\
    auto ex = psat.getExisting();

  for (int i=1; i<=10000; i=i+2) {
    BASE
    CALC
    Check(ex.motorShaftPower_,ex.motorShaftPower_,"SAME");
  }

  {
    BASE
    motor.setMotorRpm(1786);
    fd.setMotorPower(80);
    CALC
    Check(101.9,ex.motorShaftPower_);
    Check100(95,ex.motorEfficiency_);
    Check100(79.1,ex.motorPowerFactor_);
    Check(127,ex.motorCurrent_);
  }
  {
    BASE
    fd.setMotorPower(80);
    motor.setMotorRatedPower(100);
    motor.setFullLoadAmps(113.8);
    CALC
    Check(101.8,ex.motorShaftPower_);
    Check100(94.9,ex.motorEfficiency_);
    Check100(86.7,ex.motorPowerFactor_);
    Check(115.8,ex.motorCurrent_);
  }
  {
    BASE
    fd.setMotorPower(80);
    fd.setVoltage(260);
    CALC
    Check(101.9,ex.motorShaftPower_);
    Check100(95,ex.motorEfficiency_);
    Check100(138.8,ex.motorPowerFactor_);
    Check(128,ex.motorCurrent_);
  }
  {
    BASE
    motor.setMotorRpm(1200);
    fd.setMotorPower(80);
    motor.setFullLoadAmps(235.3);
    CALC
    Check(101.4,ex.motorShaftPower_);
    Check100(94.5,ex.motorEfficiency_);
    Check100(74.3,ex.motorPowerFactor_);
    Check(135.1,ex.motorCurrent_);
  }
  {
    BASE
    fd.setMotorPower(111.855);
    CALC
    Check(143.4,ex.motorShaftPower_);
    Check100(95.6,ex.motorEfficiency_);
    Check100(84.3,ex.motorPowerFactor_);
    Check(166.5,ex.motorCurrent_);
  }
  {
    BASE
    fd.setMotorPower(80);
    motor.setMotorRatedVoltage(200);
    motor.setFullLoadAmps(519.3);
    CALC
    Check(101.9,ex.motorShaftPower_);
    Check100(95,ex.motorEfficiency_);
    Check100(35.2,ex.motorPowerFactor_);
    Check(284.9,ex.motorCurrent_);
  }
  {
    BASE
    CALC
    Check(217.5,ex.motorCurrent_);
  }
  {
    BASE
    fd.setLoadEstimationMethod(FieldData::LoadEstimationMethod::CURRENT);
    fd.setMotorAmps(218);
    fd.setMotorPower(0);
    CALC
    Check(150.4,ex.motorPower_);
    Check100(72.5,ex.pumpEfficiency_);
  }
  {
    BASE
    fd.setMotorPower(80);
    CALC
    Check(700.8,ex.annualEnergy_);
  }
  {
    BASE
    fin.setOperatingFraction(.25);
    CALC
    Check(328.5,ex.annualEnergy_);
    Check(16.4,ex.annualCost_);
  }
  {
    BASE
    motor.setFullLoadAmps(300);
    CALC
    Check(288.9,ex.motorCurrent_);
  }
  {
    BASE
    motor.setEfficiencyClass(Motor::EfficiencyClass(0));
    CALC
    Check(213.7,ex.motorCurrent_);
  }
  {
    BASE
    motor.setEfficiencyClass(Motor::EfficiencyClass(2));
    motor.setSpecifiedEfficiency(75);
    CALC
    Check(173.7,ex.motorCurrent_);
  }
  cout << "done";
}

void Wtf(const FunctionCallbackInfo<Value>& args) {
}

void Init(Local<Object> exports) {
  NODE_SET_METHOD(exports, "results", Results);
  NODE_SET_METHOD(exports, "estFLA", EstFLA);
  NODE_SET_METHOD(exports, "test", Test);
  NODE_SET_METHOD(exports, "wtf", Wtf);
}

NODE_MODULE(bridge, Init)

<commit_msg>no message<commit_after>#include <iostream>
#include <vector>
#include <map>
#include <node.h>

#include "PSATResult.h"
#include "calculator/EstimateFLA.h"
#include "calculator/MotorCurrent.h"

using namespace v8;
using namespace std;

Isolate* iso;
Local<Object> inp;

double Get(const char *nm) {
  auto rObj = inp->ToObject()->Get(String::NewFromUtf8(iso,nm));
  if (rObj->IsUndefined()) {
    cout << nm << endl;;
    assert(!"defined");
  }
  return rObj->NumberValue();
}

void Results(const FunctionCallbackInfo<Value>& args) {
  iso = args.GetIsolate();
  inp = args[0]->ToObject();
  auto r = Object::New(iso);

  auto drive = (Pump::Drive)(int)Get("drive");
  auto effCls = (Motor::EfficiencyClass)(int)Get("efficiency_class");
  Pump pump((Pump::Style)(int)Get("pump_style"),Get("pump_specified"),Get("pump_rated_speed"),drive,
      Get("viscosity"),Get("specific_gravity"),Get("stages"),(Pump::Speed)(int)(!Get("fixed_speed")));
  Motor motor((Motor::LineFrequency)(int)(!Get("line")),Get("motor_rated_power"),Get("motor_rated_speed"),
      effCls,Get("efficiency"),Get("motor_rated_voltage"),Get("motor_rated_flc"),Get("margin"));
  Financial fin(Get("fraction"),Get("cost"));
  FieldData fd(Get("flow"),Get("head"),(FieldData::LoadEstimationMethod)(Get("motor_field_power")>0?0:1),
      Get("motor_field_power"),Get("motor_field_current"),Get("motor_field_voltage"));
  PSATResult psat(pump,motor,fin,fd);
  psat.calculateExisting();
  psat.calculateOptimal();
  auto ex = psat.getExisting(), opt = psat.getOptimal();

  map<const char *,vector<double>> out = {
    {"Pump Efficiency",{ex.pumpEfficiency_*100,opt.pumpEfficiency_*100}},
    {"Motor Rated Power",{ex.motorRatedPower_,opt.motorRatedPower_}},
    {"Motor Shaft Power",{ex.motorShaftPower_,opt.motorShaftPower_}},
    {"Pump Shaft Power",{ex.pumpShaftPower_,opt.pumpShaftPower_}},
    {"Motor Efficiency",{ex.motorEfficiency_,opt.motorEfficiency_}},
    {"Motor Power Factor",{ex.motorPowerFactor_,opt.motorPowerFactor_}},
    {"Motor Current",{ex.motorCurrent_,opt.motorCurrent_}},
    {"Motor Power", {ex.motorPower_,opt.motorPower_}},
    {"Annual Energy", {ex.annualEnergy_,opt.annualEnergy_}},
    {"Annual Cost", {ex.annualCost_*1000,opt.annualCost_*1000}},
    {"Savings Potential", {psat.getAnnualSavingsPotential(),-1}},
    {"Optimization Rating", {psat.getOptimizationRating(),-1}}
  };
  for(auto p: out) {
    auto a = Array::New(iso);
    a->Set(0,Number::New(iso,p.second[0]));
    a->Set(1,Number::New(iso,p.second[1]));
    r->Set(String::NewFromUtf8(iso,p.first),a);
  }
  args.GetReturnValue().Set(r);
}

void EstFLA(const FunctionCallbackInfo<Value>& args) {
  iso = args.GetIsolate();
  inp = args[0]->ToObject();
  EstimateFLA fla(Get("motor_rated_power"),Get("motor_rated_speed"),(Motor::LineFrequency)(int)(!Get("line")),(Motor::EfficiencyClass)(int)Get("efficiency_class"),
    Get("efficiency"),Get("motor_rated_voltage"));
  fla.calculate();
  args.GetReturnValue().Set(fla.getEstimatedFLA());
}

//TODO round vs js round; loosen up to make next test case
void Check(double exp, double act, const char* nm="") {
  cout << "e " << exp << "; a " << act << endl;
  // if (isnan(act) || (abs(exp-act)>.01*exp)) {
  auto p = 10;
  if (isnan(act) || ( (round(exp*p)/p)!=round(act*p)/p)) {
    printf("\"%s\" TEST FAILED: %f %f\n",nm,exp,act);
    assert(!"equal");
  }
}

void Check100(double exp, double act, const char* nm="") {
  Check(exp,act*100,nm);
}

void Test(const FunctionCallbackInfo<Value>& args) {
  MotorEfficiency mef(Motor::LineFrequency::FREQ60,1780,Motor::EfficiencyClass::ENERGY_EFFICIENT,0,200,.75);
  Check100(95.69,mef.calculate());

  MotorCurrent mc(200,1780,Motor::LineFrequency::FREQ60,Motor::EfficiencyClass::ENERGY_EFFICIENT,0,.75,460,225.8);
  Check100(76.63,mc.calculate()/225.8);
return;
  EstimateFLA fla(200,1780,(Motor::LineFrequency)1,(Motor::EfficiencyClass)(1),0,460);
  fla.calculate();
  Check(225.8,fla.getEstimatedFLA());

  #define BASE \
    Pump pump(Pump::Style::END_SUCTION_ANSI_API,0,1780,Pump::Drive::DIRECT_DRIVE,\
      1,1,1,Pump::Speed::NOT_FIXED_SPEED);\
    Motor motor(Motor::LineFrequency::FREQ60,200,1780,\
        Motor::EfficiencyClass::ENERGY_EFFICIENT,0,460,225.8,0);\
    Financial fin(1,.05);\
    FieldData fd(2000,277,FieldData::LoadEstimationMethod::POWER,\
        150,0,460);

  #define CALC \
    PSATResult psat(pump,motor,fin,fd);\
    psat.calculateExisting();\
    auto ex = psat.getExisting();

  for (int i=1; i<=10000; i=i+2) {
    BASE
    CALC
    Check(ex.motorShaftPower_,ex.motorShaftPower_,"SAME");
  }

  {
    BASE
    motor.setMotorRpm(1786);
    fd.setMotorPower(80);
    CALC
    Check(101.9,ex.motorShaftPower_);
    Check100(95,ex.motorEfficiency_);
    Check100(79.1,ex.motorPowerFactor_);
    Check(127,ex.motorCurrent_);
  }
  {
    BASE
    fd.setMotorPower(80);
    motor.setMotorRatedPower(100);
    motor.setFullLoadAmps(113.8);
    CALC
    Check(101.8,ex.motorShaftPower_);
    Check100(94.9,ex.motorEfficiency_);
    Check100(86.7,ex.motorPowerFactor_);
    Check(115.8,ex.motorCurrent_);
  }
  {
    BASE
    fd.setMotorPower(80);
    fd.setVoltage(260);
    CALC
    Check(101.9,ex.motorShaftPower_);
    Check100(95,ex.motorEfficiency_);
    Check100(138.8,ex.motorPowerFactor_);
    Check(128,ex.motorCurrent_);
  }
  {
    BASE
    motor.setMotorRpm(1200);
    fd.setMotorPower(80);
    motor.setFullLoadAmps(235.3);
    CALC
    Check(101.4,ex.motorShaftPower_);
    Check100(94.5,ex.motorEfficiency_);
    Check100(74.3,ex.motorPowerFactor_);
    Check(135.1,ex.motorCurrent_);
  }
  {
    BASE
    fd.setMotorPower(111.855);
    CALC
    Check(143.4,ex.motorShaftPower_);
    Check100(95.6,ex.motorEfficiency_);
    Check100(84.3,ex.motorPowerFactor_);
    Check(166.5,ex.motorCurrent_);
  }
  {
    BASE
    fd.setMotorPower(80);
    motor.setMotorRatedVoltage(200);
    motor.setFullLoadAmps(519.3);
    CALC
    Check(101.9,ex.motorShaftPower_);
    Check100(95,ex.motorEfficiency_);
    Check100(35.2,ex.motorPowerFactor_);
    Check(284.9,ex.motorCurrent_);
  }
  {
    BASE
    CALC
    Check(217.5,ex.motorCurrent_);
  }
  {
    BASE
    fd.setLoadEstimationMethod(FieldData::LoadEstimationMethod::CURRENT);
    fd.setMotorAmps(218);
    fd.setMotorPower(0);
    CALC
    Check(150.4,ex.motorPower_);
    Check100(72.5,ex.pumpEfficiency_);
  }
  {
    BASE
    fd.setMotorPower(80);
    CALC
    Check(700.8,ex.annualEnergy_);
  }
  {
    BASE
    fin.setOperatingFraction(.25);
    CALC
    Check(328.5,ex.annualEnergy_);
    Check(16.4,ex.annualCost_);
  }
  {
    BASE
    motor.setFullLoadAmps(300);
    CALC
    Check(288.9,ex.motorCurrent_);
  }
  {
    BASE
    motor.setEfficiencyClass(Motor::EfficiencyClass(0));
    CALC
    Check(213.7,ex.motorCurrent_);
  }
  {
    BASE
    motor.setEfficiencyClass(Motor::EfficiencyClass(2));
    motor.setSpecifiedEfficiency(75);
    CALC
    Check(173.7,ex.motorCurrent_);
  }
  cout << "done";
}

void Wtf(const FunctionCallbackInfo<Value>& args) {
}

void Init(Local<Object> exports) {
  NODE_SET_METHOD(exports, "results", Results);
  NODE_SET_METHOD(exports, "estFLA", EstFLA);
  NODE_SET_METHOD(exports, "test", Test);
  NODE_SET_METHOD(exports, "wtf", Wtf);
}

NODE_MODULE(bridge, Init)

<|endoftext|>


<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 "webkit/common/resource_type.h"

#include "base/logging.h"

using blink::WebURLRequest;

// static
ResourceType::Type ResourceType::FromTargetType(
    WebURLRequest::TargetType type) {
  switch (type) {
    case WebURLRequest::TargetIsMainFrame:
      return ResourceType::MAIN_FRAME;
    case WebURLRequest::TargetIsSubframe:
      return ResourceType::SUB_FRAME;
    case WebURLRequest::TargetIsSubresource:
      return ResourceType::SUB_RESOURCE;
    case WebURLRequest::TargetIsStyleSheet:
      return ResourceType::STYLESHEET;
    case WebURLRequest::TargetIsScript:
      return ResourceType::SCRIPT;
    case WebURLRequest::TargetIsFontResource:
      return ResourceType::FONT_RESOURCE;
    case WebURLRequest::TargetIsImage:
      return ResourceType::IMAGE;
    case WebURLRequest::TargetIsObject:
      return ResourceType::OBJECT;
    case WebURLRequest::TargetIsMedia:
      return ResourceType::MEDIA;
    case WebURLRequest::TargetIsWorker:
      return ResourceType::WORKER;
    case WebURLRequest::TargetIsSharedWorker:
      return ResourceType::SHARED_WORKER;
    case WebURLRequest::TargetIsPrefetch:
      return ResourceType::PREFETCH;
    case WebURLRequest::TargetIsFavicon:
      return ResourceType::FAVICON;
    case WebURLRequest::TargetIsXHR:
      return ResourceType::XHR;
#if defined(WEBKIT_HAS_TARGET_IS_PING)
    case WebURLRequest::TargetIsPing:
      return ResourceType::PING;
#endif
    default:
      NOTREACHED();
      return ResourceType::SUB_RESOURCE;
  }
}
<commit_msg>Remove WEBKIT_HAS_TARGET_IS_PING #ifdef.<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 "webkit/common/resource_type.h"

#include "base/logging.h"

using blink::WebURLRequest;

// static
ResourceType::Type ResourceType::FromTargetType(
    WebURLRequest::TargetType type) {
  switch (type) {
    case WebURLRequest::TargetIsMainFrame:
      return ResourceType::MAIN_FRAME;
    case WebURLRequest::TargetIsSubframe:
      return ResourceType::SUB_FRAME;
    case WebURLRequest::TargetIsSubresource:
      return ResourceType::SUB_RESOURCE;
    case WebURLRequest::TargetIsStyleSheet:
      return ResourceType::STYLESHEET;
    case WebURLRequest::TargetIsScript:
      return ResourceType::SCRIPT;
    case WebURLRequest::TargetIsFontResource:
      return ResourceType::FONT_RESOURCE;
    case WebURLRequest::TargetIsImage:
      return ResourceType::IMAGE;
    case WebURLRequest::TargetIsObject:
      return ResourceType::OBJECT;
    case WebURLRequest::TargetIsMedia:
      return ResourceType::MEDIA;
    case WebURLRequest::TargetIsWorker:
      return ResourceType::WORKER;
    case WebURLRequest::TargetIsSharedWorker:
      return ResourceType::SHARED_WORKER;
    case WebURLRequest::TargetIsPrefetch:
      return ResourceType::PREFETCH;
    case WebURLRequest::TargetIsFavicon:
      return ResourceType::FAVICON;
    case WebURLRequest::TargetIsXHR:
      return ResourceType::XHR;
    case WebURLRequest::TargetIsPing:
      return ResourceType::PING;
    default:
      NOTREACHED();
      return ResourceType::SUB_RESOURCE;
  }
}
<|endoftext|>