<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * Version: MPL 1.1 / GPLv3+ / LGPLv3+
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Initial Developer of the Original Code is
 *       Albert Thuswaldner <albert.thuswaldner@gmail.com>
 * Portions created by the Initial Developer are Copyright (C) 2012 the
 * Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
 * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
 * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
 * instead of those above.
 */

#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/Sequence.hxx>
#include <com/sun/star/lang/Locale.hpp>
#include <com/sun/star/i18n/LocaleDataItem.hpp>

#include "formulaopt.hxx"
#include "miscuno.hxx"
#include "global.hxx"

using namespace utl;
using namespace com::sun::star::uno;
using ::com::sun::star::lang::Locale;
using ::com::sun::star::i18n::LocaleDataItem;
using ::rtl::OUString;

// -----------------------------------------------------------------------

TYPEINIT1(ScTpFormulaItem, SfxPoolItem);

// -----------------------------------------------------------------------

ScFormulaOptions::ScFormulaOptions()
{
    SetDefaults();
}

ScFormulaOptions::ScFormulaOptions( const ScFormulaOptions& rCpy ) :
    bUseEnglishFuncName ( rCpy.bUseEnglishFuncName ),
    eFormulaGrammar     ( rCpy.eFormulaGrammar ),
    aFormulaSepArg      ( rCpy.aFormulaSepArg ),
    aFormulaSepArrayRow ( rCpy.aFormulaSepArrayRow ),
    aFormulaSepArrayCol ( rCpy.aFormulaSepArrayCol )
{
}

ScFormulaOptions::~ScFormulaOptions()
{
}

void ScFormulaOptions::SetDefaults()
{
    bUseEnglishFuncName = false;
    eFormulaGrammar     = ::formula::FormulaGrammar::GRAM_NATIVE;

    ResetFormulaSeparators();
}

void ScFormulaOptions::ResetFormulaSeparators()
{
    GetDefaultFormulaSeparators(aFormulaSepArg, aFormulaSepArrayCol, aFormulaSepArrayRow);
}

void ScFormulaOptions::GetDefaultFormulaSeparators(
    rtl::OUString& rSepArg, rtl::OUString& rSepArrayCol, rtl::OUString& rSepArrayRow)
{
    // Defaults to the old separator values.
    rSepArg = OUString(RTL_CONSTASCII_USTRINGPARAM(";"));
    rSepArrayCol = OUString(RTL_CONSTASCII_USTRINGPARAM(";"));
    rSepArrayRow = OUString(RTL_CONSTASCII_USTRINGPARAM("|"));

    const Locale& rLocale = *ScGlobal::GetLocale();
    const OUString& rLang = rLocale.Language;
    if (rLang.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ru")))
        // Don't do automatic guess for these languages, and fall back to
        // the old separator set.
        return;

    const LocaleDataWrapper& rLocaleData = GetLocaleDataWrapper();
    const OUString& rDecSep  = rLocaleData.getNumDecimalSep();
    const OUString& rListSep = rLocaleData.getListSep();

    if (rDecSep.isEmpty() || rListSep.isEmpty())
        // Something is wrong.  Stick with the default separators.
        return;

    sal_Unicode cDecSep  = rDecSep.getStr()[0];
    sal_Unicode cListSep = rListSep.getStr()[0];

    // Excel by default uses system's list separator as the parameter
    // separator, which in English locales is a comma.  However, OOo's list
    // separator value is set to ';' for all English locales.  Because of this
    // discrepancy, we will hardcode the separator value here, for now.
    if (cDecSep == sal_Unicode('.'))
        cListSep = sal_Unicode(',');

    // Special case for de_CH locale.
    if (rLocale.Language.equalsAsciiL("de", 2) && rLocale.Country.equalsAsciiL("CH", 2))
        cListSep = sal_Unicode(';');

    // by default, the parameter separator equals the locale-specific
    // list separator.
    rSepArg = OUString(cListSep);

    if (cDecSep == cListSep && cDecSep != sal_Unicode(';'))
        // if the decimal and list separators are equal, set the
        // parameter separator to be ';', unless they are both
        // semicolon in which case don't change the decimal separator.
        rSepArg = OUString(RTL_CONSTASCII_USTRINGPARAM(";"));

    rSepArrayCol = OUString(RTL_CONSTASCII_USTRINGPARAM(","));
    if (cDecSep == sal_Unicode(','))
        rSepArrayCol = OUString(RTL_CONSTASCII_USTRINGPARAM("."));
    rSepArrayRow = OUString(RTL_CONSTASCII_USTRINGPARAM(";"));
}

const LocaleDataWrapper& ScFormulaOptions::GetLocaleDataWrapper()
{
    return *ScGlobal::pLocaleData;
}

ScFormulaOptions& ScFormulaOptions::operator=( const ScFormulaOptions& rCpy )
{
    bUseEnglishFuncName = rCpy.bUseEnglishFuncName;
    eFormulaGrammar     = rCpy.eFormulaGrammar;
    aFormulaSepArg      = rCpy.aFormulaSepArg;
    aFormulaSepArrayRow = rCpy.aFormulaSepArrayRow;
    aFormulaSepArrayCol = rCpy.aFormulaSepArrayCol;
    return *this;
}

bool ScFormulaOptions::operator==( const ScFormulaOptions& rOpt ) const
{
    return bUseEnglishFuncName == rOpt.bUseEnglishFuncName
        && eFormulaGrammar     == rOpt.eFormulaGrammar
        && aFormulaSepArg      == rOpt.aFormulaSepArg
        && aFormulaSepArrayRow == rOpt.aFormulaSepArrayRow
        && aFormulaSepArrayCol == rOpt.aFormulaSepArrayCol;
}

bool ScFormulaOptions::operator!=( const ScFormulaOptions& rOpt ) const
{
    return !(operator==(rOpt));
}

// -----------------------------------------------------------------------

ScTpFormulaItem::ScTpFormulaItem( sal_uInt16 nWhichP, const ScFormulaOptions& rOpt ) :
    SfxPoolItem ( nWhichP ),
    theOptions  ( rOpt )
{
}

ScTpFormulaItem::ScTpFormulaItem( const ScTpFormulaItem& rItem ) :
    SfxPoolItem ( rItem ),
    theOptions  ( rItem.theOptions )
{
}

ScTpFormulaItem::~ScTpFormulaItem()
{
}

String ScTpFormulaItem::GetValueText() const
{
    return String::CreateFromAscii( "ScTpFormulaItem" );
}

int ScTpFormulaItem::operator==( const SfxPoolItem& rItem ) const
{
    OSL_ENSURE( SfxPoolItem::operator==( rItem ), "unequal Which or Type" );

    const ScTpFormulaItem& rPItem = (const ScTpFormulaItem&)rItem;
    return ( theOptions == rPItem.theOptions );
}

SfxPoolItem* ScTpFormulaItem::Clone( SfxItemPool * ) const
{
    return new ScTpFormulaItem( *this );
}

// -----------------------------------------------------------------------

#define CFGPATH_FORMULA           "Office.Calc/Formula"

#define SCFORMULAOPT_GRAMMAR           0
#define SCFORMULAOPT_ENGLISH_FUNCNAME  1
#define SCFORMULAOPT_SEP_ARG           2
#define SCFORMULAOPT_SEP_ARRAY_ROW     3
#define SCFORMULAOPT_SEP_ARRAY_COL     4
#define SCFORMULAOPT_INDIRECT_GRAMMAR  5
#define SCFORMULAOPT_COUNT             6

Sequence<OUString> ScFormulaCfg::GetPropertyNames()
{
    static const char* aPropNames[] =
    {
        "Syntax/Grammar",             // SCFORMULAOPT_GRAMMAR
        "Syntax/EnglishFunctionName", // SCFORMULAOPT_ENGLISH_FUNCNAME
        "Syntax/SeparatorArg",        // SCFORMULAOPT_SEP_ARG
        "Syntax/SeparatorArrayRow",   // SCFORMULAOPT_SEP_ARRAY_ROW
        "Syntax/SeparatorArrayCol",   // SCFORMULAOPT_SEP_ARRAY_COL
        "Syntax/IndirectFuncGrammar", // SCFORMULAOPT_INDIRECT_GRAMMAR
    };
    Sequence<OUString> aNames(SCFORMULAOPT_COUNT);
    OUString* pNames = aNames.getArray();
    for (int i = 0; i < SCFORMULAOPT_COUNT; ++i)
        pNames[i] = OUString::createFromAscii(aPropNames[i]);

    return aNames;
}

ScFormulaCfg::ScFormulaCfg() :
    ConfigItem( OUString(RTL_CONSTASCII_USTRINGPARAM( CFGPATH_FORMULA )) )
{
    Sequence<OUString> aNames = GetPropertyNames();
    Sequence<Any> aValues = GetProperties(aNames);
    const Any* pValues = aValues.getConstArray();
    OSL_ENSURE(aValues.getLength() == aNames.getLength(), "GetProperties failed");
    if(aValues.getLength() == aNames.getLength())
    {
        sal_Int32 nIntVal = 0;
        for(int nProp = 0; nProp < aNames.getLength(); nProp++)
        {
            if(pValues[nProp].hasValue())
            {
                switch(nProp)
                {
                case SCFORMULAOPT_GRAMMAR:
                {
                    // Get default value in case this option is not set.
                    ::formula::FormulaGrammar::Grammar eGram = GetFormulaSyntax();

                    do
                    {
                        if (!(pValues[nProp] >>= nIntVal))
                            // extractino failed.
                            break;

                        switch (nIntVal)
                        {
                            case 0: // Calc A1
                                eGram = ::formula::FormulaGrammar::GRAM_NATIVE;
                            break;
                            case 1: // Excel A1
                                eGram = ::formula::FormulaGrammar::GRAM_NATIVE_XL_A1;
                            break;
                            case 2: // Excel R1C1
                                eGram = ::formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1;
                            break;
                            default:
                                ;
                        }
                    }
                    while (false);
                    SetFormulaSyntax(eGram);
                }
                break;
                case SCFORMULAOPT_ENGLISH_FUNCNAME:
                {
                    sal_Bool bEnglish = false;
                    if (pValues[nProp] >>= bEnglish)
                        SetUseEnglishFuncName(bEnglish);
                }
                break;
                case SCFORMULAOPT_SEP_ARG:
                {
                    OUString aSep;
                    if ((pValues[nProp] >>= aSep) && !aSep.isEmpty())
                        SetFormulaSepArg(aSep);
                }
                break;
                case SCFORMULAOPT_SEP_ARRAY_ROW:
                {
                    OUString aSep;
                    if ((pValues[nProp] >>= aSep) && !aSep.isEmpty())
                        SetFormulaSepArrayRow(aSep);
                }
                break;
                case SCFORMULAOPT_SEP_ARRAY_COL:
                {
                    OUString aSep;
                    if ((pValues[nProp] >>= aSep) && !aSep.isEmpty())
                        SetFormulaSepArrayCol(aSep);
                }
                case SCFORMULAOPT_INDIRECT_GRAMMAR:
                {
                    // Get default value in case this option is not set.
                    ::formula::FormulaGrammar::AddressConvention eConv = GetIndirectFuncSyntax();

                    do
                    {
                        if (!(pValues[nProp] >>= nIntVal))
                            // extractino failed.
                            break;

                        switch (nIntVal)
                        {
                            case -1: // Same as the formula grammar.
                                eConv = formula::FormulaGrammar::CONV_UNSPECIFIED;
                            break;
                            case 0: // Calc A1
                                eConv = formula::FormulaGrammar::CONV_OOO;
                            break;
                            case 1: // Excel A1
                                eConv = formula::FormulaGrammar::CONV_XL_A1;
                            break;
                            case 2: // Excel R1C1
                                eConv = formula::FormulaGrammar::CONV_XL_R1C1;
                            break;
                            default:
                                ;
                        }
                    }
                    while (false);
                    SetIndirectFuncSyntax(eConv);
                }
                break;
                break;
                }
            }
        }
    }
}

void ScFormulaCfg::Commit()
{
    Sequence<OUString> aNames = GetPropertyNames();
    Sequence<Any> aValues(aNames.getLength());
    Any* pValues = aValues.getArray();

    for (int nProp = 0; nProp < aNames.getLength(); ++nProp)
    {
        switch (nProp)
        {
            case SCFORMULAOPT_GRAMMAR :
            {
                sal_Int32 nVal = 0;
                switch (GetFormulaSyntax())
                {
                    case ::formula::FormulaGrammar::GRAM_NATIVE_XL_A1:    nVal = 1; break;
                    case ::formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1:  nVal = 2; break;
                    default: break;
                }
                pValues[nProp] <<= nVal;
            }
            break;
            case SCFORMULAOPT_ENGLISH_FUNCNAME:
            {
                sal_Bool b = GetUseEnglishFuncName();
                pValues[nProp] <<= b;
            }
            break;
            case SCFORMULAOPT_SEP_ARG:
                pValues[nProp] <<= GetFormulaSepArg();
            break;
            case SCFORMULAOPT_SEP_ARRAY_ROW:
                pValues[nProp] <<= GetFormulaSepArrayRow();
            break;
            case SCFORMULAOPT_SEP_ARRAY_COL:
                pValues[nProp] <<= GetFormulaSepArrayCol();
            break;
            case SCFORMULAOPT_INDIRECT_GRAMMAR:
            {
                sal_Int32 nVal = -1;
                switch (GetIndirectFuncSyntax())
                {
                    case ::formula::FormulaGrammar::CONV_OOO:     nVal = 0; break;
                    case ::formula::FormulaGrammar::CONV_XL_A1:   nVal = 1; break;
                    case ::formula::FormulaGrammar::CONV_XL_R1C1: nVal = 2; break;
                    default: break;
                }
                pValues[nProp] <<= nVal;
            }
            break;
        }
    }
    PutProperties(aNames, aValues);
}

void ScFormulaCfg::SetOptions( const ScFormulaOptions& rNew )
{
    *(ScFormulaOptions*)this = rNew;
    SetModified();
}

void ScFormulaCfg::Notify( const ::com::sun::star::uno::Sequence< OUString >& ) {}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Reset option.<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * Version: MPL 1.1 / GPLv3+ / LGPLv3+
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Initial Developer of the Original Code is
 *       Albert Thuswaldner <albert.thuswaldner@gmail.com>
 * Portions created by the Initial Developer are Copyright (C) 2012 the
 * Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
 * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
 * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
 * instead of those above.
 */

#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/Sequence.hxx>
#include <com/sun/star/lang/Locale.hpp>
#include <com/sun/star/i18n/LocaleDataItem.hpp>

#include "formulaopt.hxx"
#include "miscuno.hxx"
#include "global.hxx"

using namespace utl;
using namespace com::sun::star::uno;
using ::com::sun::star::lang::Locale;
using ::com::sun::star::i18n::LocaleDataItem;
using ::rtl::OUString;

// -----------------------------------------------------------------------

TYPEINIT1(ScTpFormulaItem, SfxPoolItem);

// -----------------------------------------------------------------------

ScFormulaOptions::ScFormulaOptions()
{
    SetDefaults();
}

ScFormulaOptions::ScFormulaOptions( const ScFormulaOptions& rCpy ) :
    bUseEnglishFuncName ( rCpy.bUseEnglishFuncName ),
    eFormulaGrammar     ( rCpy.eFormulaGrammar ),
    aFormulaSepArg      ( rCpy.aFormulaSepArg ),
    aFormulaSepArrayRow ( rCpy.aFormulaSepArrayRow ),
    aFormulaSepArrayCol ( rCpy.aFormulaSepArrayCol )
{
}

ScFormulaOptions::~ScFormulaOptions()
{
}

void ScFormulaOptions::SetDefaults()
{
    bUseEnglishFuncName = false;
    eFormulaGrammar     = ::formula::FormulaGrammar::GRAM_NATIVE;

    // unspecified means use the current formula syntax.
    eIndirectFuncRefSyntax = formula::FormulaGrammar::CONV_UNSPECIFIED;

    ResetFormulaSeparators();
}

void ScFormulaOptions::ResetFormulaSeparators()
{
    GetDefaultFormulaSeparators(aFormulaSepArg, aFormulaSepArrayCol, aFormulaSepArrayRow);
}

void ScFormulaOptions::GetDefaultFormulaSeparators(
    rtl::OUString& rSepArg, rtl::OUString& rSepArrayCol, rtl::OUString& rSepArrayRow)
{
    // Defaults to the old separator values.
    rSepArg = OUString(RTL_CONSTASCII_USTRINGPARAM(";"));
    rSepArrayCol = OUString(RTL_CONSTASCII_USTRINGPARAM(";"));
    rSepArrayRow = OUString(RTL_CONSTASCII_USTRINGPARAM("|"));

    const Locale& rLocale = *ScGlobal::GetLocale();
    const OUString& rLang = rLocale.Language;
    if (rLang.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ru")))
        // Don't do automatic guess for these languages, and fall back to
        // the old separator set.
        return;

    const LocaleDataWrapper& rLocaleData = GetLocaleDataWrapper();
    const OUString& rDecSep  = rLocaleData.getNumDecimalSep();
    const OUString& rListSep = rLocaleData.getListSep();

    if (rDecSep.isEmpty() || rListSep.isEmpty())
        // Something is wrong.  Stick with the default separators.
        return;

    sal_Unicode cDecSep  = rDecSep.getStr()[0];
    sal_Unicode cListSep = rListSep.getStr()[0];

    // Excel by default uses system's list separator as the parameter
    // separator, which in English locales is a comma.  However, OOo's list
    // separator value is set to ';' for all English locales.  Because of this
    // discrepancy, we will hardcode the separator value here, for now.
    if (cDecSep == sal_Unicode('.'))
        cListSep = sal_Unicode(',');

    // Special case for de_CH locale.
    if (rLocale.Language.equalsAsciiL("de", 2) && rLocale.Country.equalsAsciiL("CH", 2))
        cListSep = sal_Unicode(';');

    // by default, the parameter separator equals the locale-specific
    // list separator.
    rSepArg = OUString(cListSep);

    if (cDecSep == cListSep && cDecSep != sal_Unicode(';'))
        // if the decimal and list separators are equal, set the
        // parameter separator to be ';', unless they are both
        // semicolon in which case don't change the decimal separator.
        rSepArg = OUString(RTL_CONSTASCII_USTRINGPARAM(";"));

    rSepArrayCol = OUString(RTL_CONSTASCII_USTRINGPARAM(","));
    if (cDecSep == sal_Unicode(','))
        rSepArrayCol = OUString(RTL_CONSTASCII_USTRINGPARAM("."));
    rSepArrayRow = OUString(RTL_CONSTASCII_USTRINGPARAM(";"));
}

const LocaleDataWrapper& ScFormulaOptions::GetLocaleDataWrapper()
{
    return *ScGlobal::pLocaleData;
}

ScFormulaOptions& ScFormulaOptions::operator=( const ScFormulaOptions& rCpy )
{
    bUseEnglishFuncName = rCpy.bUseEnglishFuncName;
    eFormulaGrammar     = rCpy.eFormulaGrammar;
    aFormulaSepArg      = rCpy.aFormulaSepArg;
    aFormulaSepArrayRow = rCpy.aFormulaSepArrayRow;
    aFormulaSepArrayCol = rCpy.aFormulaSepArrayCol;
    return *this;
}

bool ScFormulaOptions::operator==( const ScFormulaOptions& rOpt ) const
{
    return bUseEnglishFuncName == rOpt.bUseEnglishFuncName
        && eFormulaGrammar     == rOpt.eFormulaGrammar
        && aFormulaSepArg      == rOpt.aFormulaSepArg
        && aFormulaSepArrayRow == rOpt.aFormulaSepArrayRow
        && aFormulaSepArrayCol == rOpt.aFormulaSepArrayCol;
}

bool ScFormulaOptions::operator!=( const ScFormulaOptions& rOpt ) const
{
    return !(operator==(rOpt));
}

// -----------------------------------------------------------------------

ScTpFormulaItem::ScTpFormulaItem( sal_uInt16 nWhichP, const ScFormulaOptions& rOpt ) :
    SfxPoolItem ( nWhichP ),
    theOptions  ( rOpt )
{
}

ScTpFormulaItem::ScTpFormulaItem( const ScTpFormulaItem& rItem ) :
    SfxPoolItem ( rItem ),
    theOptions  ( rItem.theOptions )
{
}

ScTpFormulaItem::~ScTpFormulaItem()
{
}

String ScTpFormulaItem::GetValueText() const
{
    return String::CreateFromAscii( "ScTpFormulaItem" );
}

int ScTpFormulaItem::operator==( const SfxPoolItem& rItem ) const
{
    OSL_ENSURE( SfxPoolItem::operator==( rItem ), "unequal Which or Type" );

    const ScTpFormulaItem& rPItem = (const ScTpFormulaItem&)rItem;
    return ( theOptions == rPItem.theOptions );
}

SfxPoolItem* ScTpFormulaItem::Clone( SfxItemPool * ) const
{
    return new ScTpFormulaItem( *this );
}

// -----------------------------------------------------------------------

#define CFGPATH_FORMULA           "Office.Calc/Formula"

#define SCFORMULAOPT_GRAMMAR           0
#define SCFORMULAOPT_ENGLISH_FUNCNAME  1
#define SCFORMULAOPT_SEP_ARG           2
#define SCFORMULAOPT_SEP_ARRAY_ROW     3
#define SCFORMULAOPT_SEP_ARRAY_COL     4
#define SCFORMULAOPT_INDIRECT_GRAMMAR  5
#define SCFORMULAOPT_COUNT             6

Sequence<OUString> ScFormulaCfg::GetPropertyNames()
{
    static const char* aPropNames[] =
    {
        "Syntax/Grammar",             // SCFORMULAOPT_GRAMMAR
        "Syntax/EnglishFunctionName", // SCFORMULAOPT_ENGLISH_FUNCNAME
        "Syntax/SeparatorArg",        // SCFORMULAOPT_SEP_ARG
        "Syntax/SeparatorArrayRow",   // SCFORMULAOPT_SEP_ARRAY_ROW
        "Syntax/SeparatorArrayCol",   // SCFORMULAOPT_SEP_ARRAY_COL
        "Syntax/IndirectFuncGrammar", // SCFORMULAOPT_INDIRECT_GRAMMAR
    };
    Sequence<OUString> aNames(SCFORMULAOPT_COUNT);
    OUString* pNames = aNames.getArray();
    for (int i = 0; i < SCFORMULAOPT_COUNT; ++i)
        pNames[i] = OUString::createFromAscii(aPropNames[i]);

    return aNames;
}

ScFormulaCfg::ScFormulaCfg() :
    ConfigItem( OUString(RTL_CONSTASCII_USTRINGPARAM( CFGPATH_FORMULA )) )
{
    Sequence<OUString> aNames = GetPropertyNames();
    Sequence<Any> aValues = GetProperties(aNames);
    const Any* pValues = aValues.getConstArray();
    OSL_ENSURE(aValues.getLength() == aNames.getLength(), "GetProperties failed");
    if(aValues.getLength() == aNames.getLength())
    {
        sal_Int32 nIntVal = 0;
        for(int nProp = 0; nProp < aNames.getLength(); nProp++)
        {
            if(pValues[nProp].hasValue())
            {
                switch(nProp)
                {
                case SCFORMULAOPT_GRAMMAR:
                {
                    // Get default value in case this option is not set.
                    ::formula::FormulaGrammar::Grammar eGram = GetFormulaSyntax();

                    do
                    {
                        if (!(pValues[nProp] >>= nIntVal))
                            // extractino failed.
                            break;

                        switch (nIntVal)
                        {
                            case 0: // Calc A1
                                eGram = ::formula::FormulaGrammar::GRAM_NATIVE;
                            break;
                            case 1: // Excel A1
                                eGram = ::formula::FormulaGrammar::GRAM_NATIVE_XL_A1;
                            break;
                            case 2: // Excel R1C1
                                eGram = ::formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1;
                            break;
                            default:
                                ;
                        }
                    }
                    while (false);
                    SetFormulaSyntax(eGram);
                }
                break;
                case SCFORMULAOPT_ENGLISH_FUNCNAME:
                {
                    sal_Bool bEnglish = false;
                    if (pValues[nProp] >>= bEnglish)
                        SetUseEnglishFuncName(bEnglish);
                }
                break;
                case SCFORMULAOPT_SEP_ARG:
                {
                    OUString aSep;
                    if ((pValues[nProp] >>= aSep) && !aSep.isEmpty())
                        SetFormulaSepArg(aSep);
                }
                break;
                case SCFORMULAOPT_SEP_ARRAY_ROW:
                {
                    OUString aSep;
                    if ((pValues[nProp] >>= aSep) && !aSep.isEmpty())
                        SetFormulaSepArrayRow(aSep);
                }
                break;
                case SCFORMULAOPT_SEP_ARRAY_COL:
                {
                    OUString aSep;
                    if ((pValues[nProp] >>= aSep) && !aSep.isEmpty())
                        SetFormulaSepArrayCol(aSep);
                }
                case SCFORMULAOPT_INDIRECT_GRAMMAR:
                {
                    // Get default value in case this option is not set.
                    ::formula::FormulaGrammar::AddressConvention eConv = GetIndirectFuncSyntax();

                    do
                    {
                        if (!(pValues[nProp] >>= nIntVal))
                            // extractino failed.
                            break;

                        switch (nIntVal)
                        {
                            case -1: // Same as the formula grammar.
                                eConv = formula::FormulaGrammar::CONV_UNSPECIFIED;
                            break;
                            case 0: // Calc A1
                                eConv = formula::FormulaGrammar::CONV_OOO;
                            break;
                            case 1: // Excel A1
                                eConv = formula::FormulaGrammar::CONV_XL_A1;
                            break;
                            case 2: // Excel R1C1
                                eConv = formula::FormulaGrammar::CONV_XL_R1C1;
                            break;
                            default:
                                ;
                        }
                    }
                    while (false);
                    SetIndirectFuncSyntax(eConv);
                }
                break;
                break;
                }
            }
        }
    }
}

void ScFormulaCfg::Commit()
{
    Sequence<OUString> aNames = GetPropertyNames();
    Sequence<Any> aValues(aNames.getLength());
    Any* pValues = aValues.getArray();

    for (int nProp = 0; nProp < aNames.getLength(); ++nProp)
    {
        switch (nProp)
        {
            case SCFORMULAOPT_GRAMMAR :
            {
                sal_Int32 nVal = 0;
                switch (GetFormulaSyntax())
                {
                    case ::formula::FormulaGrammar::GRAM_NATIVE_XL_A1:    nVal = 1; break;
                    case ::formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1:  nVal = 2; break;
                    default: break;
                }
                pValues[nProp] <<= nVal;
            }
            break;
            case SCFORMULAOPT_ENGLISH_FUNCNAME:
            {
                sal_Bool b = GetUseEnglishFuncName();
                pValues[nProp] <<= b;
            }
            break;
            case SCFORMULAOPT_SEP_ARG:
                pValues[nProp] <<= GetFormulaSepArg();
            break;
            case SCFORMULAOPT_SEP_ARRAY_ROW:
                pValues[nProp] <<= GetFormulaSepArrayRow();
            break;
            case SCFORMULAOPT_SEP_ARRAY_COL:
                pValues[nProp] <<= GetFormulaSepArrayCol();
            break;
            case SCFORMULAOPT_INDIRECT_GRAMMAR:
            {
                sal_Int32 nVal = -1;
                switch (GetIndirectFuncSyntax())
                {
                    case ::formula::FormulaGrammar::CONV_OOO:     nVal = 0; break;
                    case ::formula::FormulaGrammar::CONV_XL_A1:   nVal = 1; break;
                    case ::formula::FormulaGrammar::CONV_XL_R1C1: nVal = 2; break;
                    default: break;
                }
                pValues[nProp] <<= nVal;
            }
            break;
        }
    }
    PutProperties(aNames, aValues);
}

void ScFormulaCfg::SetOptions( const ScFormulaOptions& rNew )
{
    *(ScFormulaOptions*)this = rNew;
    SetModified();
}

void ScFormulaCfg::Notify( const ::com::sun::star::uno::Sequence< OUString >& ) {}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>#include "paddle/framework/grad_op_builder.h"
#include <gtest/gtest.h>
#include "paddle/framework/op_registry.h"
#include "paddle/framework/operator.h"

USE_OP(add);

namespace paddle {
namespace framework {

class MutiInOutOpMaker : public OpProtoAndCheckerMaker {
 public:
  MutiInOutOpMaker(OpProto *proto, OpAttrChecker *op_checker)
      : OpProtoAndCheckerMaker(proto, op_checker) {
    AddInput("In1", "a single input");
    AddInput("In2_mult", "a multiple input").AsDuplicable();
    AddInput("In3", "another single input");
    AddOutput("Out1", "a single output");
    AddOutput("Out2_mult", "a multiple output").AsDuplicable();
    AddComment("test op with multiple inputs and outputs");
  }
};

class IOIgnoredOpMaker : public OpProtoAndCheckerMaker {
 public:
  IOIgnoredOpMaker(OpProto *proto, OpAttrChecker *op_checker)
      : OpProtoAndCheckerMaker(proto, op_checker) {
    AddInput("In1", "a single input");
    AddInput("In2_mult", "a multiple input").AsDuplicable().NotInGradient();
    AddInput("In3_mult", "another multiple input").AsDuplicable();
    AddOutput("Out1_mult", "a multiple output").AsDuplicable();
    AddOutput("Out2", "a single output").NotInGradient();
    AddComment("op with inputs and outputs ignored in gradient calculating");
  }
};

}  // namespace framework
}  // namespace paddle

namespace f = paddle::framework;

TEST(GradOpBuilder, AddTwo) {
  std::shared_ptr<f::OperatorBase> add_op(f::OpRegistry::CreateOp(
      "add", {{"X", {"x"}}, {"Y", {"y"}}}, {{"Out", {"out"}}}, {}));
  std::shared_ptr<f::OperatorBase> grad_add_op =
      f::OpRegistry::CreateGradOp(*add_op);
  EXPECT_EQ(grad_add_op->Inputs().size(), 4UL);
  EXPECT_EQ(grad_add_op->Outputs().size(), 2UL);
  EXPECT_EQ(grad_add_op->Input("X"), "x");
  EXPECT_EQ(grad_add_op->Input("Y"), "y");
  EXPECT_EQ(grad_add_op->Input("Out"), "out");
  EXPECT_EQ(grad_add_op->Input(f::GradVarName("Out")), f::GradVarName("out"));
  EXPECT_EQ(grad_add_op->Output(f::GradVarName("X")), f::GradVarName("x"));
  EXPECT_EQ(grad_add_op->Output(f::GradVarName("Y")), f::GradVarName("y"));
}

REGISTER_OP(mult_io, f::NOP, f::MutiInOutOpMaker, mult_io_grad, f::NOP);
REGISTER_OP(io_ignored, f::NOP, f::IOIgnoredOpMaker, io_ignored_grad, f::NOP);

TEST(GradOpBuilder, MutiInOut) {
  std::shared_ptr<f::OperatorBase> test_op(f::OpRegistry::CreateOp(
      "mult_io", {{"In1", {"in1"}},
                  {"In2_mult", {"in2_1", "in2_2", "in2_3"}},
                  {"In3", {"in3"}}},
      {{"Out1", {"out1"}}, {"Out2_mult", {"out2_1", "out2_2"}}}, {}));
  std::shared_ptr<f::OperatorBase> grad_test_op =
      f::OpRegistry::CreateGradOp(*test_op);

  ASSERT_EQ(grad_test_op->Inputs().size(), 3UL + 2UL + 2UL);
  EXPECT_EQ(grad_test_op->Input("In1"), "in1");
  EXPECT_EQ(grad_test_op->Inputs("In2_mult"),
            std::vector<std::string>({"in2_1", "in2_2", "in2_3"}));
  EXPECT_EQ(grad_test_op->Input("In3"), "in3");
  EXPECT_EQ(grad_test_op->Input("Out1"), "out1");
  EXPECT_EQ(grad_test_op->Inputs("Out2_mult"),
            std::vector<std::string>({"out2_1", "out2_2"}));
  EXPECT_EQ(grad_test_op->Input(f::GradVarName("Out1")),
            f::GradVarName("out1"));
  EXPECT_EQ(grad_test_op->Inputs(f::GradVarName("Out2_mult")),
            std::vector<std::string>(
                {f::GradVarName("out2_1"), f::GradVarName("out2_2")}));

  ASSERT_EQ(grad_test_op->Outputs().size(), 3UL);
  EXPECT_EQ(grad_test_op->Output(f::GradVarName("In1")), f::GradVarName("in1"));
  EXPECT_EQ(grad_test_op->Outputs(f::GradVarName("In2_mult")),
            std::vector<std::string>({f::GradVarName("in2_1"),
                                      f::GradVarName("in2_2"),
                                      f::GradVarName("in2_3")}));
  EXPECT_EQ(grad_test_op->Output(f::GradVarName("In3")), f::GradVarName("in3"));
}

TEST(GradOpBuilder, IOIgnoredInGradient) {
  std::shared_ptr<f::OperatorBase> test_op(f::OpRegistry::CreateOp(
      "io_ignored", {{"In1", {"in1"}},
                     {"In2_mult", {"in2_1", "in2_2"}},
                     {"In3_mult", {"in3_1", "in3_2"}}},
      {{"Out1_mult", {"out1_1", "out1_2"}}, {"Out2", {"out2"}}}, {}));
  std::shared_ptr<f::OperatorBase> grad_test_op =
      f::OpRegistry::CreateGradOp(*test_op);

  // 'In2' and 'Out2' are ignored in gradient calculating
  ASSERT_EQ(grad_test_op->Inputs().size(), 2UL + 1UL + 2UL);
  EXPECT_EQ(grad_test_op->Input("In1"), "in1");
  EXPECT_EQ(grad_test_op->Inputs("In3_mult"),
            std::vector<std::string>({"in3_1", "in3_2"}));
  EXPECT_EQ(grad_test_op->Inputs("Out1_mult"),
            std::vector<std::string>({"out1_1", "out1_2"}));
  EXPECT_EQ(grad_test_op->Inputs(f::GradVarName("Out1_mult")),
            std::vector<std::string>(
                {f::GradVarName("out1_1"), f::GradVarName("out1_2")}));
  EXPECT_EQ(grad_test_op->Input(f::GradVarName("Out2")),
            f::GradVarName("out2"));

  ASSERT_EQ(grad_test_op->Outputs().size(), 3UL);
  EXPECT_EQ(grad_test_op->Output(f::GradVarName("In1")), f::GradVarName("in1"));
  EXPECT_EQ(grad_test_op->Outputs(f::GradVarName("In2_mult")),
            std::vector<std::string>(
                {f::GradVarName("in2_1"), f::GradVarName("in2_2")}));
  EXPECT_EQ(grad_test_op->Outputs(f::GradVarName("In3_mult")),
            std::vector<std::string>(
                {f::GradVarName("in3_1"), f::GradVarName("in3_2")}));
}

TEST(GradOpDescBuilder, MutiInOut) {
  f::OpDescBind *forw_op = new f::OpDescBind();
  forw_op->SetType("mult_io");
  forw_op->SetInput("In1", {"in1"});
  forw_op->SetInput("In2_mult", {"in2_1", "in2_2", "in2_3"});
  forw_op->SetInput("In3", {"in3"});
  forw_op->SetOutput("Out1", {"out1"});
  forw_op->SetOutput("Out2_mult", {"out2_1", "out2_2"});

  f::OpDescBind *grad_op = new f::OpDescBind();
  f::CompleteGradOpDesc(forw_op, grad_op);

  ASSERT_EQ(grad_op->InputNames().size(), 3UL + 2UL + 2UL);
  EXPECT_EQ(grad_op->Input("In1"), std::vector<std::string>({"in1"}));
  EXPECT_EQ(grad_op->Input("In2_mult"),
            std::vector<std::string>({"in2_1", "in2_2", "in2_3"}));
  EXPECT_EQ(grad_op->Input("In3"), std::vector<std::string>({"in3"}));
  EXPECT_EQ(grad_op->Input("Out1"), std::vector<std::string>({"out1"}));
  EXPECT_EQ(grad_op->Input("Out2_mult"),
            std::vector<std::string>({"out2_1", "out2_2"}));
  EXPECT_EQ(grad_op->Input(f::GradVarName("Out1")),
            std::vector<std::string>({f::GradVarName("out1")}));
  EXPECT_EQ(grad_op->Input(f::GradVarName("Out2_mult")),
            std::vector<std::string>(
                {f::GradVarName("out2_1"), f::GradVarName("out2_2")}));

  ASSERT_EQ(grad_op->OutputNames().size(), 3UL);
  EXPECT_EQ(grad_op->Output(f::GradVarName("In1")),
            std::vector<std::string>({f::GradVarName("in1")}));
  EXPECT_EQ(grad_op->Output(f::GradVarName("In2_mult")),
            std::vector<std::string>({f::GradVarName("in2_1"),
                                      f::GradVarName("in2_2"),
                                      f::GradVarName("in2_3")}));
  EXPECT_EQ(grad_op->Output(f::GradVarName("In3")),
            std::vector<std::string>({f::GradVarName("in3")}));
}
<commit_msg>Add unit tests<commit_after>#include "paddle/framework/grad_op_builder.h"
#include <gtest/gtest.h>
#include "paddle/framework/op_registry.h"
#include "paddle/framework/operator.h"

USE_OP(add);

namespace paddle {
namespace framework {

class MutiInOutOpMaker : public OpProtoAndCheckerMaker {
 public:
  MutiInOutOpMaker(OpProto *proto, OpAttrChecker *op_checker)
      : OpProtoAndCheckerMaker(proto, op_checker) {
    AddInput("In1", "a single input");
    AddInput("In2_mult", "a multiple input").AsDuplicable();
    AddInput("In3", "another single input");
    AddOutput("Out1", "a single output");
    AddOutput("Out2_mult", "a multiple output").AsDuplicable();
    AddComment("test op with multiple inputs and outputs");
  }
};

class IOIgnoredOpMaker : public OpProtoAndCheckerMaker {
 public:
  IOIgnoredOpMaker(OpProto *proto, OpAttrChecker *op_checker)
      : OpProtoAndCheckerMaker(proto, op_checker) {
    AddInput("In1", "a single input");
    AddInput("In2_mult", "a multiple input").AsDuplicable().NotInGradient();
    AddInput("In3_mult", "another multiple input").AsDuplicable();
    AddOutput("Out1_mult", "a multiple output").AsDuplicable();
    AddOutput("Out2", "a single output").NotInGradient();
    AddComment("op with inputs and outputs ignored in gradient calculating");
  }
};

}  // namespace framework
}  // namespace paddle

namespace f = paddle::framework;

TEST(GradOpBuilder, AddTwo) {
  std::shared_ptr<f::OperatorBase> add_op(f::OpRegistry::CreateOp(
      "add", {{"X", {"x"}}, {"Y", {"y"}}}, {{"Out", {"out"}}}, {}));
  std::shared_ptr<f::OperatorBase> grad_add_op =
      f::OpRegistry::CreateGradOp(*add_op);
  EXPECT_EQ(grad_add_op->Inputs().size(), 4UL);
  EXPECT_EQ(grad_add_op->Outputs().size(), 2UL);
  EXPECT_EQ(grad_add_op->Input("X"), "x");
  EXPECT_EQ(grad_add_op->Input("Y"), "y");
  EXPECT_EQ(grad_add_op->Input("Out"), "out");
  EXPECT_EQ(grad_add_op->Input(f::GradVarName("Out")), f::GradVarName("out"));
  EXPECT_EQ(grad_add_op->Output(f::GradVarName("X")), f::GradVarName("x"));
  EXPECT_EQ(grad_add_op->Output(f::GradVarName("Y")), f::GradVarName("y"));
}

REGISTER_OP(mult_io, f::NOP, f::MutiInOutOpMaker, mult_io_grad, f::NOP);
REGISTER_OP(io_ignored, f::NOP, f::IOIgnoredOpMaker, io_ignored_grad, f::NOP);

TEST(GradOpBuilder, MutiInOut) {
  std::shared_ptr<f::OperatorBase> test_op(f::OpRegistry::CreateOp(
      "mult_io", {{"In1", {"in1"}},
                  {"In2_mult", {"in2_1", "in2_2", "in2_3"}},
                  {"In3", {"in3"}}},
      {{"Out1", {"out1"}}, {"Out2_mult", {"out2_1", "out2_2"}}}, {}));
  std::shared_ptr<f::OperatorBase> grad_test_op =
      f::OpRegistry::CreateGradOp(*test_op);

  ASSERT_EQ(grad_test_op->Inputs().size(), 3UL + 2UL + 2UL);
  EXPECT_EQ(grad_test_op->Input("In1"), "in1");
  EXPECT_EQ(grad_test_op->Inputs("In2_mult"),
            std::vector<std::string>({"in2_1", "in2_2", "in2_3"}));
  EXPECT_EQ(grad_test_op->Input("In3"), "in3");
  EXPECT_EQ(grad_test_op->Input("Out1"), "out1");
  EXPECT_EQ(grad_test_op->Inputs("Out2_mult"),
            std::vector<std::string>({"out2_1", "out2_2"}));
  EXPECT_EQ(grad_test_op->Input(f::GradVarName("Out1")),
            f::GradVarName("out1"));
  EXPECT_EQ(grad_test_op->Inputs(f::GradVarName("Out2_mult")),
            std::vector<std::string>(
                {f::GradVarName("out2_1"), f::GradVarName("out2_2")}));

  ASSERT_EQ(grad_test_op->Outputs().size(), 3UL);
  EXPECT_EQ(grad_test_op->Output(f::GradVarName("In1")), f::GradVarName("in1"));
  EXPECT_EQ(grad_test_op->Outputs(f::GradVarName("In2_mult")),
            std::vector<std::string>({f::GradVarName("in2_1"),
                                      f::GradVarName("in2_2"),
                                      f::GradVarName("in2_3")}));
  EXPECT_EQ(grad_test_op->Output(f::GradVarName("In3")), f::GradVarName("in3"));
}

TEST(GradOpBuilder, IOIgnoredInGradient) {
  std::shared_ptr<f::OperatorBase> test_op(f::OpRegistry::CreateOp(
      "io_ignored", {{"In1", {"in1"}},
                     {"In2_mult", {"in2_1", "in2_2"}},
                     {"In3_mult", {"in3_1", "in3_2"}}},
      {{"Out1_mult", {"out1_1", "out1_2"}}, {"Out2", {"out2"}}}, {}));
  std::shared_ptr<f::OperatorBase> grad_test_op =
      f::OpRegistry::CreateGradOp(*test_op);

  // 'In2' and 'Out2' are ignored in gradient calculating
  ASSERT_EQ(grad_test_op->Inputs().size(), 2UL + 1UL + 2UL);
  EXPECT_EQ(grad_test_op->Input("In1"), "in1");
  EXPECT_EQ(grad_test_op->Inputs("In3_mult"),
            std::vector<std::string>({"in3_1", "in3_2"}));
  EXPECT_EQ(grad_test_op->Inputs("Out1_mult"),
            std::vector<std::string>({"out1_1", "out1_2"}));
  EXPECT_EQ(grad_test_op->Inputs(f::GradVarName("Out1_mult")),
            std::vector<std::string>(
                {f::GradVarName("out1_1"), f::GradVarName("out1_2")}));
  EXPECT_EQ(grad_test_op->Input(f::GradVarName("Out2")),
            f::GradVarName("out2"));

  ASSERT_EQ(grad_test_op->Outputs().size(), 3UL);
  EXPECT_EQ(grad_test_op->Output(f::GradVarName("In1")), f::GradVarName("in1"));
  EXPECT_EQ(grad_test_op->Outputs(f::GradVarName("In2_mult")),
            std::vector<std::string>(
                {f::GradVarName("in2_1"), f::GradVarName("in2_2")}));
  EXPECT_EQ(grad_test_op->Outputs(f::GradVarName("In3_mult")),
            std::vector<std::string>(
                {f::GradVarName("in3_1"), f::GradVarName("in3_2")}));
}

TEST(GradOpDescBuilder, MutiInOut) {
  f::OpDescBind *forw_op = new f::OpDescBind();
  forw_op->SetType("mult_io");
  forw_op->SetInput("In1", {"in1"});
  forw_op->SetInput("In2_mult", {"in2_1", "in2_2", "in2_3"});
  forw_op->SetInput("In3", {"in3"});
  forw_op->SetOutput("Out1", {"out1"});
  forw_op->SetOutput("Out2_mult", {"out2_1", "out2_2"});

  f::OpDescBind *grad_op = new f::OpDescBind();
  f::CompleteGradOpDesc(forw_op, grad_op);

  EXPECT_EQ(grad_op->Type(), "mult_io_grad");
  ASSERT_EQ(grad_op->InputNames().size(), 3UL + 2UL + 2UL);
  EXPECT_EQ(grad_op->Input("In1"), std::vector<std::string>({"in1"}));
  EXPECT_EQ(grad_op->Input("In2_mult"),
            std::vector<std::string>({"in2_1", "in2_2", "in2_3"}));
  EXPECT_EQ(grad_op->Input("In3"), std::vector<std::string>({"in3"}));
  EXPECT_EQ(grad_op->Input("Out1"), std::vector<std::string>({"out1"}));
  EXPECT_EQ(grad_op->Input("Out2_mult"),
            std::vector<std::string>({"out2_1", "out2_2"}));
  EXPECT_EQ(grad_op->Input(f::GradVarName("Out1")),
            std::vector<std::string>({f::GradVarName("out1")}));
  EXPECT_EQ(grad_op->Input(f::GradVarName("Out2_mult")),
            std::vector<std::string>(
                {f::GradVarName("out2_1"), f::GradVarName("out2_2")}));

  ASSERT_EQ(grad_op->OutputNames().size(), 3UL);
  EXPECT_EQ(grad_op->Output(f::GradVarName("In1")),
            std::vector<std::string>({f::GradVarName("in1")}));
  EXPECT_EQ(grad_op->Output(f::GradVarName("In2_mult")),
            std::vector<std::string>({f::GradVarName("in2_1"),
                                      f::GradVarName("in2_2"),
                                      f::GradVarName("in2_3")}));
  EXPECT_EQ(grad_op->Output(f::GradVarName("In3")),
            std::vector<std::string>({f::GradVarName("in3")}));
  delete forw_op;
  delete grad_op;
}

TEST(GradOpDescBuilder, IOIgnoredInGradient) {
  f::OpDescBind *forw_op = new f::OpDescBind();
  forw_op->SetType("io_ignored");
  forw_op->SetInput("In1", {"in1"});
  forw_op->SetInput("In2_mult", {"in2_1", "in2_2"});
  forw_op->SetInput("In3_mult", {"in3_1", "in3_2"});
  forw_op->SetOutput("Out1_mult", {"out1_1", "out1_2"});
  forw_op->SetOutput("Out2", {"out2"});

  f::OpDescBind *grad_op = new f::OpDescBind();
  f::CompleteGradOpDesc(forw_op, grad_op);

  EXPECT_EQ(grad_op->Type(), "io_ignored_grad");
  // 'In2' and 'Out2' are ignored in gradient calculating
  ASSERT_EQ(grad_op->InputNames().size(), 2UL + 1UL + 2UL);
  EXPECT_EQ(grad_op->Input("In1"), std::vector<std::string>({"in1"}));
  EXPECT_EQ(grad_op->Input("In3_mult"),
            std::vector<std::string>({"in3_1", "in3_2"}));
  EXPECT_EQ(grad_op->Input("Out1_mult"),
            std::vector<std::string>({"out1_1", "out1_2"}));
  EXPECT_EQ(grad_op->Input(f::GradVarName("Out1_mult")),
            std::vector<std::string>(
                {f::GradVarName("out1_1"), f::GradVarName("out1_2")}));
  EXPECT_EQ(grad_op->Input(f::GradVarName("Out2")),
            std::vector<std::string>({f::GradVarName("out2")}));

  ASSERT_EQ(grad_op->OutputNames().size(), 3UL);
  EXPECT_EQ(grad_op->Output(f::GradVarName("In1")),
            std::vector<std::string>({f::GradVarName("in1")}));
  EXPECT_EQ(grad_op->Output(f::GradVarName("In2_mult")),
            std::vector<std::string>(
                {f::GradVarName("in2_1"), f::GradVarName("in2_2")}));
  EXPECT_EQ(grad_op->Output(f::GradVarName("In3_mult")),
            std::vector<std::string>(
                {f::GradVarName("in3_1"), f::GradVarName("in3_2")}));
  delete forw_op;
  delete grad_op;
}<|endoftext|>


<commit_before>/* http_bidder_interface.cc
   Eric Robert, 2 April 2014
   Copyright (c) 2011 Datacratic.  All rights reserved.
*/

#include "http_bidder_interface.h"
#include "jml/db/persistent.h"
#include "soa/service/http_client.h"
#include "rtbkit/common/messages.h"
#include "rtbkit/plugins/bid_request/openrtb_bid_request.h"
#include "rtbkit/openrtb/openrtb_parsing.h"
#include "rtbkit/core/router/router.h"

using namespace Datacratic;
using namespace RTBKIT;

namespace {
    DefaultDescription<OpenRTB::BidRequest> desc;

    void tagRequest(OpenRTB::BidRequest &request,
                    const std::map<std::string, BidInfo> &bidders)
    {

        for (const auto &bidder: bidders) {
            const auto &agentConfig = bidder.second.agentConfig;
            const auto &spots = bidder.second.imp;
            const auto &creatives = agentConfig->creatives;

            Json::Value creativesValue(Json::arrayValue);
            for (const auto &spot: spots) {
                const int adSpotIndex = spot.first;
                ExcCheck(adSpotIndex >= 0 && adSpotIndex < request.imp.size(),
                         "adSpotIndex out of range");
                auto &imp = request.imp[adSpotIndex];
                auto &ext = imp.ext;
                for (int creativeIndex: spot.second) {
                    ExcCheck(creativeIndex >= 0 && creativeIndex < creatives.size(),
                             "creativeIndex out of range");
                    const int creativeId = creatives[creativeIndex].id;
                    creativesValue.append(creativeId);
                }

                ext["allowed_ids"][std::to_string(agentConfig->externalId)] =
                    std::move(creativesValue);

            }

        }

    }
}

HttpBidderInterface::HttpBidderInterface(std::string name,
                                         std::shared_ptr<ServiceProxies> proxies,
                                         Json::Value const & json) {
    host = json["host"].asString();
    path = json["path"].asString();
    httpClient.reset(new HttpClient(host));
    loop.addSource("HttpBidderInterface::httpClient", httpClient);
}

void HttpBidderInterface::sendAuctionMessage(std::shared_ptr<Auction> const & auction,
                                             double timeLeftMs,
                                             std::map<std::string, BidInfo> const & bidders) {
    using namespace std;
    for(auto & item : bidders) {
        auto & agent = item.first;
        auto & info = router->agents[agent];
        const auto &config = info.config;
        BidRequest originalRequest = *auction->request;
        WinCostModel wcm = auction->exchangeConnector->getWinCostModel(*auction, *info.config);

        OpenRTB::BidRequest openRtbRequest = toOpenRtb(originalRequest);
        bool ok = prepareRequest(openRtbRequest, originalRequest, bidders);
        /* If we took too much time processing the request, then we don't send it.
           Instead, we're making null bids for each impression
        */
        if (!ok) {
            Bids bids;
            for_each(begin(openRtbRequest.imp), end(openRtbRequest.imp),
                     [&](const OpenRTB::Impression &imp) {
                Bid theBid;
                theBid.price = USD_CPM(0);
                bids.push_back(move(theBid));
            });
            submitBids(agent, auction->id, bids, wcm);
            return;
        }
        StructuredJsonPrintingContext context;
        desc.printJson(&openRtbRequest, context);
        auto requestStr = context.output.toString();

        /* We need to capture by copy inside the lambda otherwise we might get
           a dangling reference if we go out of scope before receiving the http response
        */
        auto callbacks = std::make_shared<HttpClientSimpleCallbacks>(
                [=](const HttpRequest &, HttpClientError errorCode,
                    int, const std::string &, const std::string &body)
                {
                    if (errorCode != HttpClientError::NONE) {
                        auto toErrorString = [](HttpClientError code) -> std::string {
                            switch (code) {
                                #define CASE(code) \
                                    case code: \
                                        return #code;
                                CASE(HttpClientError::NONE)
                                CASE(HttpClientError::UNKNOWN)
                                CASE(HttpClientError::TIMEOUT)
                                CASE(HttpClientError::HOST_NOT_FOUND)
                                CASE(HttpClientError::COULD_NOT_CONNECT)
                                #undef CASE
                            }
                            ExcCheck(false, "Invalid code path");
                            return "";
                        };
                        cerr << "Error requesting " << host
                                  << ": " << toErrorString(errorCode);
                      }
                      else {
                        // cerr << "Response: " << body << endl;
                         OpenRTB::BidResponse response;
                         ML::Parse_Context context("payload",
                               body.c_str(), body.size());
                         StreamingJsonParsingContext jsonContext(context);
                         static DefaultDescription<OpenRTB::BidResponse> respDesc;
                         respDesc.parseJson(&response, jsonContext);

                         for (const auto &seatbid: response.seatbid) {
                             Bids bids;

                             for (const auto &bid: seatbid.bid) {
                                 Bid theBid;

                                 /* Looping over the creatives to find the corresponding
                                    creativeIndex
                                 */
                                 int crid = bid.crid.toInt();
                                 auto crIt = find_if(
                                    begin(config->creatives), end(config->creatives),
                                    [&](const Creative &creative) {
                                        return creative.id == crid;
                                 });

                                 if (crIt == end(config->creatives)) {
                                     throw ML::Exception(ML::format(
                                        "Unknown creative id: %d", crid));
                                 }

                                 auto creativeIndex = distance(begin(config->creatives),
                                                               crIt);
                                 theBid.creativeIndex = creativeIndex;
                                 theBid.price = USD_CPM(bid.price.val);
                                 theBid.priority = 0.0;

                                 /* Looping over the impressions to find the corresponding
                                    adSpotIndex
                                 */
                                 auto impIt = find_if(
                                     begin(openRtbRequest.imp), end(openRtbRequest.imp),
                                     [&](const OpenRTB::Impression &imp) {
                                         return imp.id == bid.impid;
                                 });
                                 if (impIt == end(openRtbRequest.imp)) {
                                     throw ML::Exception(ML::format(
                                         "Unknown impression id: %s", bid.impid.toString()));
                                 }

                                 auto spotIndex = distance(begin(openRtbRequest.imp),
                                                                 impIt);
                                 theBid.spotIndex = spotIndex;

                                 bids.push_back(std::move(theBid));
                             }
                             submitBids(agent, auction->id, bids, wcm);
                         }
                     }
                }
        );

        HttpRequest::Content reqContent { requestStr, "application/json" };
        RestParams headers { { "x-openrtb-version", "2.1" } };
       // std::cerr << "Sending HTTP POST to: " << host << " " << path << std::endl;
       // std::cerr << "Content " << reqContent.str << std::endl;

        httpClient->post(path, callbacks, reqContent,
                         { } /* queryParams */, headers);
    }
}

void HttpBidderInterface::sendWinMessage(std::string const & agent,
                                         std::string const & id,
                                         Amount price) {
}

void HttpBidderInterface::sendWinMessage(std::string const & agent,
                                         Amount price,
                                         FinishedInfo const & event) {
}

void HttpBidderInterface::sendLateWinMessage(std::string const & agent,
                                             Amount price,
                                             FinishedInfo const & event) {
}

void HttpBidderInterface::sendLossMessage(std::string const & agent,
                                          std::string const & id) {
}

void HttpBidderInterface::sendLossMessage(std::string const & agent,
                                          FinishedInfo const & event) {
}

void HttpBidderInterface::sendCampaignEventMessage(std::string const & agent,
                                                   std::string const & label,
                                                   FinishedInfo const & event) {
}

void HttpBidderInterface::sendBidLostMessage(std::string const & agent,
                                             std::shared_ptr<Auction> const & auction) {
}

void HttpBidderInterface::sendBidDroppedMessage(std::string const & agent,
                                                std::shared_ptr<Auction> const & auction) {
}

void HttpBidderInterface::sendBidInvalidMessage(std::string const & agent,
                                                std::string const & reason,
                                                std::shared_ptr<Auction> const & auction) {
}

void HttpBidderInterface::sendNoBudgetMessage(std::string const & agent,
                                              std::shared_ptr<Auction> const & auction) {
}

void HttpBidderInterface::sendTooLateMessage(std::string const & agent,
                                             std::shared_ptr<Auction> const & auction) {
}

void HttpBidderInterface::sendMessage(std::string const & agent,
                                      std::string const & message) {
}

void HttpBidderInterface::sendErrorMessage(std::string const & agent,
                                           std::string const & error,
                                           std::vector<std::string> const & payload) {
}

void HttpBidderInterface::sendPingMessage(std::string const & agent,
                                          int ping) {
}

void HttpBidderInterface::send(std::shared_ptr<PostAuctionEvent> const & event) {
}

bool HttpBidderInterface::prepareRequest(OpenRTB::BidRequest &request,
                                         const RTBKIT::BidRequest &originalRequest,
                                         const std::map<std::string, BidInfo> &bidders) const {
    tagRequest(request, bidders);

    // We update the tmax value before sending the BidRequest to substract our processing time
    double processingTimeMs = originalRequest.timestamp.secondsUntil(Date::now()) * 1000;
    int oldTmax = request.tmax.value();
    int newTmax = oldTmax - static_cast<int>(std::round(processingTimeMs));
    if (newTmax <= 0) {
        return false;
    }
#if 0
    std::cerr << "old tmax = " << oldTmax << std::endl
              << "new tmax = " << newTmax << std::endl;
#endif
    ExcCheck(newTmax <= oldTmax, "Wrong tmax calculation");
    request.tmax.val = newTmax;
    return true;
}

void HttpBidderInterface::submitBids(const std::string &agent, Id auctionId,
                                     const Bids &bids, WinCostModel wcm)
{
     Json::FastWriter writer;
     std::vector<std::string> message { agent, "BID" };
     message.push_back(auctionId.toString());
     std::string bidsStr = writer.write(bids.toJson());
     std::string wcmStr = writer.write(wcm.toJson());
     message.push_back(std::move(bidsStr));
     message.push_back(std::move(wcmStr));

     router->doBid(message);
}

//
// factory
//

namespace {

struct AtInit {
    AtInit()
    {
        BidderInterface::registerFactory("http", [](std::string const & name , std::shared_ptr<ServiceProxies> const & proxies, Json::Value const & json) {
            return new HttpBidderInterface(name, proxies, json);
        });
    }
} atInit;

}

<commit_msg>Used the generic indexOf function to retrieve the creative and adSpot indexes<commit_after>/* http_bidder_interface.cc
   Eric Robert, 2 April 2014
   Copyright (c) 2011 Datacratic.  All rights reserved.
*/

#include "http_bidder_interface.h"
#include "jml/db/persistent.h"
#include "soa/service/http_client.h"
#include "soa/utils/generic_utils.h"
#include "rtbkit/common/messages.h"
#include "rtbkit/plugins/bid_request/openrtb_bid_request.h"
#include "rtbkit/openrtb/openrtb_parsing.h"
#include "rtbkit/core/router/router.h"

using namespace Datacratic;
using namespace RTBKIT;

namespace {
    DefaultDescription<OpenRTB::BidRequest> desc;

    void tagRequest(OpenRTB::BidRequest &request,
                    const std::map<std::string, BidInfo> &bidders)
    {

        for (const auto &bidder: bidders) {
            const auto &agentConfig = bidder.second.agentConfig;
            const auto &spots = bidder.second.imp;
            const auto &creatives = agentConfig->creatives;

            Json::Value creativesValue(Json::arrayValue);
            for (const auto &spot: spots) {
                const int adSpotIndex = spot.first;
                ExcCheck(adSpotIndex >= 0 && adSpotIndex < request.imp.size(),
                         "adSpotIndex out of range");
                auto &imp = request.imp[adSpotIndex];
                auto &ext = imp.ext;
                for (int creativeIndex: spot.second) {
                    ExcCheck(creativeIndex >= 0 && creativeIndex < creatives.size(),
                             "creativeIndex out of range");
                    const int creativeId = creatives[creativeIndex].id;
                    creativesValue.append(creativeId);
                }

                ext["allowed_ids"][std::to_string(agentConfig->externalId)] =
                    std::move(creativesValue);

            }

        }

    }
}

HttpBidderInterface::HttpBidderInterface(std::string name,
                                         std::shared_ptr<ServiceProxies> proxies,
                                         Json::Value const & json) {
    host = json["host"].asString();
    path = json["path"].asString();
    httpClient.reset(new HttpClient(host));
    loop.addSource("HttpBidderInterface::httpClient", httpClient);
}

void HttpBidderInterface::sendAuctionMessage(std::shared_ptr<Auction> const & auction,
                                             double timeLeftMs,
                                             std::map<std::string, BidInfo> const & bidders) {
    using namespace std;
    for(auto & item : bidders) {
        auto & agent = item.first;
        auto & info = router->agents[agent];
        const auto &config = info.config;
        BidRequest originalRequest = *auction->request;
        WinCostModel wcm = auction->exchangeConnector->getWinCostModel(*auction, *info.config);

        OpenRTB::BidRequest openRtbRequest = toOpenRtb(originalRequest);
        bool ok = prepareRequest(openRtbRequest, originalRequest, bidders);
        /* If we took too much time processing the request, then we don't send it.
           Instead, we're making null bids for each impression
        */
        if (!ok) {
            Bids bids;
            for_each(begin(openRtbRequest.imp), end(openRtbRequest.imp),
                     [&](const OpenRTB::Impression &imp) {
                Bid theBid;
                theBid.price = USD_CPM(0);
                bids.push_back(move(theBid));
            });
            submitBids(agent, auction->id, bids, wcm);
            return;
        }
        StructuredJsonPrintingContext context;
        desc.printJson(&openRtbRequest, context);
        auto requestStr = context.output.toString();

        /* We need to capture by copy inside the lambda otherwise we might get
           a dangling reference if we go out of scope before receiving the http response
        */
        auto callbacks = std::make_shared<HttpClientSimpleCallbacks>(
                [=](const HttpRequest &, HttpClientError errorCode,
                    int, const std::string &, const std::string &body)
                {
                    if (errorCode != HttpClientError::NONE) {
                        auto toErrorString = [](HttpClientError code) -> std::string {
                            switch (code) {
                                #define CASE(code) \
                                    case code: \
                                        return #code;
                                CASE(HttpClientError::NONE)
                                CASE(HttpClientError::UNKNOWN)
                                CASE(HttpClientError::TIMEOUT)
                                CASE(HttpClientError::HOST_NOT_FOUND)
                                CASE(HttpClientError::COULD_NOT_CONNECT)
                                #undef CASE
                            }
                            ExcCheck(false, "Invalid code path");
                            return "";
                        };
                        cerr << "Error requesting " << host
                                  << ": " << toErrorString(errorCode);
                      }
                      else {
                        // cerr << "Response: " << body << endl;
                         OpenRTB::BidResponse response;
                         ML::Parse_Context context("payload",
                               body.c_str(), body.size());
                         StreamingJsonParsingContext jsonContext(context);
                         static DefaultDescription<OpenRTB::BidResponse> respDesc;
                         respDesc.parseJson(&response, jsonContext);

                         for (const auto &seatbid: response.seatbid) {
                             Bids bids;

                             for (const auto &bid: seatbid.bid) {
                                 Bid theBid;

                                 int crid = bid.crid.toInt();
                                 int creativeIndex = indexOf(config->creatives,
                                     &Creative::id, crid);

                                 if (creativeIndex == -1) {
                                     throw ML::Exception(ML::format(
                                        "Unknown creative id: %d", crid));
                                 }

                                 theBid.creativeIndex = creativeIndex;
                                 theBid.price = USD_CPM(bid.price.val);
                                 theBid.priority = 0.0;

                                 int spotIndex = indexOf(openRtbRequest.imp,
                                                        &OpenRTB::Impression::id, bid.impid);
                                 if (spotIndex == -1) {
                                     throw ML::Exception(ML::format(
                                         "Unknown impression id: %s", bid.impid.toString()));
                                 }

                                 theBid.spotIndex = spotIndex;

                                 bids.push_back(std::move(theBid));
                             }
                             submitBids(agent, auction->id, bids, wcm);
                         }
                     }
                }
        );

        HttpRequest::Content reqContent { requestStr, "application/json" };
        RestParams headers { { "x-openrtb-version", "2.1" } };
       // std::cerr << "Sending HTTP POST to: " << host << " " << path << std::endl;
       // std::cerr << "Content " << reqContent.str << std::endl;

        httpClient->post(path, callbacks, reqContent,
                         { } /* queryParams */, headers);
    }
}

void HttpBidderInterface::sendWinMessage(std::string const & agent,
                                         std::string const & id,
                                         Amount price) {
}

void HttpBidderInterface::sendWinMessage(std::string const & agent,
                                         Amount price,
                                         FinishedInfo const & event) {
}

void HttpBidderInterface::sendLateWinMessage(std::string const & agent,
                                             Amount price,
                                             FinishedInfo const & event) {
}

void HttpBidderInterface::sendLossMessage(std::string const & agent,
                                          std::string const & id) {
}

void HttpBidderInterface::sendLossMessage(std::string const & agent,
                                          FinishedInfo const & event) {
}

void HttpBidderInterface::sendCampaignEventMessage(std::string const & agent,
                                                   std::string const & label,
                                                   FinishedInfo const & event) {
}

void HttpBidderInterface::sendBidLostMessage(std::string const & agent,
                                             std::shared_ptr<Auction> const & auction) {
}

void HttpBidderInterface::sendBidDroppedMessage(std::string const & agent,
                                                std::shared_ptr<Auction> const & auction) {
}

void HttpBidderInterface::sendBidInvalidMessage(std::string const & agent,
                                                std::string const & reason,
                                                std::shared_ptr<Auction> const & auction) {
}

void HttpBidderInterface::sendNoBudgetMessage(std::string const & agent,
                                              std::shared_ptr<Auction> const & auction) {
}

void HttpBidderInterface::sendTooLateMessage(std::string const & agent,
                                             std::shared_ptr<Auction> const & auction) {
}

void HttpBidderInterface::sendMessage(std::string const & agent,
                                      std::string const & message) {
}

void HttpBidderInterface::sendErrorMessage(std::string const & agent,
                                           std::string const & error,
                                           std::vector<std::string> const & payload) {
}

void HttpBidderInterface::sendPingMessage(std::string const & agent,
                                          int ping) {
}

void HttpBidderInterface::send(std::shared_ptr<PostAuctionEvent> const & event) {
}

bool HttpBidderInterface::prepareRequest(OpenRTB::BidRequest &request,
                                         const RTBKIT::BidRequest &originalRequest,
                                         const std::map<std::string, BidInfo> &bidders) const {
    tagRequest(request, bidders);

    // We update the tmax value before sending the BidRequest to substract our processing time
    double processingTimeMs = originalRequest.timestamp.secondsUntil(Date::now()) * 1000;
    int oldTmax = request.tmax.value();
    int newTmax = oldTmax - static_cast<int>(std::round(processingTimeMs));
    if (newTmax <= 0) {
        return false;
    }
#if 0
    std::cerr << "old tmax = " << oldTmax << std::endl
              << "new tmax = " << newTmax << std::endl;
#endif
    ExcCheck(newTmax <= oldTmax, "Wrong tmax calculation");
    request.tmax.val = newTmax;
    return true;
}

void HttpBidderInterface::submitBids(const std::string &agent, Id auctionId,
                                     const Bids &bids, WinCostModel wcm)
{
     Json::FastWriter writer;
     std::vector<std::string> message { agent, "BID" };
     message.push_back(auctionId.toString());
     std::string bidsStr = writer.write(bids.toJson());
     std::string wcmStr = writer.write(wcm.toJson());
     message.push_back(std::move(bidsStr));
     message.push_back(std::move(wcmStr));

     router->doBid(message);
}

//
// factory
//

namespace {

struct AtInit {
    AtInit()
    {
        BidderInterface::registerFactory("http", [](std::string const & name , std::shared_ptr<ServiceProxies> const & proxies, Json::Value const & json) {
            return new HttpBidderInterface(name, proxies, json);
        });
    }
} atInit;

}

<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdlib.h>
#include "field_descriptor.hpp"

int myrank, nprocs;

int main(int argc, char *argv[])
{
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);

    int n[3];
    field_descriptor *f0r, *f0c;
    field_descriptor *f1r, *f1c;

    if (argc != 4)
    {
        MPI_Finalize();
        printf("wrong number of parameters.\n");
        return EXIT_SUCCESS;
    }

    n[0] = atoi(argv[1]);
    n[1] = atoi(argv[2]);
    n[2] = atoi(argv[3]);
    f0c = new field_descriptor(3, n, MPI_COMPLEX8);
    n[0] = f0c->sizes[0];
    n[1] = f0c->sizes[1];
    n[2] = 2*(f0c->sizes[2]-1);
    f0r = new field_descriptor(3, n, MPI_REAL4);

    n[0] = 2*atoi(argv[1]);
    n[1] = 2*atoi(argv[2]);
    n[2] = 2*atoi(argv[3]);
    f1c = new field_descriptor(3, n, MPI_COMPLEX8);
    n[0] = f1c->sizes[0];
    n[1] = f1c->sizes[1];
    n[2] = 2*(f1c->sizes[2]-1);
    f1r = new field_descriptor(3, n, MPI_REAL4);

    fftwf_complex *a0, *a1c;
    float *a1r;
    a0 = fftwf_alloc_complex(f0c->local_size);
    a1c = fftwf_alloc_complex(f1c->local_size);
    a1r = fftwf_alloc_real(2*f1c->local_size);

    f0c->read("data0c", (void*)a0);

    fftwf_plan c2r = fftwf_mpi_plan_dft_c2r_3d(
            f0r->sizes[0], f0r->sizes[1], f0r->sizes[2],
            a0, a1r,
            MPI_COMM_WORLD,
            FFTW_ESTIMATE);
    fftwf_execute(c2r);
    fftwf_destroy_plan(c2r);
    fftwf_clip_zero_padding(f0r, a1r);
    f0r->write("data0r", (void*)a1r);

    fftwf_copy_complex_array(
            f0c, a0,
            f1c, a1c);

    c2r = fftwf_mpi_plan_dft_c2r_3d(
            f1r->sizes[0], f1r->sizes[1], f1r->sizes[2],
            a1c, a1r,
            MPI_COMM_WORLD,
            FFTW_ESTIMATE);
    fftwf_execute(c2r);
    fftwf_destroy_plan(c2r);

    fftwf_clip_zero_padding(f1r, a1r);
    f1r->write("data1r", (void*)a1r);
    fftw_free(a0);
    fftw_free(a1c);
    fftw_free(a1r);

    delete f0r;
    delete f0c;
    delete f1r;
    delete f1c;
    MPI_Finalize();
    return EXIT_SUCCESS;
}

<commit_msg>add fftw mpi init and cleanup calls<commit_after>#include <stdio.h>
#include <stdlib.h>
#include "field_descriptor.hpp"

int myrank, nprocs;

int main(int argc, char *argv[])
{
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
    fftwf_mpi_init();

    int n[3];
    field_descriptor *f0r, *f0c;
    field_descriptor *f1r, *f1c;

    if (argc != 4)
    {
        MPI_Finalize();
        printf("wrong number of parameters.\n");
        return EXIT_SUCCESS;
    }

    n[0] = atoi(argv[1]);
    n[1] = atoi(argv[2]);
    n[2] = atoi(argv[3]);
    f0c = new field_descriptor(3, n, MPI_COMPLEX8);
    n[0] = f0c->sizes[0];
    n[1] = f0c->sizes[1];
    n[2] = 2*(f0c->sizes[2]-1);
    f0r = new field_descriptor(3, n, MPI_REAL4);

    n[0] = 2*atoi(argv[1]);
    n[1] = 2*atoi(argv[2]);
    n[2] = 2*atoi(argv[3]);
    f1c = new field_descriptor(3, n, MPI_COMPLEX8);
    n[0] = f1c->sizes[0];
    n[1] = f1c->sizes[1];
    n[2] = 2*(f1c->sizes[2]-1);
    f1r = new field_descriptor(3, n, MPI_REAL4);

    fftwf_complex *a0, *a1c;
    float *a1r;
    a0 = fftwf_alloc_complex(f0c->local_size);
    a1c = fftwf_alloc_complex(f1c->local_size);
    a1r = fftwf_alloc_real(2*f1c->local_size);

    f0c->read("data0c", (void*)a0);

    fftwf_plan c2r = fftwf_mpi_plan_dft_c2r_3d(
            f0r->sizes[0], f0r->sizes[1], f0r->sizes[2],
            a0, a1r,
            MPI_COMM_WORLD,
            FFTW_ESTIMATE);
    fftwf_execute(c2r);
    fftwf_destroy_plan(c2r);
    fftwf_clip_zero_padding(f0r, a1r);
    f0r->write("data0r", (void*)a1r);

    fftwf_copy_complex_array(
            f0c, a0,
            f1c, a1c);

    c2r = fftwf_mpi_plan_dft_c2r_3d(
            f1r->sizes[0], f1r->sizes[1], f1r->sizes[2],
            a1c, a1r,
            MPI_COMM_WORLD,
            FFTW_ESTIMATE);
    fftwf_execute(c2r);
    fftwf_destroy_plan(c2r);

    fftwf_clip_zero_padding(f1r, a1r);
    f1r->write("data1r", (void*)a1r);
    fftw_free(a0);
    fftw_free(a1c);
    fftw_free(a1r);
    fftwf_mpi_cleanup();

    delete f0r;
    delete f0c;
    delete f1r;
    delete f1c;
    MPI_Finalize();
    return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>#ifndef DUNE_STUFF_COMMON_PARAMETER_TREE_HH
#define DUNE_STUFF_COMMON_PARAMETER_TREE_HH

#ifdef HAVE_CMAKE_CONFIG
 #include "cmake_config.h"
#else
 #include "config.h"
#endif // ifdef HAVE_CMAKE_CONFIG

// system
#include <sstream>
#include <boost/algorithm/string/join.hpp>
#include <boost/format.hpp>

// dune-common
#include <dune/common/exceptions.hh>
#include <dune/common/parametertreeparser.hh>
#include <dune/stuff/common/string.hh>

namespace Dune {
namespace Stuff {
namespace Common {

//! ParameterTree extension for nicer output
//! \todo This should go into dune-common.
class ExtendedParameterTree
  : public Dune::ParameterTree {
public:
  typedef Dune::ParameterTree BaseType;

  ExtendedParameterTree()
  {}

  ExtendedParameterTree(int argc, char** argv, std::string filename)
    : BaseType(init(argc, argv, filename))
  {}

  ExtendedParameterTree(const Dune::ParameterTree& other)
    : BaseType(other)
  {}

  ExtendedParameterTree& operator=(const Dune::ParameterTree& other)
  {
    if (this != &other) {
      Dune::ParameterTree::operator=(other);
    }
    return *this;
  }

  static void assertSub(const Dune::ParameterTree& paramTree, std::string sub, std::string id = "")
  {
    if (!paramTree.hasSub(sub)) {
      std::stringstream msg;
      msg << "Error";
      if (id != "") {
        msg << " in " << id;
      }
      msg << ": subTree '" << sub << "' not found in the following Dune::Parametertree" << std::endl;
      paramTree.report(msg);
      DUNE_THROW(Dune::InvalidStateException, msg.str());
    }
  } // static void assertSub(...)

  void assertSub(const std::string subTree, const std::string id = "") const
  {
    assertSub(*this, subTree, id);
  }

  static void assertKey(const Dune::ParameterTree& paramTree, const std::string key, const std::string id = "")
  {
    if (!paramTree.hasKey(key)) {
      std::stringstream msg;
      msg << "Error";
      if (id != "") {
        msg << " in " << id;
      }
      msg << ": key '" << key << "' not found in the following Dune::Parametertree" << std::endl;
      paramTree.report(msg);
      DUNE_THROW(Dune::InvalidStateException, msg.str());
    }
  } // static void assertKey(...)

  void assertKey(const std::string key, const std::string id = "") const
  {
    assertKey(*this, key, id);
  }

  void report(std::ostream& stream = std::cout,
              const std::string& prefix = "") const
  {
    for(auto pair : values)
          stream << pair.first << " = \"" << pair.second << "\"" << std::endl;

    for(auto pair : subs)
    {
      ExtendedParameterTree subTree(pair.second);
      if (subTree.getValueKeys().size())
        stream << "[ " << prefix + pair.first << " ]" << std::endl;
      subTree.report(stream, prefix + pair.first + ".");
    }
  }

  /**
    \brief      Fills a Dune::ParameterTree given a parameter file or command line arguments.
    \param[in]  argc
                From \c main()
    \param[in]  argv
                From \c main()
    \param[out] paramTree
                The Dune::ParameterTree that is to be filled.
    **/
  static ExtendedParameterTree init(int argc, char** argv, std::string filename)
  {
    ExtendedParameterTree paramTree;
    if (argc == 1) {
      Dune::ParameterTreeParser::readINITree(filename, paramTree);
    } else if (argc == 2) {
      Dune::ParameterTreeParser::readINITree(argv[1], paramTree);
    } else {
      Dune::ParameterTreeParser::readOptions(argc, argv, paramTree);
    }
    if (paramTree.hasKey("paramfile")) {
      Dune::ParameterTreeParser::readINITree(paramTree.get< std::string >("paramfile"), paramTree, false);
    }
    return paramTree;
  } // static ExtendedParameterTree init(...)
};

} // namespace Common
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_COMMON_PARAMETER_TREE_HH
<commit_msg>[commo.parameter.tree] added {assert,has,get}Vector()<commit_after>#ifndef DUNE_STUFF_COMMON_PARAMETER_TREE_HH
#define DUNE_STUFF_COMMON_PARAMETER_TREE_HH

#ifdef HAVE_CMAKE_CONFIG
 #include "cmake_config.h"
#else
 #include "config.h"
#endif // ifdef HAVE_CMAKE_CONFIG

// system
#include <cstring>
#include <sstream>
#include <vector>

// boost
#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/format.hpp>

// dune-common
#include <dune/common/exceptions.hh>
#include <dune/common/parametertreeparser.hh>

// dune-stuff
#include <dune/stuff/common/string.hh>

namespace Dune {
namespace Stuff {
namespace Common {

//! ParameterTree extension for nicer output
//! \todo This should go into dune-common.
class ExtendedParameterTree
  : public Dune::ParameterTree {
public:
  typedef Dune::ParameterTree BaseType;

  ExtendedParameterTree()
  {}

  ExtendedParameterTree(int argc, char** argv, std::string filename)
    : BaseType(init(argc, argv, filename))
  {}

  ExtendedParameterTree(const Dune::ParameterTree& other)
    : BaseType(other)
  {}

  ExtendedParameterTree& operator=(const Dune::ParameterTree& other)
  {
    if (this != &other) {
      Dune::ParameterTree::operator=(other);
    }
    return *this;
  }

  static void assertSub(const Dune::ParameterTree& paramTree, std::string sub, std::string id = "")
  {
    if (!paramTree.hasSub(sub)) {
      std::stringstream msg;
      msg << "Error";
      if (id != "") {
        msg << " in " << id;
      }
      msg << ": subTree '" << sub << "' not found in the following Dune::Parametertree" << std::endl;
      ExtendedParameterTree(paramTree).report(msg);
      DUNE_THROW(Dune::InvalidStateException, msg.str());
    }
  } // static void assertSub(...)

  void assertSub(const std::string subTree, const std::string id = "") const
  {
    assertSub(*this, subTree, id);
  }

  static void assertKey(const Dune::ParameterTree& paramTree, const std::string key, const std::string id = "")
  {
    if (!paramTree.hasKey(key)) {
      std::stringstream msg;
      msg << "Error";
      if (id != "") {
        msg << " in " << id;
      }
      msg << ": key '" << key << "' not found in the following Dune::Parametertree" << std::endl;
      ExtendedParameterTree(paramTree).report(msg);
      DUNE_THROW(Dune::InvalidStateException, msg.str());
    }
  } // static void assertKey(...)

  void assertKey(const std::string key, const std::string id = "") const
  {
    assertKey(*this, key, id);
  }

  void report(std::ostream& stream = std::cout, const std::string& prefix = "") const
  {
    for(auto pair : values)
          stream << pair.first << " = \"" << pair.second << "\"" << std::endl;

    for(auto pair : subs)
    {
      ExtendedParameterTree subTree(pair.second);
      if (subTree.getValueKeys().size())
        stream << "[ " << prefix + pair.first << " ]" << std::endl;
      subTree.report(stream, prefix + pair.first + ".");
    }
  }

  bool hasVector(const std::string& vector) const
  {
    if (hasKey(vector)) {
      const std::string str = get< std::string >(vector, "default_value");
      if (Dune::Stuff::Common::String::equal(str.substr(0, 1), "[")
          && Dune::Stuff::Common::String::equal(str.substr(str.size() - 1, 1), "]"))
        return true;
    }
    return false;
  } // bool hasVector(const std::string& vector) const

  void assertVector(const std::string vector, const std::string id = "") const
  {
    if (!hasVector(vector)) {
      std::stringstream msg;
      msg << "Error";
      if (id != "") {
        msg << " in " << id;
      }
      msg << ": vector '" << vector << "' not found in the following Dune::Parametertree" << std::endl;
      report(msg);
      DUNE_THROW(Dune::InvalidStateException, msg.str());
    }
  } // void assertVector(...)

  template< class T >
  std::vector< T > getVector(const std::string& key, const T def) const
  {
    std::vector< T > ret;
    if (!hasKey(key))
      ret.push_back(def);
    else {
      const std::string str = get< std::string >(key, "default_value");
      // the dune parametertree strips any leading and trailing whitespace
      // so we can be sure that the first and last have to be the brackets []
      assert(Dune::Stuff::Common::String::equal(str.substr(0, 1), "[")
             && "Vectors have to be of the form '[entry_0; entry_1; ... ]'!");
      assert(Dune::Stuff::Common::String::equal(str.substr(str.size() - 1, 1), "]")
             && "Vectors have to be of the form '[entry_0; entry_1; ... ]'!");
      const std::vector< std::string > tokens = Dune::Stuff::Common::tokenize< std::string >(str.substr(1, str.size() - 2), ";");
      for (unsigned int i = 0; i < tokens.size(); ++i)
        ret.push_back(Dune::Stuff::Common::fromString< T >(boost::algorithm::trim_copy(tokens[i])));
    }
    return ret;
  } // std::vector< T > getVector(const std::string& key, const T def) const

  /**
    \brief      Fills a Dune::ParameterTree given a parameter file or command line arguments.
    \param[in]  argc
                From \c main()
    \param[in]  argv
                From \c main()
    \param[out] paramTree
                The Dune::ParameterTree that is to be filled.
    **/
  static ExtendedParameterTree init(int argc, char** argv, std::string filename)
  {
    Dune::ParameterTree paramTree;
    if (argc == 1) {
      Dune::ParameterTreeParser::readINITree(filename, paramTree);
    } else if (argc == 2) {
      Dune::ParameterTreeParser::readINITree(argv[1], paramTree);
    } else {
      Dune::ParameterTreeParser::readOptions(argc, argv, paramTree);
    }
    if (paramTree.hasKey("paramfile")) {
      Dune::ParameterTreeParser::readINITree(paramTree.get< std::string >("paramfile"), paramTree, false);
    }
    return paramTree;
  } // static ExtendedParameterTree init(...)
};

} // namespace Common
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_COMMON_PARAMETER_TREE_HH
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: pagedata.cxx,v $
 *
 *  $Revision: 1.1.1.1 $
 *
 *  last change: $Author: hr $ $Date: 2000-09-18 16:44:55 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifdef PCH
#include "ui_pch.hxx"
#endif

#include <string.h>

#ifndef _DEBUG_HXX //autogen
#include <tools/debug.hxx>
#endif

#pragma hdrstop

#ifndef PCH
#include "segmentc.hxx"
#endif

#include "pagedata.hxx"

//============================================================================

ScPrintRangeData::ScPrintRangeData()
{
    nPagesX = nPagesY = 0;
    pPageEndX = pPageEndY = NULL;
    bTopDown = bAutomatic = TRUE;
    nFirstPage = 1;
}

ScPrintRangeData::~ScPrintRangeData()
{
    delete[] pPageEndX;
    delete[] pPageEndY;
}

void ScPrintRangeData::SetPagesX( USHORT nCount, const USHORT* pData )
{
    delete[] pPageEndX;
    if ( nCount )
    {
        pPageEndX = new USHORT[nCount];
        memcpy( pPageEndX, pData, nCount * sizeof(USHORT) );
    }
    else
        pPageEndX = NULL;
    nPagesX = nCount;
}

void ScPrintRangeData::SetPagesY( USHORT nCount, const USHORT* pData )
{
    delete[] pPageEndY;
    if ( nCount )
    {
        pPageEndY = new USHORT[nCount];
        memcpy( pPageEndY, pData, nCount * sizeof(USHORT) );
    }
    else
        pPageEndY = NULL;
    nPagesY = nCount;
}

//============================================================================

ScPageBreakData::ScPageBreakData(USHORT nMax)
{
    nUsed = 0;
    if (nMax)
        pData = new ScPrintRangeData[nMax];
    else
        pData = NULL;
    nAlloc = nMax;
}

ScPageBreakData::~ScPageBreakData()
{
    delete[] pData;
}

ScPrintRangeData& ScPageBreakData::GetData(USHORT nPos)
{
    DBG_ASSERT(nPos < nAlloc, "ScPageBreakData::GetData bumm");

    if ( nPos >= nUsed )
    {
        DBG_ASSERT(nPos == nUsed, "ScPageBreakData::GetData falsche Reihenfolge");
        nUsed = nPos+1;
    }

    return pData[nPos];
}

BOOL ScPageBreakData::IsEqual( const ScPageBreakData& rOther ) const
{
    if ( nUsed != rOther.nUsed )
        return FALSE;

    for (USHORT i=0; i<nUsed; i++)
        if ( pData[i].GetPrintRange() != rOther.pData[i].GetPrintRange() )
            return FALSE;

    //! ScPrintRangeData komplett vergleichen ??

    return TRUE;
}

void ScPageBreakData::AddPages()
{
    if ( nUsed > 1 )
    {
        long nPage = pData[0].GetFirstPage();
        for (USHORT i=0; i+1<nUsed; i++)
        {
            nPage += ((long)pData[i].GetPagesX())*pData[i].GetPagesY();
            pData[i+1].SetFirstPage( nPage );
        }
    }
}

<commit_msg>del: segmentc.hxx<commit_after>/*************************************************************************
 *
 *  $RCSfile: pagedata.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: mh $ $Date: 2001-10-23 08:42:02 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifdef PCH
#include "ui_pch.hxx"
#endif

#include <string.h>

#ifndef _DEBUG_HXX //autogen
#include <tools/debug.hxx>
#endif

#pragma hdrstop

#include "pagedata.hxx"

//============================================================================

ScPrintRangeData::ScPrintRangeData()
{
    nPagesX = nPagesY = 0;
    pPageEndX = pPageEndY = NULL;
    bTopDown = bAutomatic = TRUE;
    nFirstPage = 1;
}

ScPrintRangeData::~ScPrintRangeData()
{
    delete[] pPageEndX;
    delete[] pPageEndY;
}

void ScPrintRangeData::SetPagesX( USHORT nCount, const USHORT* pData )
{
    delete[] pPageEndX;
    if ( nCount )
    {
        pPageEndX = new USHORT[nCount];
        memcpy( pPageEndX, pData, nCount * sizeof(USHORT) );
    }
    else
        pPageEndX = NULL;
    nPagesX = nCount;
}

void ScPrintRangeData::SetPagesY( USHORT nCount, const USHORT* pData )
{
    delete[] pPageEndY;
    if ( nCount )
    {
        pPageEndY = new USHORT[nCount];
        memcpy( pPageEndY, pData, nCount * sizeof(USHORT) );
    }
    else
        pPageEndY = NULL;
    nPagesY = nCount;
}

//============================================================================

ScPageBreakData::ScPageBreakData(USHORT nMax)
{
    nUsed = 0;
    if (nMax)
        pData = new ScPrintRangeData[nMax];
    else
        pData = NULL;
    nAlloc = nMax;
}

ScPageBreakData::~ScPageBreakData()
{
    delete[] pData;
}

ScPrintRangeData& ScPageBreakData::GetData(USHORT nPos)
{
    DBG_ASSERT(nPos < nAlloc, "ScPageBreakData::GetData bumm");

    if ( nPos >= nUsed )
    {
        DBG_ASSERT(nPos == nUsed, "ScPageBreakData::GetData falsche Reihenfolge");
        nUsed = nPos+1;
    }

    return pData[nPos];
}

BOOL ScPageBreakData::IsEqual( const ScPageBreakData& rOther ) const
{
    if ( nUsed != rOther.nUsed )
        return FALSE;

    for (USHORT i=0; i<nUsed; i++)
        if ( pData[i].GetPrintRange() != rOther.pData[i].GetPrintRange() )
            return FALSE;

    //! ScPrintRangeData komplett vergleichen ??

    return TRUE;
}

void ScPageBreakData::AddPages()
{
    if ( nUsed > 1 )
    {
        long nPage = pData[0].GetFirstPage();
        for (USHORT i=0; i+1<nUsed; i++)
        {
            nPage += ((long)pData[i].GetPagesX())*pData[i].GetPagesY();
            pData[i+1].SetFirstPage( nPage );
        }
    }
}

<|endoftext|>