<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "formulagroup.hxx"
#include "document.hxx"
#include "formulacell.hxx"
#include "tokenarray.hxx"
#include "compiler.hxx"
#include "interpre.hxx"
#include "scmatrix.hxx"

#include "formula/vectortoken.hxx"
#include "rtl/bootstrap.hxx"
#include "config_features.h"

#include <vector>
#include <boost/unordered_map.hpp>

#define USE_DUMMY_INTERPRETER 0

#if USE_DUMMY_INTERPRETER
#include <cstdio>
#endif

#ifdef DISABLE_DYNLOADING

extern sc::FormulaGroupInterpreter* SAL_CALL createFormulaGroupOpenCLInterpreter();

#endif

namespace sc {

rtl_uString* FormulaGroupContext::intern( const OUString& rStr )
{
    StrHashType::iterator it = maStrPool.find(rStr);
    if (it == maStrPool.end())
    {
        // Not yet in the pool.
        std::pair<StrHashType::iterator, bool> r = maStrPool.insert(rStr.intern());
        if (!r.second)
            // Insertion failed.
            return NULL;

        it = r.first;
    }

    return it->pData;
}

namespace {

/**
 * Input double array consists of segments of NaN's and normal values.
 * Insert only the normal values into the matrix while skipping the NaN's.
 */
void fillMatrix( ScMatrix& rMat, size_t nCol, const double* pNums, size_t nLen )
{
    const double* p = pNums;
    const double* pEnd = p + nLen;
    const double* pHead = NULL;
    for (; p != pEnd; ++p)
    {
        if (!rtl::math::isNan(*p))
        {
            if (!pHead)
                // Store the first non-NaN position.
                pHead = p;

            continue;
        }

        if (pHead)
        {
            // Flush this non-NaN segment to the matrix.
            rMat.PutDouble(pHead, p - pHead, nCol, pHead - pNums);
            pHead = NULL;
        }
    }

    if (pHead)
    {
        // Flush last non-NaN segment to the matrix.
        rMat.PutDouble(pHead, p - pHead, nCol, pHead - pNums);
    }
}

void flushSegment(
    ScMatrix& rMat, size_t nCol, rtl_uString** pHead, rtl_uString** pCur, rtl_uString** pTop )
{
    size_t nOffset = pHead - pTop;
    std::vector<OUString> aStrs;
    aStrs.reserve(pCur - pHead);
    for (; pHead != pCur; ++pHead)
        aStrs.push_back(OUString(*pHead));

    rMat.PutString(&aStrs[0], aStrs.size(), nCol, nOffset);
}

void fillMatrix( ScMatrix& rMat, size_t nCol, rtl_uString** pStrs, size_t nLen )
{
    rtl_uString** p = pStrs;
    rtl_uString** pEnd = p + nLen;
    rtl_uString** pHead = NULL;
    for (; p != pEnd; ++p)
    {
        if (*p)
        {
            if (!pHead)
                // Store the first non-empty string position.
                pHead = p;

            continue;
        }

        if (pHead)
        {
            // Flush this non-empty segment to the matrix.
            flushSegment(rMat, nCol, pHead, p, pStrs);
            pHead = NULL;
        }
    }

    if (pHead)
    {
        // Flush last non-empty segment to the matrix.
        flushSegment(rMat, nCol, pHead, p, pStrs);
    }
}

}

FormulaGroupInterpreterSoftware::FormulaGroupInterpreterSoftware() : FormulaGroupInterpreter()
{
}

ScMatrixRef FormulaGroupInterpreterSoftware::inverseMatrix(const ScMatrix& /*rMat*/)
{
    return ScMatrixRef();
}

bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddress& rTopPos,
                                                const ScFormulaCellGroupRef& xGroup,
                                                ScTokenArray& rCode)
{
    typedef boost::unordered_map<const formula::FormulaToken*, formula::FormulaTokenRef> CachedTokensType;

    // Decompose the group into individual cells and calculate them individually.

    // The caller must ensure that the top position is the start position of
    // the group.

    ScAddress aTmpPos = rTopPos;
    std::vector<double> aResults;
    aResults.reserve(xGroup->mnLength);
    CachedTokensType aCachedTokens;

    double fNan;
    rtl::math::setNan(&fNan);

    for (SCROW i = 0; i < xGroup->mnLength; ++i, aTmpPos.IncRow())
    {
        ScTokenArray aCode2;
        for (const formula::FormulaToken* p = rCode.First(); p; p = rCode.Next())
        {
            CachedTokensType::iterator it = aCachedTokens.find(p);
            if (it != aCachedTokens.end())
            {
                // This token is cached. Use the cached one.
                aCode2.AddToken(*it->second);
                continue;
            }

            switch (p->GetType())
            {
                case formula::svSingleVectorRef:
                {
                    const formula::SingleVectorRefToken* p2 = static_cast<const formula::SingleVectorRefToken*>(p);
                    const formula::VectorRefArray& rArray = p2->GetArray();
                    if (rArray.mbNumeric)
                    {
                        double fVal = fNan;
                        if (static_cast<size_t>(i) < p2->GetArrayLength())
                            fVal = rArray.mpNumericArray[i];

                        if (rtl::math::isNan(fVal))
                            aCode2.AddToken(ScEmptyCellToken(false, false));
                        else
                            aCode2.AddDouble(fVal);
                    }
                    else
                    {
                        rtl_uString* pStr = NULL;
                        if (static_cast<size_t>(i) < p2->GetArrayLength())
                            pStr = rArray.mpStringArray[i];

                        if (pStr)
                            aCode2.AddString(OUString(pStr));
                    }
                }
                break;
                case formula::svDoubleVectorRef:
                {
                    const formula::DoubleVectorRefToken* p2 = static_cast<const formula::DoubleVectorRefToken*>(p);
                    const std::vector<formula::VectorRefArray>& rArrays = p2->GetArrays();
                    size_t nColSize = rArrays.size();
                    size_t nRowStart = p2->IsStartFixed() ? 0 : i;
                    size_t nRowEnd = p2->GetRefRowSize() - 1;
                    if (!p2->IsEndFixed())
                        nRowEnd += i;
                    size_t nRowSize = nRowEnd - nRowStart + 1;
                    ScMatrixRef pMat(new ScMatrix(nColSize, nRowSize));

                    size_t nDataRowEnd = p2->GetArrayLength() - 1;
                    if (nRowStart > nDataRowEnd)
                        // Referenced rows are all empty.
                        nRowSize = 0;
                    else if (nRowEnd > nDataRowEnd)
                        // Data array is shorter than the row size of the reference. Truncate it to the data.
                        nRowSize -= nRowEnd - nDataRowEnd;

                    for (size_t nCol = 0; nCol < nColSize; ++nCol)
                    {
                        const formula::VectorRefArray& rArray = rArrays[nCol];
                        if (rArray.mbNumeric)
                        {
                            const double* pNums = rArray.mpNumericArray;
                            pNums += nRowStart;
                            fillMatrix(*pMat, nCol, pNums, nRowSize);
                        }
                        else
                        {
                            rtl_uString** pStrs = rArray.mpStringArray;
                            pStrs += nRowStart;
                            fillMatrix(*pMat, nCol, pStrs, nRowSize);
                        }
                    }

                    if (p2->IsStartFixed() && p2->IsEndFixed())
                    {
                        // Cached the converted token for absolute range referene.
                        ScComplexRefData aRef;
                        ScRange aRefRange = rTopPos;
                        aRefRange.aEnd.SetRow(rTopPos.Row() + nRowEnd);
                        aRef.InitRange(aRefRange);
                        formula::FormulaTokenRef xTok(new ScMatrixRangeToken(pMat, aRef));
                        aCachedTokens.insert(CachedTokensType::value_type(p, xTok));
                        aCode2.AddToken(*xTok);
                    }
                    else
                    {
                        ScMatrixToken aTok(pMat);
                        aCode2.AddToken(aTok);
                    }
                }
                break;
                default:
                    aCode2.AddToken(*p);
            }
        }

        ScFormulaCell* pDest = rDoc.GetFormulaCell(aTmpPos);
        if (!pDest)
            return false;

        generateRPNCode(rDoc, aTmpPos, aCode2);
        ScInterpreter aInterpreter(pDest, &rDoc, aTmpPos, aCode2);
        aInterpreter.Interpret();
        aResults.push_back(aInterpreter.GetResultToken()->GetDouble());
    } // for loop end (xGroup->mnLength)

    if (!aResults.empty())
        rDoc.SetFormulaResults(rTopPos, &aResults[0], aResults.size());

    return true;
}

#if USE_DUMMY_INTERPRETER
class FormulaGroupInterpreterDummy : public FormulaGroupInterpreter
{
    enum Mode {
        WRITE_OUTPUT = 0
    };
    Mode meMode;
public:
    FormulaGroupInterpreterDummy()
    {
        const char *pValue = getenv("FORMULA_GROUP_DUMMY");
        meMode = static_cast<Mode>(OString(pValue, strlen(pValue)).toInt32());
        fprintf(stderr, "Using Dummy Formula Group interpreter mode %d\n", (int)meMode);
    }

    virtual ScMatrixRef inverseMatrix(const ScMatrix& /*rMat*/)
    {
        return ScMatrixRef();
    }

    virtual bool interpret(ScDocument& rDoc, const ScAddress& rTopPos,
                           const ScFormulaCellGroupRef& xGroup,
                           ScTokenArray& rCode)
    {
        (void)rCode;

        // Write simple data back into the sheet
        if (meMode == WRITE_OUTPUT)
        {
            double *pDoubles = new double[xGroup->mnLength];
            for (sal_Int32 i = 0; i < xGroup->mnLength; i++)
                pDoubles[i] = 42.0 + i;
            rDoc.SetFormulaResults(rTopPos, pDoubles, xGroup->mnLength);
            delete [] pDoubles;
        }
        return true;
    }
};

#endif

#ifndef DISABLE_DYNLOADING

class FormulaGroupInterpreterOpenCLMissing : public FormulaGroupInterpreter
{
public:
    FormulaGroupInterpreterOpenCLMissing() : FormulaGroupInterpreter() {}
    virtual ~FormulaGroupInterpreterOpenCLMissing() {}
    virtual ScMatrixRef inverseMatrix(const ScMatrix&) { return ScMatrixRef(); }
    virtual bool interpret(ScDocument&, const ScAddress&, const ScFormulaCellGroupRef&, ScTokenArray&) { return false; }
};

static void SAL_CALL thisModule() {}

typedef FormulaGroupInterpreter* (*__createFormulaGroupOpenCLInterpreter)(void);
typedef size_t (*__getOpenCLPlatformCount)(void);
typedef void (*__fillOpenCLInfo)(OpenclPlatformInfo*, size_t);
typedef bool (*__switchOpenClDevice)(const OUString*, bool);
typedef void (*__compileOpenCLKernels)(const OUString*);

#endif

FormulaGroupInterpreter *FormulaGroupInterpreter::msInstance = NULL;

osl::Module* getOpenCLModule()
{
    static osl::Module aModule;
    if (aModule.is())
        // Already loaded.
        return &aModule;

    OUString aLibName(SVLIBRARY("scopencl"));
    bool bLoaded = aModule.loadRelative(&thisModule, aLibName);
    if (!bLoaded)
        bLoaded = aModule.load(aLibName);

    return bLoaded ? &aModule : NULL;
}

/// load and/or configure the correct formula group interpreter
FormulaGroupInterpreter *FormulaGroupInterpreter::getStatic()
{
#if USE_DUMMY_INTERPRETER
    if (getenv("FORMULA_GROUP_DUMMY"))
    {
        delete msInstance;
        return msInstance = new sc::FormulaGroupInterpreterDummy();
    }
#endif

    if ( !msInstance )
    {
        switchOpenCLDevice(OUString(), ScInterpreter::GetGlobalConfig().mbOpenCLEnabled);
        if ( !msInstance ) // software fallback
        {
            fprintf(stderr, "Create S/W interp\n");
            msInstance = new sc::FormulaGroupInterpreterSoftware();
        }
    }

    return msInstance;
}

void FormulaGroupInterpreter::fillOpenCLInfo(std::vector<OpenclPlatformInfo>& rPlatforms)
{
    osl::Module* pModule = getOpenCLModule();
    if (!pModule)
        return;

    oslGenericFunction fn = pModule->getFunctionSymbol("getOpenCLPlatformCount");
    if (!fn)
        return;

    size_t nPlatforms = reinterpret_cast<__getOpenCLPlatformCount>(fn)();
    if (!nPlatforms)
        return;

    fn = pModule->getFunctionSymbol("fillOpenCLInfo");
    if (!fn)
        return;

    std::vector<OpenclPlatformInfo> aPlatforms(nPlatforms);
    reinterpret_cast<__fillOpenCLInfo>(fn)(&aPlatforms[0], aPlatforms.size());
    rPlatforms.swap(aPlatforms);
}

void FormulaGroupInterpreter::switchOpenCLDevice(const OUString& rDeviceId, bool bAutoSelect)
{
    bool bOpenCLEnabled = ScInterpreter::GetGlobalConfig().mbOpenCLEnabled;
    if(!bOpenCLEnabled || rDeviceId == "Software")
    {
        if(msInstance)
        {
            // if we already have a software interpreter don't delete it
            if(dynamic_cast<sc::FormulaGroupInterpreterSoftware*>(msInstance))
                return;

            delete msInstance;
        }

        msInstance = new sc::FormulaGroupInterpreterSoftware();
        return;
    }

    osl::Module* pModule = getOpenCLModule();
    if (!pModule)
        return;

    oslGenericFunction fn = pModule->getFunctionSymbol("switchOpenClDevice");
    if (!fn)
        return;

    bool bSuccess = reinterpret_cast<__switchOpenClDevice>(fn)(&rDeviceId, bAutoSelect);
    if(!bSuccess)
        return;

    delete msInstance;
    msInstance = NULL;

#if HAVE_FEATURE_OPENCL

    if ( ScInterpreter::GetGlobalConfig().mbOpenCLEnabled )
    {
#ifdef DISABLE_DYNLOADING
        msInstance = createFormulaGroupOpenCLInterpreter();
#else
        // Dynamically load scopencl shared object, and instantiate the opencl interpreter.
        fn = pModule->getFunctionSymbol("createFormulaGroupOpenCLInterpreter");
        if (fn)
            msInstance = reinterpret_cast<__createFormulaGroupOpenCLInterpreter>(fn)();

        if (!msInstance)
            msInstance = new sc::FormulaGroupInterpreterOpenCLMissing();
#endif
    }
#endif
}

void FormulaGroupInterpreter::compileOpenCLKernels()
{
    const ScCalcConfig& rConfig = ScInterpreter::GetGlobalConfig();
    if (!rConfig.mbOpenCLEnabled)
        // OpenCL is not enabled.
        return;

    osl::Module* pModule = getOpenCLModule();
    if (!pModule)
        return;

    oslGenericFunction fn = pModule->getFunctionSymbol("compileOpenCLKernels");
    if (!fn)
        return;

    reinterpret_cast<__compileOpenCLKernels>(fn)(&rConfig.maOpenCLDevice);
}

void FormulaGroupInterpreter::generateRPNCode(ScDocument& rDoc, const ScAddress& rPos, ScTokenArray& rCode)
{
    // First, generate an RPN (reverse polish notation) token array.
    ScCompiler aComp(&rDoc, rPos, rCode);
    aComp.SetGrammar(rDoc.GetGrammar());
    aComp.CompileTokenArray(); // Create RPN token array.
    // Now, calling FirstRPN() and NextRPN() will return tokens from the RPN token array.
}

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Try to fix the DISABLE_DYNLOADING case<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "formulagroup.hxx"
#include "document.hxx"
#include "formulacell.hxx"
#include "tokenarray.hxx"
#include "compiler.hxx"
#include "interpre.hxx"
#include "scmatrix.hxx"

#include "formula/vectortoken.hxx"
#include "rtl/bootstrap.hxx"
#include "config_features.h"

#include <vector>
#include <boost/unordered_map.hpp>

#define USE_DUMMY_INTERPRETER 0

#if USE_DUMMY_INTERPRETER
#include <cstdio>
#endif

namespace sc {

rtl_uString* FormulaGroupContext::intern( const OUString& rStr )
{
    StrHashType::iterator it = maStrPool.find(rStr);
    if (it == maStrPool.end())
    {
        // Not yet in the pool.
        std::pair<StrHashType::iterator, bool> r = maStrPool.insert(rStr.intern());
        if (!r.second)
            // Insertion failed.
            return NULL;

        it = r.first;
    }

    return it->pData;
}

namespace {

/**
 * Input double array consists of segments of NaN's and normal values.
 * Insert only the normal values into the matrix while skipping the NaN's.
 */
void fillMatrix( ScMatrix& rMat, size_t nCol, const double* pNums, size_t nLen )
{
    const double* p = pNums;
    const double* pEnd = p + nLen;
    const double* pHead = NULL;
    for (; p != pEnd; ++p)
    {
        if (!rtl::math::isNan(*p))
        {
            if (!pHead)
                // Store the first non-NaN position.
                pHead = p;

            continue;
        }

        if (pHead)
        {
            // Flush this non-NaN segment to the matrix.
            rMat.PutDouble(pHead, p - pHead, nCol, pHead - pNums);
            pHead = NULL;
        }
    }

    if (pHead)
    {
        // Flush last non-NaN segment to the matrix.
        rMat.PutDouble(pHead, p - pHead, nCol, pHead - pNums);
    }
}

void flushSegment(
    ScMatrix& rMat, size_t nCol, rtl_uString** pHead, rtl_uString** pCur, rtl_uString** pTop )
{
    size_t nOffset = pHead - pTop;
    std::vector<OUString> aStrs;
    aStrs.reserve(pCur - pHead);
    for (; pHead != pCur; ++pHead)
        aStrs.push_back(OUString(*pHead));

    rMat.PutString(&aStrs[0], aStrs.size(), nCol, nOffset);
}

void fillMatrix( ScMatrix& rMat, size_t nCol, rtl_uString** pStrs, size_t nLen )
{
    rtl_uString** p = pStrs;
    rtl_uString** pEnd = p + nLen;
    rtl_uString** pHead = NULL;
    for (; p != pEnd; ++p)
    {
        if (*p)
        {
            if (!pHead)
                // Store the first non-empty string position.
                pHead = p;

            continue;
        }

        if (pHead)
        {
            // Flush this non-empty segment to the matrix.
            flushSegment(rMat, nCol, pHead, p, pStrs);
            pHead = NULL;
        }
    }

    if (pHead)
    {
        // Flush last non-empty segment to the matrix.
        flushSegment(rMat, nCol, pHead, p, pStrs);
    }
}

}

FormulaGroupInterpreterSoftware::FormulaGroupInterpreterSoftware() : FormulaGroupInterpreter()
{
}

ScMatrixRef FormulaGroupInterpreterSoftware::inverseMatrix(const ScMatrix& /*rMat*/)
{
    return ScMatrixRef();
}

bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddress& rTopPos,
                                                const ScFormulaCellGroupRef& xGroup,
                                                ScTokenArray& rCode)
{
    typedef boost::unordered_map<const formula::FormulaToken*, formula::FormulaTokenRef> CachedTokensType;

    // Decompose the group into individual cells and calculate them individually.

    // The caller must ensure that the top position is the start position of
    // the group.

    ScAddress aTmpPos = rTopPos;
    std::vector<double> aResults;
    aResults.reserve(xGroup->mnLength);
    CachedTokensType aCachedTokens;

    double fNan;
    rtl::math::setNan(&fNan);

    for (SCROW i = 0; i < xGroup->mnLength; ++i, aTmpPos.IncRow())
    {
        ScTokenArray aCode2;
        for (const formula::FormulaToken* p = rCode.First(); p; p = rCode.Next())
        {
            CachedTokensType::iterator it = aCachedTokens.find(p);
            if (it != aCachedTokens.end())
            {
                // This token is cached. Use the cached one.
                aCode2.AddToken(*it->second);
                continue;
            }

            switch (p->GetType())
            {
                case formula::svSingleVectorRef:
                {
                    const formula::SingleVectorRefToken* p2 = static_cast<const formula::SingleVectorRefToken*>(p);
                    const formula::VectorRefArray& rArray = p2->GetArray();
                    if (rArray.mbNumeric)
                    {
                        double fVal = fNan;
                        if (static_cast<size_t>(i) < p2->GetArrayLength())
                            fVal = rArray.mpNumericArray[i];

                        if (rtl::math::isNan(fVal))
                            aCode2.AddToken(ScEmptyCellToken(false, false));
                        else
                            aCode2.AddDouble(fVal);
                    }
                    else
                    {
                        rtl_uString* pStr = NULL;
                        if (static_cast<size_t>(i) < p2->GetArrayLength())
                            pStr = rArray.mpStringArray[i];

                        if (pStr)
                            aCode2.AddString(OUString(pStr));
                    }
                }
                break;
                case formula::svDoubleVectorRef:
                {
                    const formula::DoubleVectorRefToken* p2 = static_cast<const formula::DoubleVectorRefToken*>(p);
                    const std::vector<formula::VectorRefArray>& rArrays = p2->GetArrays();
                    size_t nColSize = rArrays.size();
                    size_t nRowStart = p2->IsStartFixed() ? 0 : i;
                    size_t nRowEnd = p2->GetRefRowSize() - 1;
                    if (!p2->IsEndFixed())
                        nRowEnd += i;
                    size_t nRowSize = nRowEnd - nRowStart + 1;
                    ScMatrixRef pMat(new ScMatrix(nColSize, nRowSize));

                    size_t nDataRowEnd = p2->GetArrayLength() - 1;
                    if (nRowStart > nDataRowEnd)
                        // Referenced rows are all empty.
                        nRowSize = 0;
                    else if (nRowEnd > nDataRowEnd)
                        // Data array is shorter than the row size of the reference. Truncate it to the data.
                        nRowSize -= nRowEnd - nDataRowEnd;

                    for (size_t nCol = 0; nCol < nColSize; ++nCol)
                    {
                        const formula::VectorRefArray& rArray = rArrays[nCol];
                        if (rArray.mbNumeric)
                        {
                            const double* pNums = rArray.mpNumericArray;
                            pNums += nRowStart;
                            fillMatrix(*pMat, nCol, pNums, nRowSize);
                        }
                        else
                        {
                            rtl_uString** pStrs = rArray.mpStringArray;
                            pStrs += nRowStart;
                            fillMatrix(*pMat, nCol, pStrs, nRowSize);
                        }
                    }

                    if (p2->IsStartFixed() && p2->IsEndFixed())
                    {
                        // Cached the converted token for absolute range referene.
                        ScComplexRefData aRef;
                        ScRange aRefRange = rTopPos;
                        aRefRange.aEnd.SetRow(rTopPos.Row() + nRowEnd);
                        aRef.InitRange(aRefRange);
                        formula::FormulaTokenRef xTok(new ScMatrixRangeToken(pMat, aRef));
                        aCachedTokens.insert(CachedTokensType::value_type(p, xTok));
                        aCode2.AddToken(*xTok);
                    }
                    else
                    {
                        ScMatrixToken aTok(pMat);
                        aCode2.AddToken(aTok);
                    }
                }
                break;
                default:
                    aCode2.AddToken(*p);
            }
        }

        ScFormulaCell* pDest = rDoc.GetFormulaCell(aTmpPos);
        if (!pDest)
            return false;

        generateRPNCode(rDoc, aTmpPos, aCode2);
        ScInterpreter aInterpreter(pDest, &rDoc, aTmpPos, aCode2);
        aInterpreter.Interpret();
        aResults.push_back(aInterpreter.GetResultToken()->GetDouble());
    } // for loop end (xGroup->mnLength)

    if (!aResults.empty())
        rDoc.SetFormulaResults(rTopPos, &aResults[0], aResults.size());

    return true;
}

#if USE_DUMMY_INTERPRETER
class FormulaGroupInterpreterDummy : public FormulaGroupInterpreter
{
    enum Mode {
        WRITE_OUTPUT = 0
    };
    Mode meMode;
public:
    FormulaGroupInterpreterDummy()
    {
        const char *pValue = getenv("FORMULA_GROUP_DUMMY");
        meMode = static_cast<Mode>(OString(pValue, strlen(pValue)).toInt32());
        fprintf(stderr, "Using Dummy Formula Group interpreter mode %d\n", (int)meMode);
    }

    virtual ScMatrixRef inverseMatrix(const ScMatrix& /*rMat*/)
    {
        return ScMatrixRef();
    }

    virtual bool interpret(ScDocument& rDoc, const ScAddress& rTopPos,
                           const ScFormulaCellGroupRef& xGroup,
                           ScTokenArray& rCode)
    {
        (void)rCode;

        // Write simple data back into the sheet
        if (meMode == WRITE_OUTPUT)
        {
            double *pDoubles = new double[xGroup->mnLength];
            for (sal_Int32 i = 0; i < xGroup->mnLength; i++)
                pDoubles[i] = 42.0 + i;
            rDoc.SetFormulaResults(rTopPos, pDoubles, xGroup->mnLength);
            delete [] pDoubles;
        }
        return true;
    }
};

#endif

#ifndef DISABLE_DYNLOADING

class FormulaGroupInterpreterOpenCLMissing : public FormulaGroupInterpreter
{
public:
    FormulaGroupInterpreterOpenCLMissing() : FormulaGroupInterpreter() {}
    virtual ~FormulaGroupInterpreterOpenCLMissing() {}
    virtual ScMatrixRef inverseMatrix(const ScMatrix&) { return ScMatrixRef(); }
    virtual bool interpret(ScDocument&, const ScAddress&, const ScFormulaCellGroupRef&, ScTokenArray&) { return false; }
};

static void SAL_CALL thisModule() {}

typedef FormulaGroupInterpreter* (*__createFormulaGroupOpenCLInterpreter)(void);
typedef size_t (*__getOpenCLPlatformCount)(void);
typedef void (*__fillOpenCLInfo)(OpenclPlatformInfo*, size_t);
typedef bool (*__switchOpenClDevice)(const OUString*, bool);
typedef void (*__compileOpenCLKernels)(const OUString*);

#endif

FormulaGroupInterpreter *FormulaGroupInterpreter::msInstance = NULL;

#ifndef DISABLE_DYNLOADING

osl::Module* getOpenCLModule()
{
    static osl::Module aModule;
    if (aModule.is())
        // Already loaded.
        return &aModule;

    OUString aLibName(SVLIBRARY("scopencl"));
    bool bLoaded = aModule.loadRelative(&thisModule, aLibName);
    if (!bLoaded)
        bLoaded = aModule.load(aLibName);

    return bLoaded ? &aModule : NULL;
}

#endif

/// load and/or configure the correct formula group interpreter
FormulaGroupInterpreter *FormulaGroupInterpreter::getStatic()
{
#if USE_DUMMY_INTERPRETER
    if (getenv("FORMULA_GROUP_DUMMY"))
    {
        delete msInstance;
        return msInstance = new sc::FormulaGroupInterpreterDummy();
    }
#endif

    if ( !msInstance )
    {
        switchOpenCLDevice(OUString(), ScInterpreter::GetGlobalConfig().mbOpenCLEnabled);
        if ( !msInstance ) // software fallback
        {
            fprintf(stderr, "Create S/W interp\n");
            msInstance = new sc::FormulaGroupInterpreterSoftware();
        }
    }

    return msInstance;
}

void FormulaGroupInterpreter::fillOpenCLInfo(std::vector<OpenclPlatformInfo>& rPlatforms)
{
#ifndef DISABLE_DYNLOADING
    osl::Module* pModule = getOpenCLModule();
    if (!pModule)
        return;

    oslGenericFunction fn = pModule->getFunctionSymbol("getOpenCLPlatformCount");
    if (!fn)
        return;

    size_t nPlatforms = reinterpret_cast<__getOpenCLPlatformCount>(fn)();
    if (!nPlatforms)
        return;

    fn = pModule->getFunctionSymbol("fillOpenCLInfo");
    if (!fn)
        return;

    std::vector<OpenclPlatformInfo> aPlatforms(nPlatforms);
    reinterpret_cast<__fillOpenCLInfo>(fn)(&aPlatforms[0], aPlatforms.size());
    rPlatforms.swap(aPlatforms);
#else
    extern size_t getOpenCLPlatformCount(void);
    extern void fillOpenCLInfo(OpenclPlatformInfo*, size_t);

    size_t nPlatforms = getOpenCLPlatformCount();
    if (!nPlatforms)
        return;

    std::vector<OpenclPlatformInfo> aPlatforms(nPlatforms);
    fillOpenCLInfo(&aPlatforms[0], aPlatforms.size());
    rPlatforms.swap(aPlatforms);
#endif
}

void FormulaGroupInterpreter::switchOpenCLDevice(const OUString& rDeviceId, bool bAutoSelect)
{
    bool bOpenCLEnabled = ScInterpreter::GetGlobalConfig().mbOpenCLEnabled;
    if(!bOpenCLEnabled || rDeviceId == "Software")
    {
        if(msInstance)
        {
            // if we already have a software interpreter don't delete it
            if(dynamic_cast<sc::FormulaGroupInterpreterSoftware*>(msInstance))
                return;

            delete msInstance;
        }

        msInstance = new sc::FormulaGroupInterpreterSoftware();
        return;
    }
#ifndef DISABLE_DYNLOADING
    osl::Module* pModule = getOpenCLModule();
    if (!pModule)
        return;

    oslGenericFunction fn = pModule->getFunctionSymbol("switchOpenClDevice");
    if (!fn)
        return;

    bool bSuccess = reinterpret_cast<__switchOpenClDevice>(fn)(&rDeviceId, bAutoSelect);
    if(!bSuccess)
        return;
#else
    extern bool switchOpenClDevice(const OUString*, bool);

    bool bSuccesss = switchOpenClDevice(&rDeviceId, bAutoSelect);
    if(!bSuccess)
        return;
#endif

    delete msInstance;
    msInstance = NULL;

#if HAVE_FEATURE_OPENCL

    if ( ScInterpreter::GetGlobalConfig().mbOpenCLEnabled )
    {
#ifdef DISABLE_DYNLOADING
        extern sc::FormulaGroupInterpreter* createFormulaGroupOpenCLInterpreter();
        msInstance = createFormulaGroupOpenCLInterpreter();
#else
        // Dynamically load scopencl shared object, and instantiate the opencl interpreter.
        fn = pModule->getFunctionSymbol("createFormulaGroupOpenCLInterpreter");
        if (fn)
            msInstance = reinterpret_cast<__createFormulaGroupOpenCLInterpreter>(fn)();

        if (!msInstance)
            msInstance = new sc::FormulaGroupInterpreterOpenCLMissing();
#endif
    }
#endif
}

void FormulaGroupInterpreter::compileOpenCLKernels()
{
    const ScCalcConfig& rConfig = ScInterpreter::GetGlobalConfig();
    if (!rConfig.mbOpenCLEnabled)
        // OpenCL is not enabled.
        return;

#ifndef DISABLE_DYNLOADING
    osl::Module* pModule = getOpenCLModule();
    if (!pModule)
        return;

    oslGenericFunction fn = pModule->getFunctionSymbol("compileOpenCLKernels");
    if (!fn)
        return;

    reinterpret_cast<__compileOpenCLKernels>(fn)(&rConfig.maOpenCLDevice);
#else
    extern void compileOpenCLKernels(const OUString*);

    compileOpenCLKernels(&rConfig.maOpenCLDevice);
#endif
}

void FormulaGroupInterpreter::generateRPNCode(ScDocument& rDoc, const ScAddress& rPos, ScTokenArray& rCode)
{
    // First, generate an RPN (reverse polish notation) token array.
    ScCompiler aComp(&rDoc, rPos, rCode);
    aComp.SetGrammar(rDoc.GetGrammar());
    aComp.CompileTokenArray(); // Create RPN token array.
    // Now, calling FirstRPN() and NextRPN() will return tokens from the RPN token array.
}

}

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


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

#include "media/base/android/media_player_bridge_manager.h"

namespace media {

MediaPlayerBridgeManager::~MediaPlayerBridgeManager() {}

}
<commit_msg>[Android] Upstream a namespace comment in media<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/base/android/media_player_bridge_manager.h"

namespace media {

MediaPlayerBridgeManager::~MediaPlayerBridgeManager() {}

}  // namespace media
<|endoftext|>


<commit_before>#include "main.hpp"

using namespace std;

int main(int argc, char** argv)
{
    // Init mpi
    int n_tasks, my_rank;
    MPI_Datatype mpi_particle;
    pcord_t* mpi_p;

    MPI_Request send_count_request;
    MPI_Request send_data_request;
    MPI_Request receive_data_request;
    MPI_Request receive_count_request;
    unsigned recv_count = 0;
    int send_count = 0;
    pcord_t* recv_buffer;

    MPI_Comm com = MPI_COMM_WORLD;
    MPI_Init(&argc, &argv);
    MPI_Comm_size(com, &n_tasks);
    MPI_Comm_rank(com, &my_rank);
    create_mpi_particle_t(mpi_p, &mpi_particle);

    // Init random nr generator
    Utils::init(my_rank);

    // Initiate walls for box as well as split box into sub-areas
    const cord_t box = {0, BOX_HORIZ_SIZE, 0, BOX_VERT_SIZE};
    vector<pcord_t*> particles;
    vector<pcord_t*> tmp_particles;
    float vert_stop;

    if ( my_rank != n_tasks-1 ) {
        vert_stop = ((float)BOX_VERT_SIZE/n_tasks)*(my_rank+1);
    }
    else {
        vert_stop = (float)BOX_VERT_SIZE;
    }

    cord_t my_cords = {0, (float)BOX_HORIZ_SIZE, ((float)BOX_HORIZ_SIZE/n_tasks)*my_rank, vert_stop};

    // Initiate particles
    for (size_t i = 0; i < INIT_NO_PARTICLES; i++) {
        pcord_t* p = new pcord_t();
        p->x = Utils::generate_random_float(my_cords.x0, my_cords.x1);
        p->y = Utils::generate_random_float(my_cords.y0, my_cords.y1);
        p->vx = Utils::generate_random_float(0, MAX_INITIAL_VELOCITY);
        p->vy = Utils::generate_random_float(0, MAX_INITIAL_VELOCITY);
        particles.push_back(p);
    }

    // Main loop: for each time-step do
    float total_momentum = 0;
    float collision;

    // Temporary storage for transfers
    vector<pcord_t> up_transfers;
    vector<pcord_t> down_transfers;

    vector<int> pos_to_erase;

    for (size_t t = 0; t < _SIMULATION_STEPS_; t++) {

        // Check for collisions.
        // Move particles that has not collided with another.
        // Check for wall interaction and add the momentum.
        // Check if particles need to be communicated
        pcord_t* particle;
        pcord_t* other_particle;
        size_t last_pos = particles.size()-1;

        for (size_t i = 0; i < last_pos; i++) {
            particle = particles.at(i);
            for (size_t j = i+1; j < last_pos+1; j++) {
                other_particle = particles.at(j);
                collision = collide(particle, other_particle);
                interact(particle, other_particle, collision);
            }

            total_momentum += wall_collide(particle,box);

            if ( particle->y < my_cords.y0 ) {
                up_transfers.push_back(*particle);
                pos_to_erase.push_back(i);
            }
            else if ( particle->y > my_cords.y1 ){
                down_transfers.push_back(*particle);
                pos_to_erase.push_back(i);
            }
            else{
                tmp_particles.push_back(particle);
            }
        }

        particle = particles.at(last_pos);
        total_momentum += wall_collide(particle,box);

        if ( particle->y < my_cords.y0 ) {
            up_transfers.push_back(*particle);
            pos_to_erase.push_back(last_pos);
        }
        else if ( particle->y > my_cords.y1 ){
            down_transfers.push_back(*particle);
            pos_to_erase.push_back(last_pos);
        }
        else{
            tmp_particles.push_back(particle);
        }

        // Free memory
        size_t pos_to_erase_size = pos_to_erase.size();
        for (size_t i = 0; i < pos_to_erase_size; i++) {
            delete particles.at(pos_to_erase.back());
            pos_to_erase.pop_back();
        }
        particles.erase(particles.begin(), particles.end());
        particles.swap(tmp_particles);

        // Send particles who should change processing element
        if (my_rank != n_tasks-1) {
            send_count = down_transfers.size();
            MPI_Ibsend(&send_count, 1, MPI_UNSIGNED, my_rank+1, 2*my_rank+1, com, &send_count_request);

            if(send_count != 0) {
                MPI_Ibsend(&down_transfers.at(0), send_count, mpi_particle, my_rank+1, my_rank+1, com, &send_data_request);
            }
        }

        if ( my_rank != 0) {
            // Receive the nr of elements to get from processor my_rank-1
            MPI_Irecv(&recv_count, 1, MPI_UNSIGNED, my_rank-1, 2*my_rank-1, com, &receive_count_request);
            MPI_Wait(&receive_count_request, MPI_STATUS_IGNORE);

            if(recv_count != 0) {
                // Allocate buffer
                recv_buffer = (pcord_t*)malloc(sizeof(pcord_t)*recv_count);

                // Receive elements from my_rank-1
                MPI_Irecv(recv_buffer, recv_count, mpi_particle, my_rank-1, my_rank, com, &receive_data_request);
                MPI_Wait(&receive_data_request, MPI_STATUS_IGNORE);

                // Check whether receive particles and upgoing particles collide
                pcord_t *particle, *other_particle;
                size_t transfer_size = up_transfers.size();
                vector<int> back_to_particles;

                for (size_t i = 0; i < recv_count; i++) {
                    for (size_t j = 0; j < transfer_size; j++) {

                        particle = &recv_buffer[i];
                        other_particle = &up_transfers.at(j);

                        collision = collide(particle, other_particle);
                        interact(particle, other_particle, collision);

                        // Check if incomming particle should be sent back or kept
                        if ( particle->y < my_cords.y0 ) {
                            up_transfers.push_back(*particle);
                        }
                        else{
                            pcord_t* p = new pcord_t();
                            p->x = particle->x;
                            p->y = particle->y;
                            p->vx = particle->vx;
                            p->vy = particle->vy;
                            particles.push_back(p);
                        }
                        // Check if we should keep outgoing particle
                        if (other_particle->y >= my_cords.y0) {
                            back_to_particles.push_back(j);
                        }
                    }
                }

                // Put back outgoing particles if they should be put back in particles
                transfer_size = back_to_particles.size();
                unsigned pos;

                for (size_t i = 0; i < transfer_size; i++) {
                    pos = back_to_particles.back();
                    pcord_t* p = new pcord_t();
                    p->x = recv_buffer[pos].x;
                    p->y = recv_buffer[pos].y;
                    p->vx = recv_buffer[pos].vx;
                    p->vy = recv_buffer[pos].vy;
                    particles.push_back(p);
                    back_to_particles.pop_back();
                }

                // Free the receive buffer
                free(recv_buffer);
            }

            // Send particles to my_rank-1
            if (my_rank != n_tasks-1) { // First see that send_count is available for reuse
                MPI_Wait(&send_count_request, MPI_STATUS_IGNORE);
                if(send_count != 0) {
                    MPI_Wait(&send_data_request, MPI_STATUS_IGNORE);
                }
            }

            send_count = up_transfers.size();
            MPI_Ibsend(&send_count, 1, MPI_UNSIGNED, my_rank-1, 2*my_rank-1, com, &send_count_request);
            if(send_count != 0) {
                MPI_Ibsend(&up_transfers.at(0), send_count, mpi_particle, my_rank-1, my_rank-1, com, &send_data_request);
            }
        }

        // Receive particles from my_rank+1
        if (my_rank != n_tasks-1) {
            // Receive the nr of elements to get from processor my_rank+1
            MPI_Irecv(&recv_count, 1, MPI_UNSIGNED, my_rank+1, 2*my_rank+1, com, &receive_count_request);
            MPI_Wait(&receive_count_request, MPI_STATUS_IGNORE);

            if(recv_count != 0) {
                // Allocate recv buffer
                recv_buffer = (pcord_t*)malloc(sizeof(pcord_t)*recv_count);

                // Get the particles!
                MPI_Irecv(recv_buffer, recv_count, mpi_particle, my_rank+1, my_rank, com, &receive_data_request);
                MPI_Wait(&receive_data_request, MPI_STATUS_IGNORE);

                for (size_t i = 0; i < recv_count; i++) {
                    pcord_t* p = new pcord_t();
                    p->x = recv_buffer[i].x;
                    p->y = recv_buffer[i].y;
                    p->vx = recv_buffer[i].vx;
                    p->vy = recv_buffer[i].vy;
                    particles.push_back(p);
                }

                free(recv_buffer);
            }
        }

        // Wait for send stuff to get free for next run.
        MPI_Wait(&send_count_request, MPI_STATUS_IGNORE);
        if(send_count != 0) {
            MPI_Wait(&send_data_request, MPI_STATUS_IGNORE);
        }
        up_transfers.clear();
        down_transfers.clear();
    }

    // Reduction and calculate pressure.
    total_momentum = total_momentum/(_SIMULATION_STEPS_ * STEP_SIZE);

    if(my_rank == 0) {
        MPI_Reduce(MPI_IN_PLACE, &total_momentum, 1, MPI_FLOAT, MPI_SUM, 0, com);
            cout << "Pressure = " << total_momentum << endl;
    }
    else {
        MPI_Reduce(&total_momentum, &total_momentum, 1, MPI_FLOAT, MPI_SUM, 0, com);
    }

    MPI_Finalize();
    return 0;
}
<commit_msg>Unique IDs<commit_after>#include "main.hpp"

using namespace std;

int main(int argc, char** argv)
{
    // Init mpi
    int n_tasks, my_rank;
    MPI_Datatype mpi_particle;
    pcord_t* mpi_p;

    MPI_Request send_count_request;
    MPI_Request send_data_request;
    MPI_Request receive_data_request;
    MPI_Request receive_count_request;
    unsigned recv_count = 0;
    int send_count = 0;
    pcord_t* recv_buffer;

    MPI_Comm com = MPI_COMM_WORLD;
    MPI_Init(&argc, &argv);
    MPI_Comm_size(com, &n_tasks);
    MPI_Comm_rank(com, &my_rank);
    create_mpi_particle_t(mpi_p, &mpi_particle);

    // Init random nr generator
    Utils::init(my_rank);

    // Initiate walls for box as well as split box into sub-areas
    const cord_t box = {0, BOX_HORIZ_SIZE, 0, BOX_VERT_SIZE};
    vector<pcord_t*> particles;
    vector<pcord_t*> tmp_particles;
    float vert_stop;

    if ( my_rank != n_tasks-1 ) {
        vert_stop = ((float)BOX_VERT_SIZE/n_tasks)*(my_rank+1);
    }
    else {
        vert_stop = (float)BOX_VERT_SIZE;
    }

    cord_t my_cords = {0, (float)BOX_HORIZ_SIZE, ((float)BOX_HORIZ_SIZE/n_tasks)*my_rank, vert_stop};

    // Initiate particles
    for (size_t i = 0; i < INIT_NO_PARTICLES; i++) {
        pcord_t* p = new pcord_t();
        p->x = Utils::generate_random_float(my_cords.x0, my_cords.x1);
        p->y = Utils::generate_random_float(my_cords.y0, my_cords.y1);
        p->vx = Utils::generate_random_float(0, MAX_INITIAL_VELOCITY);
        p->vy = Utils::generate_random_float(0, MAX_INITIAL_VELOCITY);
        particles.push_back(p);
    }

    // Main loop: for each time-step do
    float total_momentum = 0;
    float collision;

    // Temporary storage for transfers
    vector<pcord_t> up_transfers;
    vector<pcord_t> down_transfers;

    vector<int> pos_to_erase;

    for (size_t t = 0; t < _SIMULATION_STEPS_; t++) {

        // Check for collisions.
        // Move particles that has not collided with another.
        // Check for wall interaction and add the momentum.
        // Check if particles need to be communicated
        pcord_t* particle;
        pcord_t* other_particle;
        size_t last_pos = particles.size()-1;

        for (size_t i = 0; i < last_pos; i++) {
            particle = particles.at(i);
            for (size_t j = i+1; j < last_pos+1; j++) {
                other_particle = particles.at(j);
                collision = collide(particle, other_particle);
                interact(particle, other_particle, collision);
            }

            total_momentum += wall_collide(particle,box);

            if ( particle->y < my_cords.y0 ) {
                up_transfers.push_back(*particle);
                pos_to_erase.push_back(i);
            }
            else if ( particle->y > my_cords.y1 ){
                down_transfers.push_back(*particle);
                pos_to_erase.push_back(i);
            }
            else{
                tmp_particles.push_back(particle);
            }
        }

        particle = particles.at(last_pos);
        total_momentum += wall_collide(particle,box);

        if ( particle->y < my_cords.y0 ) {
            up_transfers.push_back(*particle);
            pos_to_erase.push_back(last_pos);
        }
        else if ( particle->y > my_cords.y1 ){
            down_transfers.push_back(*particle);
            pos_to_erase.push_back(last_pos);
        }
        else{
            tmp_particles.push_back(particle);
        }

        // Free memory
        size_t pos_to_erase_size = pos_to_erase.size();
        for (size_t i = 0; i < pos_to_erase_size; i++) {
            delete particles.at(pos_to_erase.back());
            pos_to_erase.pop_back();
        }
        particles.erase(particles.begin(), particles.end());
        particles.swap(tmp_particles);

        // Send particles who should change processing element
        if (my_rank != n_tasks-1) {
            send_count = down_transfers.size();
            MPI_Ibsend(&send_count, 1, MPI_UNSIGNED, my_rank+1, 2*(my_rank+1), com, &send_count_request);

            if(send_count != 0) {
                MPI_Ibsend(&down_transfers.at(0), send_count, mpi_particle, my_rank+1, my_rank+1, com, &send_data_request);
            }
        }

        if ( my_rank != 0) {
            // Receive the nr of elements to get from processor my_rank-1
            MPI_Irecv(&recv_count, 1, MPI_UNSIGNED, my_rank-1, 2*my_rank, com, &receive_count_request);
            MPI_Wait(&receive_count_request, MPI_STATUS_IGNORE);

            if(recv_count != 0) {
                // Allocate buffer
                recv_buffer = (pcord_t*)malloc(sizeof(pcord_t)*recv_count);

                // Receive elements from my_rank-1
                MPI_Irecv(recv_buffer, recv_count, mpi_particle, my_rank-1, my_rank, com, &receive_data_request);
                MPI_Wait(&receive_data_request, MPI_STATUS_IGNORE);

                // Check whether receive particles and upgoing particles collide
                pcord_t *particle, *other_particle;
                size_t transfer_size = up_transfers.size();
                vector<int> back_to_particles;

                for (size_t i = 0; i < recv_count; i++) {
                    for (size_t j = 0; j < transfer_size; j++) {

                        particle = &recv_buffer[i];
                        other_particle = &up_transfers.at(j);

                        collision = collide(particle, other_particle);
                        interact(particle, other_particle, collision);

                        // Check if incomming particle should be sent back or kept
                        if ( particle->y < my_cords.y0 ) {
                            up_transfers.push_back(*particle);
                        }
                        else{
                            pcord_t* p = new pcord_t();
                            p->x = particle->x;
                            p->y = particle->y;
                            p->vx = particle->vx;
                            p->vy = particle->vy;
                            particles.push_back(p);
                        }
                        // Check if we should keep outgoing particle
                        if (other_particle->y >= my_cords.y0) {
                            back_to_particles.push_back(j);
                        }
                    }
                }

                // Put back outgoing particles if they should be put back in particles
                transfer_size = back_to_particles.size();
                unsigned pos;

                for (size_t i = 0; i < transfer_size; i++) {
                    pos = back_to_particles.back();
                    pcord_t* p = new pcord_t();
                    p->x = recv_buffer[pos].x;
                    p->y = recv_buffer[pos].y;
                    p->vx = recv_buffer[pos].vx;
                    p->vy = recv_buffer[pos].vy;
                    particles.push_back(p);
                    back_to_particles.pop_back();
                }

                // Free the receive buffer
                free(recv_buffer);
            }

            // Send particles to my_rank-1
            if (my_rank != n_tasks-1) { // First see that send_count is available for reuse
                MPI_Wait(&send_count_request, MPI_STATUS_IGNORE);
                if(send_count != 0) {
                    MPI_Wait(&send_data_request, MPI_STATUS_IGNORE);
                }
            }

            send_count = up_transfers.size();
            MPI_Ibsend(&send_count, 1, MPI_UNSIGNED, my_rank-1, 2*my_rank, com, &send_count_request);
            if(send_count != 0) {
                MPI_Ibsend(&up_transfers.at(0), send_count, mpi_particle, my_rank-1, my_rank-1, com, &send_data_request);
            }
        }

        // Receive particles from my_rank+1
        if (my_rank != n_tasks-1) {
            // Receive the nr of elements to get from processor my_rank+1
            MPI_Irecv(&recv_count, 1, MPI_UNSIGNED, my_rank+1, 2*(my_rank+1), com, &receive_count_request);
            MPI_Wait(&receive_count_request, MPI_STATUS_IGNORE);

            if(recv_count != 0) {
                // Allocate recv buffer
                recv_buffer = (pcord_t*)malloc(sizeof(pcord_t)*recv_count);

                // Get the particles!
                MPI_Irecv(recv_buffer, recv_count, mpi_particle, my_rank+1, my_rank, com, &receive_data_request);
                MPI_Wait(&receive_data_request, MPI_STATUS_IGNORE);

                for (size_t i = 0; i < recv_count; i++) {
                    pcord_t* p = new pcord_t();
                    p->x = recv_buffer[i].x;
                    p->y = recv_buffer[i].y;
                    p->vx = recv_buffer[i].vx;
                    p->vy = recv_buffer[i].vy;
                    particles.push_back(p);
                }

                free(recv_buffer);
            }
        }

        // Wait for send stuff to get free for next run.
        MPI_Wait(&send_count_request, MPI_STATUS_IGNORE);
        if(send_count != 0) {
            MPI_Wait(&send_data_request, MPI_STATUS_IGNORE);
        }
        up_transfers.clear();
        down_transfers.clear();
    }

    // Reduction and calculate pressure.
    total_momentum = total_momentum/(_SIMULATION_STEPS_ * STEP_SIZE);

    if(my_rank == 0) {
        MPI_Reduce(MPI_IN_PLACE, &total_momentum, 1, MPI_FLOAT, MPI_SUM, 0, com);
            cout << "Pressure = " << total_momentum << endl;
    }
    else {
        MPI_Reduce(&total_momentum, &total_momentum, 1, MPI_FLOAT, MPI_SUM, 0, com);
    }

    MPI_Finalize();
    return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: dbastrings.cxx,v $
 *
 *  $Revision: 1.1 $
 *
 *  last change: $Author: oj $ $Date: 2000-10-24 13:04:00 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/
#ifndef DBACCESS_SHARED_DBASTRINGS_HRC
#include "dbastrings.hrc"
#endif

namespace dbaccess
{
#include "stringconstants.cxx"
}
<commit_msg>#87909# moved dba-specific strings herein (not compiled into both libraries anymore)<commit_after>/*************************************************************************
 *
 *  $RCSfile: dbastrings.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: fs $ $Date: 2001-06-08 08:39:31 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/
#ifndef DBACCESS_SHARED_DBASTRINGS_HRC
#include "dbastrings.hrc"
#endif

namespace dbaccess
{

#include "stringconstants.cxx"

    //============================================================
    //= configuration key names
    //============================================================
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DBLINK_CONNECTURL, "URL");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DBLINK_USER, "User");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DBLINK_TABLEFILTER, "TableFilter");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DBLINK_TABLETYEFILTER, "TableTypeFilter");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DBLINK_LOGINTIMEOUT, "LoginTimeout");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DBLINK_PASSWORDREQUIRED, "IsPasswordRequired");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DBLINK_SUPPRESSVERSIONCL, "SuppressVersionColumns");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DBLINK_INFO, "DataSourceSettings");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DBLINK_BOOKMARKS, "Bookmarks");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DBLINK_QUERYDOCUMENTS, "Queries");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DBLINK_TABLES, "Tables");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DBLINK_DOCUMENTLOCAITON, "DocumentLocation");

    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_QRYDESCR_COMMAND, "Command");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_QRYDESCR_USE_ESCAPE_PROCESSING, "EscapeProcessing");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_QRYDESCR_UPDATE_TABLENAME, "UpdateTableName");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_QRYDESCR_UPDATE_SCHEMANAME, "UpdateSchemaName");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_QRYDESCR_UPDATE_CATALOGNAME, "UpdateCatalogName");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_QRYDESCR_COLUMNS, "Columns");

    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DATASETTINGS_MAIN, "DataSettings");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_SETTINGS, "Settings");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DEFSET_FILTER, "Filter");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DEFSET_APPLYFILTER, "ApplyFilter");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DEFSET_ORDER, "Order");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DEFSET_ROW_HEIGHT, "RowHeight");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_LAYOUTINFORMATION, "LayoutInformation");

    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DEFSET_TEXTCOLOR, "TextColor");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DEFSET_FONT_NAME, "Font/Name");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DEFSET_FONT_HEIGHT, "Font/Height");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DEFSET_FONT_WIDTH, "Font/Width");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DEFSET_FONT_STYLENAME, "Font/StyleName");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DEFSET_FONT_FAMILY, "Font/Family");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DEFSET_FONT_CHARSET, "Font/CharSet");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DEFSET_FONT_PITCH, "Font/Pitch");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DEFSET_FONT_CHARACTERWIDTH, "Font/CharacterWidth");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DEFSET_FONT_WEIGHT, "Font/Weight");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DEFSET_FONT_SLANT, "Font/Slant");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DEFSET_FONT_UNDERLINE, "Font/UnderLine");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DEFSET_FONT_STRIKEOUT, "Font/Strikeout");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DEFSET_FONT_ORIENTATION, "Font/Orientation");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DEFSET_FONT_KERNING, "Font/Kerning");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DEFSET_FONT_WORDLINEMODE, "Font/WordLineMode");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_DEFSET_FONT_TYPE, "Font/Type");

    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_COLUMN_ALIGNMENT, "Align");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_COLUMN_WIDTH, "Width");
//  IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_COLUMN_DESCRIPTION, "Description");
//  IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_COLUMN_DEFAULTVALUE, "DefaultValue");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_COLUMN_NUMBERFORMAT, "FormatKey");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_COLUMN_RELPOSITION, "Position");
    IMPLEMENT_CONSTASCII_USTRING(CONFIGKEY_COLUMN_HIDDEN, "Hidden");

    //============================================================
    //= SQLSTATE
    //============================================================
    IMPLEMENT_CONSTASCII_USTRING(SQLSTATE_GENERAL, "01000");

}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: queryorder.cxx,v $
 *
 *  $Revision: 1.17 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-20 03:09:43 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/
#ifndef DBAUI_QUERYORDER_HRC
#include "queryorder.hrc"
#endif
#ifndef DBAUI_QUERYORDER_HXX
#include "queryorder.hxx"
#endif

#ifndef DBACCESS_SHARED_DBUSTRINGS_HRC
#include "dbustrings.hrc"
#endif

#ifndef _COM_SUN_STAR_SDB_XSINGLESELECTQUERYCOMPOSER_HPP_
#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_COLUMNSEARCH_HPP_
#include <com/sun/star/sdbc/ColumnSearch.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif
#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef _DBAUI_MODULE_DBU_HXX_
#include "moduledbu.hxx"
#endif
#ifndef _CONNECTIVITY_PARSE_SQLITERATOR_HXX_
#include <connectivity/sqliterator.hxx>
#endif
#ifndef _CONNECTIVITY_DBTOOLS_HXX_
#include <connectivity/dbtools.hxx>
#endif
#ifndef _COMPHELPER_EXTRACT_HXX_
#include <comphelper/extract.hxx>
#endif
#ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_
#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
#endif

#ifndef TOOLS_DIAGNOSE_EX_H
#include <tools/diagnose_ex.h>
#endif

#include <algorithm>

using namespace dbaui;
using namespace connectivity;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::util;
using namespace ::com::sun::star::sdb;
using namespace ::com::sun::star::sdbc;
using namespace ::com::sun::star::sdbcx;
using namespace ::com::sun::star::beans;

DBG_NAME(DlgOrderCrit)
//------------------------------------------------------------------------------
DlgOrderCrit::DlgOrderCrit( Window * pParent,
                            const Reference< XConnection>& _rxConnection,
                            const Reference< XSingleSelectQueryComposer >& _rxComposer,
                            const Reference< XNameAccess>& _rxCols)
             :ModalDialog( pParent, ModuleRes(DLG_ORDERCRIT) )
            ,aLB_ORDERFIELD1(   this, ResId( LB_ORDERFIELD1 ) )
            ,aLB_ORDERVALUE1(   this, ResId( LB_ORDERVALUE1 ) )
            ,aLB_ORDERFIELD2(   this, ResId( LB_ORDERFIELD2 ) )
            ,aLB_ORDERVALUE2(   this, ResId( LB_ORDERVALUE2 ) )
            ,aLB_ORDERFIELD3(   this, ResId( LB_ORDERFIELD3 ) )
            ,aLB_ORDERVALUE3(   this, ResId( LB_ORDERVALUE3 ) )
            ,aFT_ORDERFIELD(    this, ResId( FT_ORDERFIELD ) )
            ,aFT_ORDERAFTER1(   this, ResId( FT_ORDERAFTER1 ) )
            ,aFT_ORDERAFTER2(   this, ResId( FT_ORDERAFTER2 ) )
            ,aFT_ORDEROPER(     this, ResId( FT_ORDEROPER ) )
            ,aFT_ORDERDIR(      this, ResId( FT_ORDERDIR ) )
            ,aBT_OK(            this, ResId( BT_OK ) )
            ,aBT_CANCEL(        this, ResId( BT_CANCEL ) )
            ,aBT_HELP(          this, ResId( BT_HELP ) )
            ,aFL_ORDER(         this, ResId( FL_ORDER ) )
            ,aSTR_NOENTRY(      ResId( STR_NOENTRY ) )
            ,m_xQueryComposer( _rxComposer )
            ,m_xColumns(_rxCols)
            ,m_xConnection(_rxConnection)
{
    DBG_CTOR(DlgOrderCrit,NULL);

    AllSettings aSettings( GetSettings() );
    StyleSettings aStyle( aSettings.GetStyleSettings() );
    aStyle.SetAutoMnemonic( FALSE );
    aSettings.SetStyleSettings( aStyle );
    SetSettings( aSettings );

    m_aColumnList[0] = &aLB_ORDERFIELD1;
    m_aColumnList[1] = &aLB_ORDERFIELD2;
    m_aColumnList[2] = &aLB_ORDERFIELD3;

    m_aValueList[0] = &aLB_ORDERVALUE1;
    m_aValueList[1] = &aLB_ORDERVALUE2;
    m_aValueList[2] = &aLB_ORDERVALUE3;

    xub_StrLen j;
    for(j=0 ; j < DOG_ROWS ; j++ )
    {
        m_aColumnList[j]->InsertEntry( aSTR_NOENTRY );
    }

    for( j=0 ; j < DOG_ROWS ; j++ )
    {
        m_aColumnList[j]->SelectEntryPos(0);
        m_aValueList[j]->SelectEntryPos(0);
    }
    try
    {
        // ... sowie auch die restlichen Felder
        Sequence< ::rtl::OUString> aNames = m_xColumns->getElementNames();
        const ::rtl::OUString* pIter = aNames.getConstArray();
        const ::rtl::OUString* pEnd   = pIter + aNames.getLength();
        Reference<XPropertySet> xColumn;
        for(;pIter != pEnd;++pIter)
        {
            xColumn.set(m_xColumns->getByName(*pIter),UNO_QUERY);
            OSL_ENSURE(xColumn.is(),"Column is null!");
            if ( xColumn.is() )
            {
                sal_Int32 nDataType;
                xColumn->getPropertyValue(PROPERTY_TYPE) >>= nDataType;
                sal_Int32 eColumnSearch = dbtools::getSearchColumnFlag(m_xConnection,nDataType);
                if(eColumnSearch != ColumnSearch::NONE)
                {
                    for( j=0 ; j < DOG_ROWS ; j++ )
                    {
                        m_aColumnList[j]->InsertEntry(*pIter);
                    }
                }
            }
        }

        m_sOrgOrder = m_xQueryComposer->getOrder();
        impl_initializeOrderList_nothrow();
    }
    catch(const Exception&)
    {
        OSL_ENSURE(0,"Exception catched while filling order lines!");
    }
    EnableLines();

    aLB_ORDERFIELD1.SetSelectHdl(LINK(this,DlgOrderCrit,FieldListSelectHdl));
    aLB_ORDERFIELD2.SetSelectHdl(LINK(this,DlgOrderCrit,FieldListSelectHdl));

    FreeResource();

}

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

#define LbText(x)       ((x).GetSelectEntry())
#define LbPos(x)        ((x).GetSelectEntryPos())

//------------------------------------------------------------------------------
DlgOrderCrit::~DlgOrderCrit()
{
    DBG_DTOR(DlgOrderCrit,NULL);
}

//------------------------------------------------------------------------------
IMPL_LINK_INLINE_START( DlgOrderCrit, FieldListSelectHdl, ListBox *, /*pListBox*/ )
{
    DBG_CHKTHIS(DlgOrderCrit,NULL);
    EnableLines();
    return 0;
}
IMPL_LINK_INLINE_END( DlgOrderCrit, FieldListSelectHdl, ListBox *, pListBox )

//------------------------------------------------------------------------------
void DlgOrderCrit::impl_initializeOrderList_nothrow()
{
    try
    {
        const ::rtl::OUString sNameProperty = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Name" ) );
        const ::rtl::OUString sAscendingProperty = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsAscending" ) );

        Reference< XIndexAccess > xOrderColumns( m_xQueryComposer->getOrderColumns(), UNO_QUERY_THROW );
        sal_Int32 nColumns = xOrderColumns->getCount();
        if ( nColumns > DOG_ROWS )
            nColumns = DOG_ROWS;

        for ( sal_Int32 i = 0; i < nColumns; ++i )
        {
            Reference< XPropertySet > xColumn( xOrderColumns->getByIndex( i ), UNO_QUERY_THROW );

            ::rtl::OUString sColumnName;
            sal_Bool        bIsAscending( sal_True );

            xColumn->getPropertyValue( sNameProperty ) >>= sColumnName;
            xColumn->getPropertyValue( sAscendingProperty ) >>= bIsAscending;

            m_aColumnList[i]->SelectEntry( sColumnName );
            m_aValueList[i]->SelectEntryPos( bIsAscending ? 0 : 1 );
        }
    }
    catch( const Exception& )
    {
        DBG_UNHANDLED_EXCEPTION();
    }
}

//------------------------------------------------------------------------------
void DlgOrderCrit::EnableLines()
{
    DBG_CHKTHIS(DlgOrderCrit,NULL);

    if ( aLB_ORDERFIELD1.GetSelectEntryPos() == 0 )
    {
        aLB_ORDERFIELD2.Disable();
        aLB_ORDERVALUE2.Disable();

        aLB_ORDERFIELD2.SelectEntryPos( 0 );
        aLB_ORDERVALUE2.SelectEntryPos( 0 );
    }
    else
    {
        aLB_ORDERFIELD2.Enable();
        aLB_ORDERVALUE2.Enable();
    }

    if ( aLB_ORDERFIELD2.GetSelectEntryPos() == 0 )
    {
        aLB_ORDERFIELD3.Disable();
        aLB_ORDERVALUE3.Disable();

        aLB_ORDERFIELD3.SelectEntryPos( 0 );
        aLB_ORDERVALUE3.SelectEntryPos( 0 );
    }
    else
    {
        aLB_ORDERFIELD3.Enable();
        aLB_ORDERVALUE3.Enable();
    }
}

//------------------------------------------------------------------------------
::rtl::OUString DlgOrderCrit::GetOrderList( ) const
{
    DBG_CHKTHIS(DlgOrderCrit,NULL);
    Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData();
    ::rtl::OUString sQuote  = xMetaData.is() ? xMetaData->getIdentifierQuoteString() : ::rtl::OUString();
    static const ::rtl::OUString sDESC = ::rtl::OUString::createFromAscii(" DESC ");
    static const ::rtl::OUString sASC  = ::rtl::OUString::createFromAscii(" ASC ");

    Reference< XNameAccess> xColumns = Reference< XColumnsSupplier >(m_xQueryComposer,UNO_QUERY)->getColumns();

    ::rtl::OUString sOrder;
    for( sal_uInt16 i=0 ; i<DOG_ROWS; i++ )
    {
        if(m_aColumnList[i]->GetSelectEntryPos() != 0)
        {
            if(sOrder.getLength())
                sOrder += ::rtl::OUString::createFromAscii(",");

            String sName = m_aColumnList[i]->GetSelectEntry();
            try
            {
                sal_Bool bFunction = sal_False;
                Reference< XPropertySet > xColumn;
                if ( xColumns.is() && xColumns->hasByName( sName ) && (xColumns->getByName( sName ) >>= xColumn) && xColumn.is() )
                {
                    if ( xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME) )
                    {
                        ::rtl::OUString sRealName;
                        xColumn->getPropertyValue(PROPERTY_REALNAME)    >>= sRealName;
                        sName = sRealName;
                        static ::rtl::OUString sAgg(RTL_CONSTASCII_USTRINGPARAM("AggregateFunction"));
                        static ::rtl::OUString sFunction(RTL_CONSTASCII_USTRINGPARAM("Function"));
                        if ( xColumn->getPropertySetInfo()->hasPropertyByName(sFunction) )
                            xColumn->getPropertyValue(sFunction) >>= bFunction;
                    }
                }
                if ( bFunction )
                    sOrder += sName;
                else
                    sOrder += ::dbtools::quoteName(sQuote,sName);
            }
            catch(Exception)
            {
            }
            if(m_aValueList[i]->GetSelectEntryPos())
                sOrder += sDESC;
            else
                sOrder += sASC;
        }
    }
    return sOrder;
}

//------------------------------------------------------------------------------
void DlgOrderCrit::BuildOrderPart()
{
    DBG_CHKTHIS(DlgOrderCrit,NULL);
    m_xQueryComposer->setOrder(GetOrderList());
}
// -----------------------------------------------------------------------------

<commit_msg>INTEGRATION: CWS pchfix02 (1.17.48); FILE MERGED 2006/09/01 17:24:30 kaib 1.17.48.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: queryorder.cxx,v $
 *
 *  $Revision: 1.18 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 07:11:34 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_dbaccess.hxx"
#ifndef DBAUI_QUERYORDER_HRC
#include "queryorder.hrc"
#endif
#ifndef DBAUI_QUERYORDER_HXX
#include "queryorder.hxx"
#endif

#ifndef DBACCESS_SHARED_DBUSTRINGS_HRC
#include "dbustrings.hrc"
#endif

#ifndef _COM_SUN_STAR_SDB_XSINGLESELECTQUERYCOMPOSER_HPP_
#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_COLUMNSEARCH_HPP_
#include <com/sun/star/sdbc/ColumnSearch.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif
#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef _DBAUI_MODULE_DBU_HXX_
#include "moduledbu.hxx"
#endif
#ifndef _CONNECTIVITY_PARSE_SQLITERATOR_HXX_
#include <connectivity/sqliterator.hxx>
#endif
#ifndef _CONNECTIVITY_DBTOOLS_HXX_
#include <connectivity/dbtools.hxx>
#endif
#ifndef _COMPHELPER_EXTRACT_HXX_
#include <comphelper/extract.hxx>
#endif
#ifndef _COM_SUN_STAR_SDBCX_XCOLUMNSSUPPLIER_HPP_
#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
#endif

#ifndef TOOLS_DIAGNOSE_EX_H
#include <tools/diagnose_ex.h>
#endif

#include <algorithm>

using namespace dbaui;
using namespace connectivity;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::util;
using namespace ::com::sun::star::sdb;
using namespace ::com::sun::star::sdbc;
using namespace ::com::sun::star::sdbcx;
using namespace ::com::sun::star::beans;

DBG_NAME(DlgOrderCrit)
//------------------------------------------------------------------------------
DlgOrderCrit::DlgOrderCrit( Window * pParent,
                            const Reference< XConnection>& _rxConnection,
                            const Reference< XSingleSelectQueryComposer >& _rxComposer,
                            const Reference< XNameAccess>& _rxCols)
             :ModalDialog( pParent, ModuleRes(DLG_ORDERCRIT) )
            ,aLB_ORDERFIELD1(   this, ResId( LB_ORDERFIELD1 ) )
            ,aLB_ORDERVALUE1(   this, ResId( LB_ORDERVALUE1 ) )
            ,aLB_ORDERFIELD2(   this, ResId( LB_ORDERFIELD2 ) )
            ,aLB_ORDERVALUE2(   this, ResId( LB_ORDERVALUE2 ) )
            ,aLB_ORDERFIELD3(   this, ResId( LB_ORDERFIELD3 ) )
            ,aLB_ORDERVALUE3(   this, ResId( LB_ORDERVALUE3 ) )
            ,aFT_ORDERFIELD(    this, ResId( FT_ORDERFIELD ) )
            ,aFT_ORDERAFTER1(   this, ResId( FT_ORDERAFTER1 ) )
            ,aFT_ORDERAFTER2(   this, ResId( FT_ORDERAFTER2 ) )
            ,aFT_ORDEROPER(     this, ResId( FT_ORDEROPER ) )
            ,aFT_ORDERDIR(      this, ResId( FT_ORDERDIR ) )
            ,aBT_OK(            this, ResId( BT_OK ) )
            ,aBT_CANCEL(        this, ResId( BT_CANCEL ) )
            ,aBT_HELP(          this, ResId( BT_HELP ) )
            ,aFL_ORDER(         this, ResId( FL_ORDER ) )
            ,aSTR_NOENTRY(      ResId( STR_NOENTRY ) )
            ,m_xQueryComposer( _rxComposer )
            ,m_xColumns(_rxCols)
            ,m_xConnection(_rxConnection)
{
    DBG_CTOR(DlgOrderCrit,NULL);

    AllSettings aSettings( GetSettings() );
    StyleSettings aStyle( aSettings.GetStyleSettings() );
    aStyle.SetAutoMnemonic( FALSE );
    aSettings.SetStyleSettings( aStyle );
    SetSettings( aSettings );

    m_aColumnList[0] = &aLB_ORDERFIELD1;
    m_aColumnList[1] = &aLB_ORDERFIELD2;
    m_aColumnList[2] = &aLB_ORDERFIELD3;

    m_aValueList[0] = &aLB_ORDERVALUE1;
    m_aValueList[1] = &aLB_ORDERVALUE2;
    m_aValueList[2] = &aLB_ORDERVALUE3;

    xub_StrLen j;
    for(j=0 ; j < DOG_ROWS ; j++ )
    {
        m_aColumnList[j]->InsertEntry( aSTR_NOENTRY );
    }

    for( j=0 ; j < DOG_ROWS ; j++ )
    {
        m_aColumnList[j]->SelectEntryPos(0);
        m_aValueList[j]->SelectEntryPos(0);
    }
    try
    {
        // ... sowie auch die restlichen Felder
        Sequence< ::rtl::OUString> aNames = m_xColumns->getElementNames();
        const ::rtl::OUString* pIter = aNames.getConstArray();
        const ::rtl::OUString* pEnd   = pIter + aNames.getLength();
        Reference<XPropertySet> xColumn;
        for(;pIter != pEnd;++pIter)
        {
            xColumn.set(m_xColumns->getByName(*pIter),UNO_QUERY);
            OSL_ENSURE(xColumn.is(),"Column is null!");
            if ( xColumn.is() )
            {
                sal_Int32 nDataType;
                xColumn->getPropertyValue(PROPERTY_TYPE) >>= nDataType;
                sal_Int32 eColumnSearch = dbtools::getSearchColumnFlag(m_xConnection,nDataType);
                if(eColumnSearch != ColumnSearch::NONE)
                {
                    for( j=0 ; j < DOG_ROWS ; j++ )
                    {
                        m_aColumnList[j]->InsertEntry(*pIter);
                    }
                }
            }
        }

        m_sOrgOrder = m_xQueryComposer->getOrder();
        impl_initializeOrderList_nothrow();
    }
    catch(const Exception&)
    {
        OSL_ENSURE(0,"Exception catched while filling order lines!");
    }
    EnableLines();

    aLB_ORDERFIELD1.SetSelectHdl(LINK(this,DlgOrderCrit,FieldListSelectHdl));
    aLB_ORDERFIELD2.SetSelectHdl(LINK(this,DlgOrderCrit,FieldListSelectHdl));

    FreeResource();

}

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

#define LbText(x)       ((x).GetSelectEntry())
#define LbPos(x)        ((x).GetSelectEntryPos())

//------------------------------------------------------------------------------
DlgOrderCrit::~DlgOrderCrit()
{
    DBG_DTOR(DlgOrderCrit,NULL);
}

//------------------------------------------------------------------------------
IMPL_LINK_INLINE_START( DlgOrderCrit, FieldListSelectHdl, ListBox *, /*pListBox*/ )
{
    DBG_CHKTHIS(DlgOrderCrit,NULL);
    EnableLines();
    return 0;
}
IMPL_LINK_INLINE_END( DlgOrderCrit, FieldListSelectHdl, ListBox *, pListBox )

//------------------------------------------------------------------------------
void DlgOrderCrit::impl_initializeOrderList_nothrow()
{
    try
    {
        const ::rtl::OUString sNameProperty = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Name" ) );
        const ::rtl::OUString sAscendingProperty = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsAscending" ) );

        Reference< XIndexAccess > xOrderColumns( m_xQueryComposer->getOrderColumns(), UNO_QUERY_THROW );
        sal_Int32 nColumns = xOrderColumns->getCount();
        if ( nColumns > DOG_ROWS )
            nColumns = DOG_ROWS;

        for ( sal_Int32 i = 0; i < nColumns; ++i )
        {
            Reference< XPropertySet > xColumn( xOrderColumns->getByIndex( i ), UNO_QUERY_THROW );

            ::rtl::OUString sColumnName;
            sal_Bool        bIsAscending( sal_True );

            xColumn->getPropertyValue( sNameProperty ) >>= sColumnName;
            xColumn->getPropertyValue( sAscendingProperty ) >>= bIsAscending;

            m_aColumnList[i]->SelectEntry( sColumnName );
            m_aValueList[i]->SelectEntryPos( bIsAscending ? 0 : 1 );
        }
    }
    catch( const Exception& )
    {
        DBG_UNHANDLED_EXCEPTION();
    }
}

//------------------------------------------------------------------------------
void DlgOrderCrit::EnableLines()
{
    DBG_CHKTHIS(DlgOrderCrit,NULL);

    if ( aLB_ORDERFIELD1.GetSelectEntryPos() == 0 )
    {
        aLB_ORDERFIELD2.Disable();
        aLB_ORDERVALUE2.Disable();

        aLB_ORDERFIELD2.SelectEntryPos( 0 );
        aLB_ORDERVALUE2.SelectEntryPos( 0 );
    }
    else
    {
        aLB_ORDERFIELD2.Enable();
        aLB_ORDERVALUE2.Enable();
    }

    if ( aLB_ORDERFIELD2.GetSelectEntryPos() == 0 )
    {
        aLB_ORDERFIELD3.Disable();
        aLB_ORDERVALUE3.Disable();

        aLB_ORDERFIELD3.SelectEntryPos( 0 );
        aLB_ORDERVALUE3.SelectEntryPos( 0 );
    }
    else
    {
        aLB_ORDERFIELD3.Enable();
        aLB_ORDERVALUE3.Enable();
    }
}

//------------------------------------------------------------------------------
::rtl::OUString DlgOrderCrit::GetOrderList( ) const
{
    DBG_CHKTHIS(DlgOrderCrit,NULL);
    Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData();
    ::rtl::OUString sQuote  = xMetaData.is() ? xMetaData->getIdentifierQuoteString() : ::rtl::OUString();
    static const ::rtl::OUString sDESC = ::rtl::OUString::createFromAscii(" DESC ");
    static const ::rtl::OUString sASC  = ::rtl::OUString::createFromAscii(" ASC ");

    Reference< XNameAccess> xColumns = Reference< XColumnsSupplier >(m_xQueryComposer,UNO_QUERY)->getColumns();

    ::rtl::OUString sOrder;
    for( sal_uInt16 i=0 ; i<DOG_ROWS; i++ )
    {
        if(m_aColumnList[i]->GetSelectEntryPos() != 0)
        {
            if(sOrder.getLength())
                sOrder += ::rtl::OUString::createFromAscii(",");

            String sName = m_aColumnList[i]->GetSelectEntry();
            try
            {
                sal_Bool bFunction = sal_False;
                Reference< XPropertySet > xColumn;
                if ( xColumns.is() && xColumns->hasByName( sName ) && (xColumns->getByName( sName ) >>= xColumn) && xColumn.is() )
                {
                    if ( xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME) )
                    {
                        ::rtl::OUString sRealName;
                        xColumn->getPropertyValue(PROPERTY_REALNAME)    >>= sRealName;
                        sName = sRealName;
                        static ::rtl::OUString sAgg(RTL_CONSTASCII_USTRINGPARAM("AggregateFunction"));
                        static ::rtl::OUString sFunction(RTL_CONSTASCII_USTRINGPARAM("Function"));
                        if ( xColumn->getPropertySetInfo()->hasPropertyByName(sFunction) )
                            xColumn->getPropertyValue(sFunction) >>= bFunction;
                    }
                }
                if ( bFunction )
                    sOrder += sName;
                else
                    sOrder += ::dbtools::quoteName(sQuote,sName);
            }
            catch(Exception)
            {
            }
            if(m_aValueList[i]->GetSelectEntryPos())
                sOrder += sDESC;
            else
                sOrder += sASC;
        }
    }
    return sOrder;
}

//------------------------------------------------------------------------------
void DlgOrderCrit::BuildOrderPart()
{
    DBG_CHKTHIS(DlgOrderCrit,NULL);
    m_xQueryComposer->setOrder(GetOrderList());
}
// -----------------------------------------------------------------------------

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

// HEADER
#include <dali/public-api/dali-core-version.h>

// EXTERNAL INCLUDES
#ifdef DEBUG_ENABLED
#include <iostream>
#endif

namespace Dali
{

const unsigned int CORE_MAJOR_VERSION = 1;
const unsigned int CORE_MINOR_VERSION = 1;
const unsigned int CORE_MICRO_VERSION = 17;
const char * const CORE_BUILD_DATE    = __DATE__ " " __TIME__;

#ifndef EMSCRIPTEN

#ifdef DEBUG_ENABLED
namespace
{
/// Allows the printing of the version number ONLY when debug is enabled
struct PrintVersion
{
  PrintVersion()
  {
    std::cout << "DALi Core:      " << CORE_MAJOR_VERSION << "." << CORE_MINOR_VERSION << "." << CORE_MICRO_VERSION << " (" << CORE_BUILD_DATE << ")" << std::endl;
  }
};
PrintVersion CORE_VERSION;
} // unnamed namespace
#endif

#endif // EMSCRIPTEN

} // namespace Dali
<commit_msg>Reporting dali version on stderr instead of stdout<commit_after>/*
 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

// HEADER
#include <dali/public-api/dali-core-version.h>

// EXTERNAL INCLUDES
#ifdef DEBUG_ENABLED
#include <iostream>
#endif

namespace Dali
{

const unsigned int CORE_MAJOR_VERSION = 1;
const unsigned int CORE_MINOR_VERSION = 1;
const unsigned int CORE_MICRO_VERSION = 17;
const char * const CORE_BUILD_DATE    = __DATE__ " " __TIME__;

#ifndef EMSCRIPTEN

#ifdef DEBUG_ENABLED
namespace
{
/// Allows the printing of the version number ONLY when debug is enabled
struct PrintVersion
{
  PrintVersion()
  {
    std::cerr << "DALi Core:      " << CORE_MAJOR_VERSION << "." << CORE_MINOR_VERSION << "." << CORE_MICRO_VERSION << " (" << CORE_BUILD_DATE << ")" << std::endl;
  }
};
PrintVersion CORE_VERSION;
} // unnamed namespace
#endif

#endif // EMSCRIPTEN

} // namespace Dali
<|endoftext|>


<commit_before>/*
 *  niinudge.cpp
 *
 *  Copyright (c) 2014 Tobias Wood.
 *
 *  This Source Code Form is subject to the terms of the Mozilla Public
 *  License, v. 2.0. If a copy of the MPL was not distributed with this
 *  file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 */

#include <iostream>
#include <sstream>
#include <string>
#include <getopt.h>

#include <Eigen/Core>
#include "Nifti/Nifti.h"
#include "QUIT/MultiArray.h"

using namespace std;
using namespace Eigen;
using namespace QUIT;

const string usage = "niinudge - A utility for moving Nifti images in physical space.\n\
\n\
Usage: niinudge [options] file1 [other files]\n\
By default nothing happens. Specify one of the options to move your image.\n\
Many of the options require a 3 dimensional vector argument. Valid formats for\n\
this are:\n\
X Y Z - Make sure you encase this format in quotes (\" \")!\n\
\n\
Options:\n\
	--out, -o prefix       : Add a prefix to the output filenames\n\
	--nudge, -n \"X Y Z\"  : Nudge the image (X Y Z added to current offset)\n\
	--offset, -f \"X Y Z\" : Set the offset to (X,Y,Z)\n\
	--cog, -c              : Move the Center of Gravity to the origin of the\n\
	                         first image, and make subsequent images match\n\
	--verbose, -v          : Print out what the program is doing\n\
	-h, --help:   Print this message and quit.\n\
";

static const struct option long_opts[] = {
	{"nudge",  required_argument, 0, 'n'},
	{"out", required_argument, 0, 'o'},
	{"offset", required_argument, 0, 'f'},
	{"cog",    no_argument, 0, 'c'},
	{"verbose", no_argument, 0, 'v'},
	{"help",   no_argument, 0, 'h'},
	{0, 0, 0, 0}
};
static const char *short_opts = "n:o:f:cvh";
static string prefix;
static int verbose = false;

Vector3f parse_vector(char *str);
Vector3f parse_vector(char *str) {
	istringstream is(str);
	Vector3f vec;
	is >> vec[0] >> vec[1] >> vec[2];
	return vec;
}

Vector3f calc_cog(Nifti::File &f);
Vector3f calc_cog(Nifti::File &f) {
	const auto dims = f.matrix();
	MultiArray<float, 3> a(dims);
	f.open(f.imagePath(), Nifti::Mode::Read);
	f.readVolumes(a.begin(), a.end(), 0, 1);

	Vector3f cog = Vector3f::Zero();
	float mass = 0.;
	for (size_t k = 0; k < dims[2]; k++) {
		for (size_t j = 0; j < dims[1]; j++) {
			for (size_t i = 0; i < dims[0]; i++) {
				float val = a[{i,j,k}];
				if (isfinite(val)) {
					cog += val * Vector3f(i,j,k);
					mass += val;
				}
			}
		}
	}
	cog /= mass;
	if (verbose) cout << "CoG in voxels: " << cog.transpose() << ", mass: " << mass << endl;
	cog = f.header().transform() * cog;
	if (verbose) cout << "CoG in space:  " << cog.transpose() << endl;
	f.close();
	return cog;
}

int main(int argc, char **argv) {
	// Make a first pass to permute the options and get filenames at the end
	int indexptr = 0, c;
	while ((c = getopt_long(argc, argv, short_opts, long_opts, &indexptr)) != -1) {
		switch (c) {
		case 'o': prefix = optarg; break;
		case 'v': verbose = true; break;
		case '?': // getopt will print an error message
		case 'h':
			cout << usage << endl;
			return EXIT_FAILURE;
		default:
			break;
		}
	}
	if ((argc - optind) <= 0 ) {
		cerr << "No input image file specified." << endl;
		cout << usage << endl;
		return EXIT_FAILURE;
	}
	vector<Nifti::File> files;
	vector<vector<char>> data;
	files.reserve(argc - optind);
	data.reserve(argc - optind);
	while (optind < argc) {
		files.emplace_back(Nifti::File(argv[optind++], Nifti::Mode::Read));
		Nifti::File &f = files.back();
		if (verbose) cout << "Opened file: " << f.imagePath() << endl;
		data.emplace_back(vector<char>(f.dataSize()));
		f.readBytes(data.back());
		f.close();
	}
	optind = 1;
	while ((c = getopt_long(argc, argv, short_opts, long_opts, &indexptr)) != -1) {
		Vector3f nudge;
		switch (c) {
		case 'n':
			nudge = parse_vector(optarg);
			for (Nifti::File &f : files) {
				if (verbose) cout << "Nudging offset by: " << nudge.transpose() << " in file: " << f.imagePath() << endl;
				Nifti::Header h = f.header();
				Affine3f xfm = h.transform();
				xfm = Translation3f(nudge) * xfm;
				h.setTransform(xfm);
				f.setHeader(h);
			}
			break;
		case 'f':
			nudge = parse_vector(optarg);
			for (Nifti::File &f : files) {
				if (verbose) cout << "Setting offset to: " << nudge.transpose() << " in file: " << f.imagePath() << endl;
				Nifti::Header h = f.header();
				Affine3f xfm = h.transform();
				xfm.translation() = nudge;
				h.setTransform(xfm);
				f.setHeader(h);
			}
			break;
		case 'c': {
			if (verbose) cout << "Aligning origin to CoG in file: " << files.front().imagePath() << endl;
			Vector3f CoG = calc_cog(files.front());
			Affine3f xfm1 = files.front().header().transform();
			xfm1 = Translation3f(-CoG) * xfm1;
			Vector3f offset = xfm1.translation();
			for (Nifti::File &f : files) {
				Nifti::Header h = f.header();
				Affine3f xfm = h.transform();
				xfm.translation() = offset;
				h.setTransform(xfm);
				f.setHeader(h);
			}
		} break;
		case '?': // getopt will print an error message
		case 'h':
			break;
		default:
			break;
		}
	}
	auto f = files.begin();
	auto d = data.begin();
	for (; f != files.end(); f++, d++) {
		string outpath = prefix + f->imagePath();
		if (verbose) cout << "Writing file: " << outpath << endl;
		f->open(outpath, Nifti::Mode::Write);
		f->writeBytes(*d);
		f->close();
	}

	return EXIT_SUCCESS;
}

<commit_msg>Added output in Insight format.<commit_after>/*
 *  niinudge.cpp
 *
 *  Copyright (c) 2014 Tobias Wood.
 *
 *  This Source Code Form is subject to the terms of the Mozilla Public
 *  License, v. 2.0. If a copy of the MPL was not distributed with this
 *  file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 */

#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <getopt.h>

#include <Eigen/Core>
#include "Nifti/Nifti.h"
#include "QUIT/MultiArray.h"

using namespace std;
using namespace Eigen;
using namespace QUIT;

const string usage = "niinudge - A utility for moving Nifti images in physical space.\n\
\n\
Usage: niinudge [options] file1 [other files]\n\
By default nothing happens. Specify one of the options to move your image.\n\
Many of the options require a 3 dimensional vector argument. Valid formats for\n\
this are:\n\
X Y Z - Make sure you encase this format in quotes (\" \")!\n\
\n\
Options:\n\
	--tfm, -t              : Output an Insight Transform file for ANTs\n\
	--out, -o prefix       : Add a prefix to the output filenames\n\
	--nudge, -n \"X Y Z\"  : Nudge the image (X Y Z added to current offset)\n\
	--offset, -f \"X Y Z\" : Set the offset to (X,Y,Z)\n\
	--cog, -c              : Move the Center of Gravity to the origin of the\n\
	                         first image, and make subsequent images match\n\
	--verbose, -v          : Print out what the program is doing\n\
	-h, --help:   Print this message and quit.\n\
";

static const struct option long_opts[] = {
	{"tfm", no_argument, 0, 't'},
	{"nudge",  required_argument, 0, 'n'},
	{"out", required_argument, 0, 'o'},
	{"offset", required_argument, 0, 'f'},
	{"cog",    no_argument, 0, 'c'},
	{"verbose", no_argument, 0, 'v'},
	{"help",   no_argument, 0, 'h'},
	{0, 0, 0, 0}
};
static const char *short_opts = "tn:o:f:cvh";
static string prefix;
static int verbose = false, output_transform = false;

Vector3f parse_vector(char *str);
Vector3f parse_vector(char *str) {
	istringstream is(str);
	Vector3f vec;
	is >> vec[0] >> vec[1] >> vec[2];
	return vec;
}

Vector3f calc_cog(Nifti::File &f);
Vector3f calc_cog(Nifti::File &f) {
	const auto dims = f.matrix();
	MultiArray<float, 3> a(dims);
	f.open(f.imagePath(), Nifti::Mode::Read);
	f.readVolumes(a.begin(), a.end(), 0, 1);

	Vector3f cog = Vector3f::Zero();
	float mass = 0.;
	for (size_t k = 0; k < dims[2]; k++) {
		for (size_t j = 0; j < dims[1]; j++) {
			for (size_t i = 0; i < dims[0]; i++) {
				float val = a[{i,j,k}];
				if (isfinite(val)) {
					cog += val * Vector3f(i,j,k);
					mass += val;
				}
			}
		}
	}
	cog /= mass;
	if (verbose) cout << "CoG in voxels: " << cog.transpose() << ", mass: " << mass << endl;
	cog = f.header().transform() * cog;
	if (verbose) cout << "CoG in space:  " << cog.transpose() << endl;
	f.close();
	return cog;
}

void write_transform(const Affine3f &tfm, const string path);
void write_transform(const Affine3f &tfm, const string path){
	ofstream file(path);

	IOFormat fmt(StreamPrecision, DontAlignCols);
	file << "#Insight Transform File V1.0" << endl;
	file << "# Transform 0" << endl;
	file << "Transform: MatrixOffsetTransformBase_double_3_3" << endl;
	file << "Parameters: " << tfm.matrix().block<1,3>(0,0).format(fmt)
	     << " " << tfm.matrix().block<1,3>(1,0).format(fmt)
	     << " " << tfm.matrix().block<1,3>(2,0).format(fmt)
	     << " " << tfm.translation().matrix().transpose().format(fmt) << endl;
	file << "FixedParameters: 0 0 0" << endl;
	file.close();
}

int main(int argc, char **argv) {
	// Make a first pass to permute the options and get filenames at the end
	int indexptr = 0, c;
	while ((c = getopt_long(argc, argv, short_opts, long_opts, &indexptr)) != -1) {
		switch (c) {
		case 't': output_transform = true; break;
		case 'o': prefix = optarg; break;
		case 'v': verbose = true; break;
		case '?': // getopt will print an error message
		case 'h':
			cout << usage << endl;
			return EXIT_FAILURE;
		default:
			break;
		}
	}
	if ((argc - optind) <= 0 ) {
		cerr << "No input image file specified." << endl;
		cout << usage << endl;
		return EXIT_FAILURE;
	}
	vector<Nifti::File> files;
	vector<vector<char>> data;
	files.reserve(argc - optind);
	data.reserve(argc - optind);
	while (optind < argc) {
		files.emplace_back(Nifti::File(argv[optind++], Nifti::Mode::Read));
		Nifti::File &f = files.back();
		if (verbose) cout << "Opened file: " << f.imagePath() << endl;
		data.emplace_back(vector<char>(f.dataSize()));
		f.readBytes(data.back());
		f.close();
	}
	optind = 1;
	while ((c = getopt_long(argc, argv, short_opts, long_opts, &indexptr)) != -1) {
		Vector3f nudge;
		switch (c) {
		case 'n':
			nudge = parse_vector(optarg);
			for (Nifti::File &f : files) {
				if (verbose) cout << "Nudging offset by: " << nudge.transpose() << " in file: " << f.imagePath() << endl;
				Nifti::Header h = f.header();
				Affine3f xfm = h.transform();
				xfm = Translation3f(nudge) * xfm;
				h.setTransform(xfm);
				f.setHeader(h);
			}
			break;
		case 'f':
			nudge = parse_vector(optarg);
			for (Nifti::File &f : files) {
				if (verbose) cout << "Setting offset to: " << nudge.transpose() << " in file: " << f.imagePath() << endl;
				Nifti::Header h = f.header();
				Affine3f xfm = h.transform();
				xfm.translation() = nudge;
				h.setTransform(xfm);
				f.setHeader(h);
			}
			break;
		case 'c': {
			if (verbose) cout << "Aligning origin to CoG in file: " << files.front().imagePath() << endl;
			Vector3f CoG = calc_cog(files.front());
			if (output_transform) {
				Affine3f tfm(Translation3f(-CoG));
				write_transform(tfm, files.front().basePath()+".tfm");
			} else {
				Affine3f xfm1 = files.front().header().transform();
				xfm1 = Translation3f(-CoG) * xfm1;
				Vector3f offset = xfm1.translation();
				for (Nifti::File &f : files) {
					Nifti::Header h = f.header();
					Affine3f xfm = h.transform();
					xfm.translation() = offset;
					h.setTransform(xfm);
					f.setHeader(h);
				}
			}
		} break;
		case '?': // getopt will print an error message
		case 'h':
			break;
		default:
			break;
		}
	}
	auto f = files.begin();
	auto d = data.begin();
	for (; f != files.end(); f++, d++) {
		string outpath = prefix + f->imagePath();
		if (verbose) cout << "Writing file: " << outpath << endl;
		f->open(outpath, Nifti::Mode::Write);
		f->writeBytes(*d);
		f->close();
	}

	return EXIT_SUCCESS;
}

<|endoftext|>