<commit_before>/*
Copyright libCellML Contributors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include "libcellml/analysermodel.h"

#include <algorithm>

#include "libcellml/variable.h"

#include "analysermodel_p.h"

namespace libcellml {

bool AnalyserModel::AnalyserModelImpl::haveEquivalentVariables(const Variable *variable1,
                                                               const Variable *variable2,
                                                               std::vector<const Variable *> &testedVariables)
{
    if (variable1 == variable2) {
        return true;
    }

    testedVariables.push_back(variable2);

    auto testedVariablesBegin = testedVariables.begin();
    auto testedVariablesEnd = testedVariables.end();

    for (size_t i = 0; i < variable2->equivalentVariableCount(); ++i) {
        Variable *equivalentVariable2 = variable2->equivalentVariable(i).get();

        if ((std::find(testedVariablesBegin, testedVariablesEnd, equivalentVariable2) == testedVariablesEnd)
            && haveEquivalentVariables(variable1, equivalentVariable2, testedVariables)) {
            return true;
        }
    }

    return false;
}

AnalyserModel::AnalyserModel()
    : mPimpl(new AnalyserModelImpl())
{
}

AnalyserModel::~AnalyserModel()
{
    delete mPimpl;
}

bool AnalyserModel::isValid() const
{
    return (mPimpl->mType == AnalyserModel::Type::ALGEBRAIC)
           || (mPimpl->mType == AnalyserModel::Type::ODE);
}

AnalyserModel::Type AnalyserModel::type() const
{
    return mPimpl->mType;
}

AnalyserVariablePtr AnalyserModel::voi() const
{
    if (!isValid()) {
        return {};
    }

    return mPimpl->mVoi;
}

size_t AnalyserModel::stateCount() const
{
    if (!isValid()) {
        return 0;
    }

    return mPimpl->mStates.size();
}

std::vector<AnalyserVariablePtr> AnalyserModel::states() const
{
    if (!isValid()) {
        return {};
    }

    return mPimpl->mStates;
}

AnalyserVariablePtr AnalyserModel::state(size_t index) const
{
    if (!isValid()
        || (index >= mPimpl->mStates.size())) {
        return {};
    }

    return mPimpl->mStates[index];
}

size_t AnalyserModel::variableCount() const
{
    if (!isValid()) {
        return 0;
    }

    return mPimpl->mVariables.size();
}

std::vector<AnalyserVariablePtr> AnalyserModel::variables() const
{
    if (!isValid()) {
        return {};
    }

    return mPimpl->mVariables;
}

AnalyserVariablePtr AnalyserModel::variable(size_t index) const
{
    if (!isValid() || (index >= mPimpl->mVariables.size())) {
        return {};
    }

    return mPimpl->mVariables[index];
}

size_t AnalyserModel::equationCount() const
{
    if (!isValid()) {
        return 0;
    }

    return mPimpl->mEquations.size();
}

std::vector<AnalyserEquationPtr> AnalyserModel::equations() const
{
    if (!isValid()) {
        return {};
    }

    return mPimpl->mEquations;
}

AnalyserEquationPtr AnalyserModel::equation(size_t index) const
{
    if (!isValid() || (index >= mPimpl->mEquations.size())) {
        return {};
    }

    return mPimpl->mEquations[index];
}

bool AnalyserModel::needEqFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedEqFunction;
}

bool AnalyserModel::needNeqFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedNeqFunction;
}

bool AnalyserModel::needLtFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedLtFunction;
}

bool AnalyserModel::needLeqFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedLeqFunction;
}

bool AnalyserModel::needGtFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedGtFunction;
}

bool AnalyserModel::needGeqFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedGeqFunction;
}

bool AnalyserModel::needAndFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAndFunction;
}

bool AnalyserModel::needOrFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedOrFunction;
}

bool AnalyserModel::needXorFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedXorFunction;
}

bool AnalyserModel::needNotFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedNotFunction;
}

bool AnalyserModel::needMinFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedMinFunction;
}

bool AnalyserModel::needMaxFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedMaxFunction;
}

bool AnalyserModel::needSecFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedSecFunction;
}

bool AnalyserModel::needCscFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedCscFunction;
}

bool AnalyserModel::needCotFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedCotFunction;
}

bool AnalyserModel::needSechFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedSechFunction;
}

bool AnalyserModel::needCschFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedCschFunction;
}

bool AnalyserModel::needCothFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedCothFunction;
}

bool AnalyserModel::needAsecFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAsecFunction;
}

bool AnalyserModel::needAcscFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAcscFunction;
}

bool AnalyserModel::needAcotFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAcotFunction;
}

bool AnalyserModel::needAsechFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAsechFunction;
}

bool AnalyserModel::needAcschFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAcschFunction;
}

bool AnalyserModel::needAcothFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAcothFunction;
}

bool AnalyserModel::areEquivalentVariables(const VariablePtr &variable1,
                                           const VariablePtr &variable2)
{
    if (variable1 == variable2) {
        return true;
    }

    auto key = reinterpret_cast<intptr_t>(variable1.get()) * reinterpret_cast<intptr_t>(variable2.get());
    auto cacheKey = mPimpl->mCachedEquivalentVariables.find(key);

    if (cacheKey != mPimpl->mCachedEquivalentVariables.end()) {
        return cacheKey->second;
    }

    std::vector<const Variable *> testedVariables;
    bool res = mPimpl->haveEquivalentVariables(variable1.get(), variable2.get(), testedVariables);

    mPimpl->mCachedEquivalentVariables[key] = res;

    return res;
}

} // namespace libcellml
<commit_msg>AnalyserModel: added some background information to the `areEquivalentVariables()` method.<commit_after>/*
Copyright libCellML Contributors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#include "libcellml/analysermodel.h"

#include <algorithm>

#include "libcellml/variable.h"

#include "analysermodel_p.h"

namespace libcellml {

bool AnalyserModel::AnalyserModelImpl::haveEquivalentVariables(const Variable *variable1,
                                                               const Variable *variable2,
                                                               std::vector<const Variable *> &testedVariables)
{
    if (variable1 == variable2) {
        return true;
    }

    testedVariables.push_back(variable2);

    auto testedVariablesBegin = testedVariables.begin();
    auto testedVariablesEnd = testedVariables.end();

    for (size_t i = 0; i < variable2->equivalentVariableCount(); ++i) {
        Variable *equivalentVariable2 = variable2->equivalentVariable(i).get();

        if ((std::find(testedVariablesBegin, testedVariablesEnd, equivalentVariable2) == testedVariablesEnd)
            && haveEquivalentVariables(variable1, equivalentVariable2, testedVariables)) {
            return true;
        }
    }

    return false;
}

AnalyserModel::AnalyserModel()
    : mPimpl(new AnalyserModelImpl())
{
}

AnalyserModel::~AnalyserModel()
{
    delete mPimpl;
}

bool AnalyserModel::isValid() const
{
    return (mPimpl->mType == AnalyserModel::Type::ALGEBRAIC)
           || (mPimpl->mType == AnalyserModel::Type::ODE);
}

AnalyserModel::Type AnalyserModel::type() const
{
    return mPimpl->mType;
}

AnalyserVariablePtr AnalyserModel::voi() const
{
    if (!isValid()) {
        return {};
    }

    return mPimpl->mVoi;
}

size_t AnalyserModel::stateCount() const
{
    if (!isValid()) {
        return 0;
    }

    return mPimpl->mStates.size();
}

std::vector<AnalyserVariablePtr> AnalyserModel::states() const
{
    if (!isValid()) {
        return {};
    }

    return mPimpl->mStates;
}

AnalyserVariablePtr AnalyserModel::state(size_t index) const
{
    if (!isValid()
        || (index >= mPimpl->mStates.size())) {
        return {};
    }

    return mPimpl->mStates[index];
}

size_t AnalyserModel::variableCount() const
{
    if (!isValid()) {
        return 0;
    }

    return mPimpl->mVariables.size();
}

std::vector<AnalyserVariablePtr> AnalyserModel::variables() const
{
    if (!isValid()) {
        return {};
    }

    return mPimpl->mVariables;
}

AnalyserVariablePtr AnalyserModel::variable(size_t index) const
{
    if (!isValid() || (index >= mPimpl->mVariables.size())) {
        return {};
    }

    return mPimpl->mVariables[index];
}

size_t AnalyserModel::equationCount() const
{
    if (!isValid()) {
        return 0;
    }

    return mPimpl->mEquations.size();
}

std::vector<AnalyserEquationPtr> AnalyserModel::equations() const
{
    if (!isValid()) {
        return {};
    }

    return mPimpl->mEquations;
}

AnalyserEquationPtr AnalyserModel::equation(size_t index) const
{
    if (!isValid() || (index >= mPimpl->mEquations.size())) {
        return {};
    }

    return mPimpl->mEquations[index];
}

bool AnalyserModel::needEqFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedEqFunction;
}

bool AnalyserModel::needNeqFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedNeqFunction;
}

bool AnalyserModel::needLtFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedLtFunction;
}

bool AnalyserModel::needLeqFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedLeqFunction;
}

bool AnalyserModel::needGtFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedGtFunction;
}

bool AnalyserModel::needGeqFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedGeqFunction;
}

bool AnalyserModel::needAndFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAndFunction;
}

bool AnalyserModel::needOrFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedOrFunction;
}

bool AnalyserModel::needXorFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedXorFunction;
}

bool AnalyserModel::needNotFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedNotFunction;
}

bool AnalyserModel::needMinFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedMinFunction;
}

bool AnalyserModel::needMaxFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedMaxFunction;
}

bool AnalyserModel::needSecFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedSecFunction;
}

bool AnalyserModel::needCscFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedCscFunction;
}

bool AnalyserModel::needCotFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedCotFunction;
}

bool AnalyserModel::needSechFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedSechFunction;
}

bool AnalyserModel::needCschFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedCschFunction;
}

bool AnalyserModel::needCothFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedCothFunction;
}

bool AnalyserModel::needAsecFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAsecFunction;
}

bool AnalyserModel::needAcscFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAcscFunction;
}

bool AnalyserModel::needAcotFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAcotFunction;
}

bool AnalyserModel::needAsechFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAsechFunction;
}

bool AnalyserModel::needAcschFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAcschFunction;
}

bool AnalyserModel::needAcothFunction() const
{
    if (!isValid()) {
        return false;
    }

    return mPimpl->mNeedAcothFunction;
}

bool AnalyserModel::areEquivalentVariables(const VariablePtr &variable1,
                                           const VariablePtr &variable2)
{
    // We used to have a utilities method which implementation was:
    //
    //     return (variable1 == variable2)
    //            || variable1->hasEquivalentVariable(variable2, true);
    //
    // However, a call to Variable::hasEquivalentVariable() can be time
    // consuming. So, here, we stripped down the implementation of that method
    // (and of others that it calls) and cache its results for future re-use.

    if (variable1 == variable2) {
        return true;
    }

    auto key = reinterpret_cast<intptr_t>(variable1.get()) * reinterpret_cast<intptr_t>(variable2.get());
    auto cacheKey = mPimpl->mCachedEquivalentVariables.find(key);

    if (cacheKey != mPimpl->mCachedEquivalentVariables.end()) {
        return cacheKey->second;
    }

    std::vector<const Variable *> testedVariables;
    bool res = mPimpl->haveEquivalentVariables(variable1.get(), variable2.get(), testedVariables);

    mPimpl->mCachedEquivalentVariables[key] = res;

    return res;
}

} // namespace libcellml
<|endoftext|>


<commit_before>// Copyright (c) 2009-2011 Satoshi Nakamoto & Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.

#include "headers.h"
#include "db.h"

//////////////////////////////////////////////////////////////////////////////
//
// mapKeys
//

std::vector<unsigned char> CKeyStore::GenerateNewKey()
{
    RandAddSeedPerfmon();
    CKey key;
    key.MakeNewKey();
    if (!AddKey(key))
        throw std::runtime_error("GenerateNewKey() : AddKey failed");
    return key.GetPubKey();
}

bool CKeyStore::AddKey(const CKey& key)
{
    CRITICAL_BLOCK(cs_mapKeys)
    {
        mapKeys[key.GetPubKey()] = key.GetPrivKey();
        mapPubKeys[Hash160(key.GetPubKey())] = key.GetPubKey();
    }
}

<commit_msg>CKeyStore::AddKey must return a boolean<commit_after>// Copyright (c) 2009-2011 Satoshi Nakamoto & Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.

#include "headers.h"
#include "db.h"

//////////////////////////////////////////////////////////////////////////////
//
// mapKeys
//

std::vector<unsigned char> CKeyStore::GenerateNewKey()
{
    RandAddSeedPerfmon();
    CKey key;
    key.MakeNewKey();
    if (!AddKey(key))
        throw std::runtime_error("GenerateNewKey() : AddKey failed");
    return key.GetPubKey();
}

bool CKeyStore::AddKey(const CKey& key)
{
    CRITICAL_BLOCK(cs_mapKeys)
    {
        mapKeys[key.GetPubKey()] = key.GetPrivKey();
        mapPubKeys[Hash160(key.GetPubKey())] = key.GetPubKey();
    }
    return true;
}

<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_filter.hxx"

#include <vcl/graph.hxx>
#include <vcl/bmpacc.hxx>
#include <svtools/fltcall.hxx>
#include <svtools/FilterConfigItem.hxx>

//============================ RASWriter ==================================

class RASWriter {

private:

    SvStream*           mpOStm;
    USHORT              mpOStmOldModus;

    BOOL                mbStatus;
    BitmapReadAccess*   mpAcc;

    ULONG               mnWidth, mnHeight;
    USHORT              mnColors, mnDepth;

    ULONG               mnRepCount;
    BYTE                mnRepVal;

    com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator > xStatusIndicator;

    void                ImplCallback( ULONG nCurrentYPos );
    BOOL                ImplWriteHeader();
    void                ImplWritePalette();
    void                ImplWriteBody();
    void                ImplPutByte( BYTE );    // RLE decoding

public:
                        RASWriter();
                        ~RASWriter();

    BOOL                WriteRAS( const Graphic& rGraphic, SvStream& rRAS, FilterConfigItem* pFilterConfigItem );
};

//=================== Methoden von RASWriter ==============================

RASWriter::RASWriter() :
    mbStatus    ( TRUE ),
    mpAcc       ( NULL ),
    mnRepCount  ( 0xffffffff )
{
}

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

RASWriter::~RASWriter()
{
}

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

void RASWriter::ImplCallback( ULONG nYPos )
{
    if ( xStatusIndicator.is() )
        xStatusIndicator->setValue( (USHORT)( ( 100 * nYPos ) / mnHeight ) );
}

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

BOOL RASWriter::WriteRAS( const Graphic& rGraphic, SvStream& rRAS, FilterConfigItem* pFilterConfigItem)
{
    Bitmap  aBmp;

    mpOStm = &rRAS;

    if ( pFilterConfigItem )
    {
        xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
        if ( xStatusIndicator.is() )
        {
            rtl::OUString aMsg;
            xStatusIndicator->start( aMsg, 100 );
        }
    }

    BitmapEx    aBmpEx( rGraphic.GetBitmapEx() );
    aBmp = aBmpEx.GetBitmap();

    if ( aBmp.GetBitCount() == 4 )
        aBmp.Convert( BMP_CONVERSION_8BIT_COLORS );

    mnDepth = aBmp.GetBitCount();

    // export code below only handles three discrete cases
    mnDepth = mnDepth <= 1 ? 1 : mnDepth <= 8 ? 8 : 24;

    mpAcc = aBmp.AcquireReadAccess();
    if ( mpAcc )
    {
        mpOStmOldModus = mpOStm->GetNumberFormatInt();
        mpOStm->SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );

        if ( ImplWriteHeader() )
        {
            if ( mnDepth <= 8 )
                ImplWritePalette();
            ImplWriteBody();
        }
        aBmp.ReleaseAccess( mpAcc );
    }
    else
        mbStatus = FALSE;

    mpOStm->SetNumberFormatInt( mpOStmOldModus );

    if ( xStatusIndicator.is() )
        xStatusIndicator->end();

    return mbStatus;
}

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

BOOL RASWriter::ImplWriteHeader()
{
    mnWidth = mpAcc->Width();
    mnHeight = mpAcc->Height();
    if ( mnDepth <= 8 )
    {
        mnColors = mpAcc->GetPaletteEntryCount();
        if (mnColors == 0)
            mbStatus = FALSE;
    }
        if ( mbStatus && mnWidth && mnHeight && mnDepth )
    {
        *mpOStm << (UINT32)0x59a66a95 << (UINT32)mnWidth << (UINT32)mnHeight
            << (UINT32)mnDepth
            << (UINT32)(( ( ( ( mnWidth * mnDepth ) + 15 ) >> 4 ) << 1 ) * mnHeight)
            << (UINT32)2;

        if ( mnDepth > 8 )
            *mpOStm << (UINT32)0 << (UINT32)0;
        else
        {

            *mpOStm << (UINT32)1 << (UINT32)( mnColors * 3 );
        }
    }
    else mbStatus = FALSE;

    return mbStatus;
}

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

void RASWriter::ImplWritePalette()
{
    USHORT i;

    for ( i = 0; i < mnColors; *mpOStm << mpAcc->GetPaletteColor( i++ ).GetRed() ) ;
    for ( i = 0; i < mnColors; *mpOStm << mpAcc->GetPaletteColor( i++ ).GetGreen() ) ;
    for ( i = 0; i < mnColors; *mpOStm << mpAcc->GetPaletteColor( i++ ).GetBlue() ) ;
}

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

void RASWriter::ImplWriteBody()
{
    ULONG   x, y;

    if ( mnDepth == 24 )
    {
        for ( y = 0; y < mnHeight; y++ )
        {
            ImplCallback( y );                              // processing output
            for ( x = 0; x < mnWidth; x++ )
            {
                BitmapColor aColor( mpAcc->GetPixel( y, x ) );
                ImplPutByte( aColor.GetBlue() );            // Format ist BGR
                ImplPutByte( aColor.GetGreen() );
                ImplPutByte( aColor.GetRed() );
            }
            if ( x & 1 ) ImplPutByte( 0 );      // WORD ALIGNMENT ???
        }
    }
    else if ( mnDepth == 8 )
    {
        for ( y = 0; y < mnHeight; y++ )
        {
            ImplCallback( y );                              // processing output
            for ( x = 0; x < mnWidth; x++ )
            {
                ImplPutByte ( mpAcc->GetPixel( y, x ) );
            }
            if ( x & 1 ) ImplPutByte( 0 );      // WORD ALIGNMENT ???
        }
    }
    else if ( mnDepth == 1 )
    {
        BYTE nDat = 0;

        for ( y = 0; y < mnHeight; y++ )
        {
            ImplCallback( y );                              // processing output
            for ( x = 0; x < mnWidth; x++ )
            {
                nDat = ( ( nDat << 1 ) | ( mpAcc->GetPixel ( y, x ) & 1 ) );
                if ( ( x & 7 ) == 7 )
                    ImplPutByte( nDat );
            }
            if ( x & 7 )
                ImplPutByte( sal::static_int_cast< BYTE >(nDat << ( ( ( x & 7 ) ^ 7 ) + 1)) );// write remaining bits
            if (!( ( x - 1 ) & 0x8 ) )
                ImplPutByte( 0 );               // WORD ALIGNMENT ???
        }
    }
    ImplPutByte( mnRepVal + 1 );    // end of RLE decoding
}

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

void RASWriter::ImplPutByte( BYTE nPutThis )
{
    if ( mnRepCount == 0xffffffff )
    {
        mnRepCount = 0;
        mnRepVal = nPutThis;
    }
    else
    {
        if ( ( nPutThis == mnRepVal ) && ( mnRepCount != 0xff ) )
            mnRepCount++;
        else
        {
            if ( mnRepCount == 0 )
            {
                *mpOStm << (BYTE)mnRepVal;
                if ( mnRepVal == 0x80 )
                    *mpOStm << (BYTE)0;
            }
            else
            {
                *mpOStm << (BYTE)0x80;
                *mpOStm << (BYTE)mnRepCount;
                *mpOStm << (BYTE)mnRepVal;
            }
            mnRepVal = nPutThis;
            mnRepCount = 0;
        }
    }
}

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

// ---------------------
// - exported function -
// ---------------------

extern "C" BOOL __LOADONCALLAPI GraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pFilterConfigItem, BOOL )
{
    RASWriter aRASWriter;

    return aRASWriter.WriteRAS( rGraphic, rStream, pFilterConfigItem );
}

// ---------------
// - Win16 trash -
// ---------------

#ifdef WIN

static HINSTANCE hDLLInst = 0;

extern "C" int CALLBACK LibMain( HINSTANCE hDLL, WORD, WORD nHeap, LPSTR )
{
    if ( nHeap )
        UnlockData( 0 );

    hDLLInst = hDLL;

    return TRUE;
}

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

extern "C" int CALLBACK WEP( int )
{
    return 1;
}

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>no need for the pointer fetishism<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_filter.hxx"

#include <vcl/graph.hxx>
#include <vcl/bmpacc.hxx>
#include <svtools/fltcall.hxx>
#include <svtools/FilterConfigItem.hxx>

//============================ RASWriter ==================================

class RASWriter {

private:

    SvStream & m_rOStm;
    USHORT              mpOStmOldModus;

    BOOL                mbStatus;
    BitmapReadAccess*   mpAcc;

    ULONG               mnWidth, mnHeight;
    USHORT              mnColors, mnDepth;

    ULONG               mnRepCount;
    BYTE                mnRepVal;

    com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator > xStatusIndicator;

    void                ImplCallback( ULONG nCurrentYPos );
    BOOL                ImplWriteHeader();
    void                ImplWritePalette();
    void                ImplWriteBody();
    void                ImplPutByte( BYTE );    // RLE decoding

public:
    RASWriter(SvStream &rStream);
    ~RASWriter();

    BOOL WriteRAS( const Graphic& rGraphic, FilterConfigItem* pFilterConfigItem );
};

//=================== Methoden von RASWriter ==============================

RASWriter::RASWriter(SvStream &rStream)
    : m_rOStm(rStream)
    , mbStatus(TRUE)
    , mpAcc(NULL)
    , mnRepCount( 0xffffffff )
{
}

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

RASWriter::~RASWriter()
{
}

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

void RASWriter::ImplCallback( ULONG nYPos )
{
    if ( xStatusIndicator.is() )
        xStatusIndicator->setValue( (USHORT)( ( 100 * nYPos ) / mnHeight ) );
}

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

BOOL RASWriter::WriteRAS( const Graphic& rGraphic, FilterConfigItem* pFilterConfigItem)
{
    Bitmap  aBmp;

    if ( pFilterConfigItem )
    {
        xStatusIndicator = pFilterConfigItem->GetStatusIndicator();
        if ( xStatusIndicator.is() )
        {
            rtl::OUString aMsg;
            xStatusIndicator->start( aMsg, 100 );
        }
    }

    BitmapEx    aBmpEx( rGraphic.GetBitmapEx() );
    aBmp = aBmpEx.GetBitmap();

    if ( aBmp.GetBitCount() == 4 )
        aBmp.Convert( BMP_CONVERSION_8BIT_COLORS );

    mnDepth = aBmp.GetBitCount();

    // export code below only handles three discrete cases
    mnDepth = mnDepth <= 1 ? 1 : mnDepth <= 8 ? 8 : 24;

    mpAcc = aBmp.AcquireReadAccess();
    if ( mpAcc )
    {
        mpOStmOldModus = m_rOStm.GetNumberFormatInt();
        m_rOStm.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );

        if ( ImplWriteHeader() )
        {
            if ( mnDepth <= 8 )
                ImplWritePalette();
            ImplWriteBody();
        }
        aBmp.ReleaseAccess( mpAcc );
    }
    else
        mbStatus = FALSE;

    m_rOStm.SetNumberFormatInt( mpOStmOldModus );

    if ( xStatusIndicator.is() )
        xStatusIndicator->end();

    return mbStatus;
}

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

BOOL RASWriter::ImplWriteHeader()
{
    mnWidth = mpAcc->Width();
    mnHeight = mpAcc->Height();
    if ( mnDepth <= 8 )
    {
        mnColors = mpAcc->GetPaletteEntryCount();
        if (mnColors == 0)
            mbStatus = FALSE;
    }
        if ( mbStatus && mnWidth && mnHeight && mnDepth )
    {
        m_rOStm << (UINT32)0x59a66a95 << (UINT32)mnWidth << (UINT32)mnHeight
            << (UINT32)mnDepth
            << (UINT32)(( ( ( ( mnWidth * mnDepth ) + 15 ) >> 4 ) << 1 ) * mnHeight)
            << (UINT32)2;

        if ( mnDepth > 8 )
            m_rOStm << (UINT32)0 << (UINT32)0;
        else
        {

            m_rOStm << (UINT32)1 << (UINT32)( mnColors * 3 );
        }
    }
    else mbStatus = FALSE;

    return mbStatus;
}

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

void RASWriter::ImplWritePalette()
{
    USHORT i;

    for ( i = 0; i < mnColors; m_rOStm << mpAcc->GetPaletteColor( i++ ).GetRed() ) ;
    for ( i = 0; i < mnColors; m_rOStm << mpAcc->GetPaletteColor( i++ ).GetGreen() ) ;
    for ( i = 0; i < mnColors; m_rOStm << mpAcc->GetPaletteColor( i++ ).GetBlue() ) ;
}

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

void RASWriter::ImplWriteBody()
{
    ULONG   x, y;

    if ( mnDepth == 24 )
    {
        for ( y = 0; y < mnHeight; y++ )
        {
            ImplCallback( y );                              // processing output
            for ( x = 0; x < mnWidth; x++ )
            {
                BitmapColor aColor( mpAcc->GetPixel( y, x ) );
                ImplPutByte( aColor.GetBlue() );            // Format ist BGR
                ImplPutByte( aColor.GetGreen() );
                ImplPutByte( aColor.GetRed() );
            }
            if ( x & 1 ) ImplPutByte( 0 );      // WORD ALIGNMENT ???
        }
    }
    else if ( mnDepth == 8 )
    {
        for ( y = 0; y < mnHeight; y++ )
        {
            ImplCallback( y );                              // processing output
            for ( x = 0; x < mnWidth; x++ )
            {
                ImplPutByte ( mpAcc->GetPixel( y, x ) );
            }
            if ( x & 1 ) ImplPutByte( 0 );      // WORD ALIGNMENT ???
        }
    }
    else if ( mnDepth == 1 )
    {
        BYTE nDat = 0;

        for ( y = 0; y < mnHeight; y++ )
        {
            ImplCallback( y );                              // processing output
            for ( x = 0; x < mnWidth; x++ )
            {
                nDat = ( ( nDat << 1 ) | ( mpAcc->GetPixel ( y, x ) & 1 ) );
                if ( ( x & 7 ) == 7 )
                    ImplPutByte( nDat );
            }
            if ( x & 7 )
                ImplPutByte( sal::static_int_cast< BYTE >(nDat << ( ( ( x & 7 ) ^ 7 ) + 1)) );// write remaining bits
            if (!( ( x - 1 ) & 0x8 ) )
                ImplPutByte( 0 );               // WORD ALIGNMENT ???
        }
    }
    ImplPutByte( mnRepVal + 1 );    // end of RLE decoding
}

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

void RASWriter::ImplPutByte( BYTE nPutThis )
{
    if ( mnRepCount == 0xffffffff )
    {
        mnRepCount = 0;
        mnRepVal = nPutThis;
    }
    else
    {
        if ( ( nPutThis == mnRepVal ) && ( mnRepCount != 0xff ) )
            mnRepCount++;
        else
        {
            if ( mnRepCount == 0 )
            {
                m_rOStm << (BYTE)mnRepVal;
                if ( mnRepVal == 0x80 )
                    m_rOStm << (BYTE)0;
            }
            else
            {
                m_rOStm << (BYTE)0x80;
                m_rOStm << (BYTE)mnRepCount;
                m_rOStm << (BYTE)mnRepVal;
            }
            mnRepVal = nPutThis;
            mnRepCount = 0;
        }
    }
}

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

// ---------------------
// - exported function -
// ---------------------

extern "C" BOOL __LOADONCALLAPI GraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pFilterConfigItem, BOOL )
{
    RASWriter aRASWriter(rStream);

    return aRASWriter.WriteRAS( rGraphic, pFilterConfigItem );
}

// ---------------
// - Win16 trash -
// ---------------

#ifdef WIN

static HINSTANCE hDLLInst = 0;

extern "C" int CALLBACK LibMain( HINSTANCE hDLL, WORD, WORD nHeap, LPSTR )
{
    if ( nHeap )
        UnlockData( 0 );

    hDLLInst = hDLL;

    return TRUE;
}

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

extern "C" int CALLBACK WEP( int )
{
    return 1;
}

#endif

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


<commit_before>#include "condor_common.h"
#include "directory.h"
#include "condor_debug.h"

#ifdef LINUX
bool isChildOf(const char *subdir, pid_t parent);
#endif
// Given a parent pid, find the first child pid of that parent pid
// by groveling through /proc

pid_t
findChildProc(pid_t parent) {
#ifdef LINUX
	Directory d("/proc");

	const char *subdir;
	while ((subdir = d.Next())) {
		// skip over all the non-pid subdirs of /proc (and 1)
		int pid = atoi(subdir);
		if (pid < 2) {
			continue;
		}
		if (isChildOf(subdir, parent)) {
			return pid;
		}

	}
	return -1;
#else
	return -1;
#endif
}

#ifdef LINUX
bool
isChildOf(const char *subdir, pid_t parent) {
	int fd;
	std::string fileName;

	char buf[512];
	buf[0] = '\0';

	formatstr(fileName, "/proc/%s/stat", subdir);

	fd = safe_open_wrapper(fileName.c_str(), O_RDONLY, 0666);
	if (fd < 0) {
		return false;
	}

	if (read(fd, buf, 511) < 0) {
		close(fd);
		return false;
	}
	close(fd);

	int pid = 0;
	int ppid = -1;

	// Format of /proc/self/stat is
	// pid program_name State ppid
	int matched = sscanf(buf, "%d%*s%*s%d", &pid, &ppid);
	if ((ppid == parent) && (matched > 0)) {
		return true;
	}
	return false;
}
#endif
<commit_msg>Check return value of read #6992<commit_after>#include "condor_common.h"
#include "directory.h"
#include "condor_debug.h"

#ifdef LINUX
bool isChildOf(const char *subdir, pid_t parent);
#endif
// Given a parent pid, find the first child pid of that parent pid
// by groveling through /proc

pid_t
findChildProc(pid_t parent) {
#ifdef LINUX
	Directory d("/proc");

	const char *subdir;
	while ((subdir = d.Next())) {
		// skip over all the non-pid subdirs of /proc (and 1)
		int pid = atoi(subdir);
		if (pid < 2) {
			continue;
		}
		if (isChildOf(subdir, parent)) {
			return pid;
		}

	}
	return -1;
#else
	return -1;
#endif
}

#ifdef LINUX
bool
isChildOf(const char *subdir, pid_t parent) {
	int fd;
	std::string fileName;

	char buf[512];
	buf[0] = '\0';

	formatstr(fileName, "/proc/%s/stat", subdir);

	fd = safe_open_wrapper(fileName.c_str(), O_RDONLY, 0666);
	if (fd < 0) {
		return false;
	}

	ssize_t num_read = read(fd, buf, 511);
	if (num_read < 5) { // minimum # of bytes for legal stat line
		close(fd);
		return false;
	}
	close(fd);

	int pid = 0;
	int ppid = -1;

	// Format of /proc/self/stat is
	// pid program_name State ppid
	int matched = sscanf(buf, "%d%*s%*s%d", &pid, &ppid);
	if ((ppid == parent) && (matched > 0)) {
		return true;
	}
	return false;
}
#endif
<|endoftext|>


<commit_before>/*
 *  JPetCmdParser.cpp
 *
 *
 *  Created by Karol Stola on 13-11-22.
 *  Copyright 2013 __MyCompanyName__. All rights reserved.
 *
 */
#include "JPetCmdParser.h"

//#ifndef __CINT__ // guard against being included into dictionary

JPetCmdParser::JPetCmdParser()
    : fOptDescriptions("Allowed options")
{
    vector<int> tmp;
    tmp.push_back(-1);
    tmp.push_back(-1);

    fOptDescriptions.add_options()
    ("help,h", "produce help message")
    ("type,t", po::value<string>()->required(), "type of file: hld or root")
    ("file,f", po::value<string>()->required(), "File to open")
    ("range,r", po::value< vector<int> >()->multitoken()->default_value(tmp,""), "Range of events to process.")
    ("param,p", po::value<string>(), "File with TRB numbers.")
    ;
}

void JPetCmdParser::parse(int argc, char** argv){
    try{

        if (argc == 1){
            cout << "No options provided." << endl;
            cout << fOptDescriptions << "\n";
            exit(0);
        }

        po::store(po::parse_command_line(argc, argv, fOptDescriptions), fVariablesMap);

        /* print out help */
        if (fVariablesMap.count("help")) {
            cout << fOptDescriptions << "\n";
            exit(0);
        }

        po::notify(fVariablesMap);

        /* parse range of events */
        if (fVariablesMap.count("range")) {
            if (fVariablesMap["range"].as< vector<int> >().size() != 2) {
                cerr << "Wrong number of bounds in range: " << fVariablesMap["range"].as< vector<int> >().size() << endl;
                exit(-1);
            }
            if (
                fVariablesMap["range"].as< vector<int> >()[0]
                > fVariablesMap["range"].as< vector<int> >()[1])
            {
                cerr << "Wrong range of events." << endl;
                exit(-1);
            }
        }

        /* check if correct file type was provided */

        if (
            fVariablesMap["type"].as <string>().compare("hld")
            && fVariablesMap["type"].as <string>().compare("root")
            )
        {
            cerr << "Wrong type of file: " << fVariablesMap["type"].as< string >() << endl;
            cerr << "Possible options: hld or root" << endl;

        }

    }
    catch(exception& e) {
        cerr << "error: " << e.what() << "\n";
        return;
    }
    catch(...) {
        cerr << "Exception of unknown type!\n";
    }
}

//#endif /* __CINT__ */<commit_msg>drobniutka poprawka parsera<commit_after>/*
 *  JPetCmdParser.cpp
 *
 *
 *  Created by Karol Stola on 13-11-22.
 *  Copyright 2013 __MyCompanyName__. All rights reserved.
 *
 */
#include "JPetCmdParser.h"

//#ifndef __CINT__ // guard against being included into dictionary

JPetCmdParser::JPetCmdParser()
    : fOptDescriptions("Allowed options")
{
    vector<int> tmp;
    tmp.push_back(-1);
    tmp.push_back(-1);

    fOptDescriptions.add_options()
    ("help,h", "produce help message")
    ("type,t", po::value<string>()->required(), "type of file: hld or root")
    ("file,f", po::value<string>()->required(), "File to open")
    ("range,r", po::value< vector<int> >()->multitoken()->default_value(tmp,""), "Range of events to process.")
    ("param,p", po::value<string>(), "File with TRB numbers.")
    ;
}

void JPetCmdParser::parse(int argc, char** argv){
    try{

        if (argc == 1){
            cout << "No options provided." << endl;
            cout << fOptDescriptions << "\n";
            exit(0);
        }

        po::store(po::parse_command_line(argc, argv, fOptDescriptions), fVariablesMap);

        /* print out help */
        if (fVariablesMap.count("help")) {
            cout << fOptDescriptions << "\n";
            exit(0);
        }

        po::notify(fVariablesMap);

        /* parse range of events */
        if (fVariablesMap.count("range")) {
            if (fVariablesMap["range"].as< vector<int> >().size() != 2) {
                cerr << "Wrong number of bounds in range: " << fVariablesMap["range"].as< vector<int> >().size() << endl;
                exit(-1);
            }
            if (
                fVariablesMap["range"].as< vector<int> >()[0]
                > fVariablesMap["range"].as< vector<int> >()[1])
            {
                cerr << "Wrong range of events." << endl;
                exit(-1);
            }
        }

        /* check if correct file type was provided */

        if (
            fVariablesMap["type"].as <string>().compare("hld")
            && fVariablesMap["type"].as <string>().compare("root")
            )
        {
            cerr << "Wrong type of file: " << fVariablesMap["type"].as< string >() << endl;
            cerr << "Possible options: hld or root" << endl;
            exit(-1);
        }

    }
    catch(exception& e) {
        cerr << "error: " << e.what() << "\n";
        return;
    }
    catch(...) {
        cerr << "Exception of unknown type!\n";
    }
}

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


<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2017 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <arith_uint256.h>

#include <uint256.h>
#include <utilstrencodings.h>
#include <crypto/common.h>

#include <stdio.h>
#include <string.h>

template <unsigned int BITS>
base_uint<BITS>::base_uint(const std::string& str)
{
    static_assert(BITS/32 > 0 && BITS%32 == 0, "Template parameter BITS must be a positive multiple of 32.");

    SetHex(str);
}

template <unsigned int BITS>
base_uint<BITS>& base_uint<BITS>::operator<<=(unsigned int shift)
{
    base_uint<BITS> a(*this);
    for (int i = 0; i < WIDTH; i++)
        pn[i] = 0;
    int k = shift / 32;
    shift = shift % 32;
    for (int i = 0; i < WIDTH; i++) {
        if (i + k + 1 < WIDTH && shift != 0)
            pn[i + k + 1] |= (a.pn[i] >> (32 - shift));
        if (i + k < WIDTH)
            pn[i + k] |= (a.pn[i] << shift);
    }
    return *this;
}

template <unsigned int BITS>
base_uint<BITS>& base_uint<BITS>::operator>>=(unsigned int shift)
{
    base_uint<BITS> a(*this);
    for (int i = 0; i < WIDTH; i++)
        pn[i] = 0;
    int k = shift / 32;
    shift = shift % 32;
    for (int i = 0; i < WIDTH; i++) {
        if (i - k - 1 >= 0 && shift != 0)
            pn[i - k - 1] |= (a.pn[i] << (32 - shift));
        if (i - k >= 0)
            pn[i - k] |= (a.pn[i] >> shift);
    }
    return *this;
}

template <unsigned int BITS>
base_uint<BITS>& base_uint<BITS>::operator*=(uint32_t b32)
{
    uint64_t carry = 0;
    for (int i = 0; i < WIDTH; i++) {
        uint64_t n = carry + (uint64_t)b32 * pn[i];
        pn[i] = n & 0xffffffff;
        carry = n >> 32;
    }
    return *this;
}

template <unsigned int BITS>
base_uint<BITS>& base_uint<BITS>::operator*=(const base_uint& b)
{
    base_uint<BITS> a = *this;
    *this = 0;
    for (int j = 0; j < WIDTH; j++) {
        uint64_t carry = 0;
        for (int i = 0; i + j < WIDTH; i++) {
            uint64_t n = carry + pn[i + j] + (uint64_t)a.pn[j] * b.pn[i];
            pn[i + j] = n & 0xffffffff;
            carry = n >> 32;
        }
    }
    return *this;
}

template <unsigned int BITS>
base_uint<BITS>& base_uint<BITS>::operator/=(const base_uint& b)
{
    base_uint<BITS> div = b;     // make a copy, so we can shift.
    base_uint<BITS> num = *this; // make a copy, so we can subtract.
    *this = 0;                   // the quotient.
    int num_bits = num.bits();
    int div_bits = div.bits();
    if (div_bits == 0)
        throw uint_error("Division by zero");
    if (div_bits > num_bits) // the result is certainly 0.
        return *this;
    int shift = num_bits - div_bits;
    div <<= shift; // shift so that div and num align.
    while (shift >= 0) {
        if (num >= div) {
            num -= div;
            pn[shift / 32] |= (1 << (shift & 31)); // set a bit of the result.
        }
        div >>= 1; // shift back.
        shift--;
    }
    // num now contains the remainder of the division.
    return *this;
}

template <unsigned int BITS>
int base_uint<BITS>::CompareTo(const base_uint<BITS>& b) const
{
    for (int i = WIDTH - 1; i >= 0; i--) {
        if (pn[i] < b.pn[i])
            return -1;
        if (pn[i] > b.pn[i])
            return 1;
    }
    return 0;
}

template <unsigned int BITS>
bool base_uint<BITS>::EqualTo(uint64_t b) const
{
    for (int i = WIDTH - 1; i >= 2; i--) {
        if (pn[i])
            return false;
    }
    if (pn[1] != (b >> 32))
        return false;
    if (pn[0] != (b & 0xfffffffful))
        return false;
    return true;
}

template <unsigned int BITS>
double base_uint<BITS>::getdouble() const
{
    double ret = 0.0;
    double fact = 1.0;
    for (int i = 0; i < WIDTH; i++) {
        ret += fact * pn[i];
        fact *= 4294967296.0;
    }
    return ret;
}

template <unsigned int BITS>
std::string base_uint<BITS>::GetHex() const
{
    return ArithToUint256(*this).GetHex();
}

template <unsigned int BITS>
void base_uint<BITS>::SetHex(const char* psz)
{
    *this = UintToArith256(uint256S(psz));
}

template <unsigned int BITS>
void base_uint<BITS>::SetHex(const std::string& str)
{
    SetHex(str.c_str());
}

template <unsigned int BITS>
std::string base_uint<BITS>::ToString() const
{
    return (GetHex());
}

template <unsigned int BITS>
unsigned int base_uint<BITS>::bits() const
{
    for (int pos = WIDTH - 1; pos >= 0; pos--) {
        if (pn[pos]) {
            for (int nbits = 31; nbits > 0; nbits--) {
                if (pn[pos] & 1 << nbits)
                    return 32 * pos + nbits + 1;
            }
            return 32 * pos + 1;
        }
    }
    return 0;
}

// Explicit instantiations for base_uint<256>
template base_uint<256>::base_uint(const std::string&);
template base_uint<256>& base_uint<256>::operator<<=(unsigned int);
template base_uint<256>& base_uint<256>::operator>>=(unsigned int);
template base_uint<256>& base_uint<256>::operator*=(uint32_t b32);
template base_uint<256>& base_uint<256>::operator*=(const base_uint<256>& b);
template base_uint<256>& base_uint<256>::operator/=(const base_uint<256>& b);
template int base_uint<256>::CompareTo(const base_uint<256>&) const;
template bool base_uint<256>::EqualTo(uint64_t) const;
template double base_uint<256>::getdouble() const;
template std::string base_uint<256>::GetHex() const;
template std::string base_uint<256>::ToString() const;
template void base_uint<256>::SetHex(const char*);
template void base_uint<256>::SetHex(const std::string&);
template unsigned int base_uint<256>::bits() const;

// This implementation directly uses shifts instead of going
// through an intermediate MPI representation.
arith_uint256& arith_uint256::SetCompact(uint32_t nCompact, bool* pfNegative, bool* pfOverflow)
{
    int nSize = nCompact >> 24;
    uint32_t nWord = nCompact & 0x007fffff;
    if (nSize <= 3) {
        nWord >>= 8 * (3 - nSize);
        *this = nWord;
    } else {
        *this = nWord;
        *this <<= 8 * (nSize - 3);
    }
    if (pfNegative)
        *pfNegative = nWord != 0 && (nCompact & 0x00800000) != 0;
    if (pfOverflow)
        *pfOverflow = nWord != 0 && ((nSize > 34) ||
                                     (nWord > 0xff && nSize > 33) ||
                                     (nWord > 0xffff && nSize > 32));
    return *this;
}

uint32_t arith_uint256::GetCompact(bool fNegative) const
{
    int nSize = (bits() + 7) / 8;
    uint32_t nCompact = 0;
    if (nSize <= 3) {
        nCompact = GetLow64() << 8 * (3 - nSize);
    } else {
        arith_uint256 bn = *this >> 8 * (nSize - 3);
        nCompact = bn.GetLow64();
    }
    // The 0x00800000 bit denotes the sign.
    // Thus, if it is already set, divide the mantissa by 256 and increase the exponent.
    if (nCompact & 0x00800000) {
        nCompact >>= 8;
        nSize++;
    }
    assert((nCompact & ~0x007fffff) == 0);
    assert(nSize < 256);
    nCompact |= nSize << 24;
    nCompact |= (fNegative && (nCompact & 0x007fffff) ? 0x00800000 : 0);
    return nCompact;
}

uint256 ArithToUint256(const arith_uint256 &a)
{
    uint256 b;
    for(int x=0; x<a.WIDTH; ++x)
        WriteLE32(b.begin() + x*4, a.pn[x]);
    return b;
}
arith_uint256 UintToArith256(const uint256 &a)
{
    arith_uint256 b;
    for(int x=0; x<b.WIDTH; ++x)
        b.pn[x] = ReadLE32(a.begin() + x*4);
    return b;
}
<commit_msg>[arith_uint256] Do not destroy *this content if passed-in operator may reference it<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2017 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <arith_uint256.h>

#include <uint256.h>
#include <utilstrencodings.h>
#include <crypto/common.h>

#include <stdio.h>
#include <string.h>

template <unsigned int BITS>
base_uint<BITS>::base_uint(const std::string& str)
{
    static_assert(BITS/32 > 0 && BITS%32 == 0, "Template parameter BITS must be a positive multiple of 32.");

    SetHex(str);
}

template <unsigned int BITS>
base_uint<BITS>& base_uint<BITS>::operator<<=(unsigned int shift)
{
    base_uint<BITS> a(*this);
    for (int i = 0; i < WIDTH; i++)
        pn[i] = 0;
    int k = shift / 32;
    shift = shift % 32;
    for (int i = 0; i < WIDTH; i++) {
        if (i + k + 1 < WIDTH && shift != 0)
            pn[i + k + 1] |= (a.pn[i] >> (32 - shift));
        if (i + k < WIDTH)
            pn[i + k] |= (a.pn[i] << shift);
    }
    return *this;
}

template <unsigned int BITS>
base_uint<BITS>& base_uint<BITS>::operator>>=(unsigned int shift)
{
    base_uint<BITS> a(*this);
    for (int i = 0; i < WIDTH; i++)
        pn[i] = 0;
    int k = shift / 32;
    shift = shift % 32;
    for (int i = 0; i < WIDTH; i++) {
        if (i - k - 1 >= 0 && shift != 0)
            pn[i - k - 1] |= (a.pn[i] << (32 - shift));
        if (i - k >= 0)
            pn[i - k] |= (a.pn[i] >> shift);
    }
    return *this;
}

template <unsigned int BITS>
base_uint<BITS>& base_uint<BITS>::operator*=(uint32_t b32)
{
    uint64_t carry = 0;
    for (int i = 0; i < WIDTH; i++) {
        uint64_t n = carry + (uint64_t)b32 * pn[i];
        pn[i] = n & 0xffffffff;
        carry = n >> 32;
    }
    return *this;
}

template <unsigned int BITS>
base_uint<BITS>& base_uint<BITS>::operator*=(const base_uint& b)
{
    base_uint<BITS> a;
    for (int j = 0; j < WIDTH; j++) {
        uint64_t carry = 0;
        for (int i = 0; i + j < WIDTH; i++) {
            uint64_t n = carry + a.pn[i + j] + (uint64_t)pn[j] * b.pn[i];
            a.pn[i + j] = n & 0xffffffff;
            carry = n >> 32;
        }
    }
    *this = a;
    return *this;
}

template <unsigned int BITS>
base_uint<BITS>& base_uint<BITS>::operator/=(const base_uint& b)
{
    base_uint<BITS> div = b;     // make a copy, so we can shift.
    base_uint<BITS> num = *this; // make a copy, so we can subtract.
    *this = 0;                   // the quotient.
    int num_bits = num.bits();
    int div_bits = div.bits();
    if (div_bits == 0)
        throw uint_error("Division by zero");
    if (div_bits > num_bits) // the result is certainly 0.
        return *this;
    int shift = num_bits - div_bits;
    div <<= shift; // shift so that div and num align.
    while (shift >= 0) {
        if (num >= div) {
            num -= div;
            pn[shift / 32] |= (1 << (shift & 31)); // set a bit of the result.
        }
        div >>= 1; // shift back.
        shift--;
    }
    // num now contains the remainder of the division.
    return *this;
}

template <unsigned int BITS>
int base_uint<BITS>::CompareTo(const base_uint<BITS>& b) const
{
    for (int i = WIDTH - 1; i >= 0; i--) {
        if (pn[i] < b.pn[i])
            return -1;
        if (pn[i] > b.pn[i])
            return 1;
    }
    return 0;
}

template <unsigned int BITS>
bool base_uint<BITS>::EqualTo(uint64_t b) const
{
    for (int i = WIDTH - 1; i >= 2; i--) {
        if (pn[i])
            return false;
    }
    if (pn[1] != (b >> 32))
        return false;
    if (pn[0] != (b & 0xfffffffful))
        return false;
    return true;
}

template <unsigned int BITS>
double base_uint<BITS>::getdouble() const
{
    double ret = 0.0;
    double fact = 1.0;
    for (int i = 0; i < WIDTH; i++) {
        ret += fact * pn[i];
        fact *= 4294967296.0;
    }
    return ret;
}

template <unsigned int BITS>
std::string base_uint<BITS>::GetHex() const
{
    return ArithToUint256(*this).GetHex();
}

template <unsigned int BITS>
void base_uint<BITS>::SetHex(const char* psz)
{
    *this = UintToArith256(uint256S(psz));
}

template <unsigned int BITS>
void base_uint<BITS>::SetHex(const std::string& str)
{
    SetHex(str.c_str());
}

template <unsigned int BITS>
std::string base_uint<BITS>::ToString() const
{
    return (GetHex());
}

template <unsigned int BITS>
unsigned int base_uint<BITS>::bits() const
{
    for (int pos = WIDTH - 1; pos >= 0; pos--) {
        if (pn[pos]) {
            for (int nbits = 31; nbits > 0; nbits--) {
                if (pn[pos] & 1 << nbits)
                    return 32 * pos + nbits + 1;
            }
            return 32 * pos + 1;
        }
    }
    return 0;
}

// Explicit instantiations for base_uint<256>
template base_uint<256>::base_uint(const std::string&);
template base_uint<256>& base_uint<256>::operator<<=(unsigned int);
template base_uint<256>& base_uint<256>::operator>>=(unsigned int);
template base_uint<256>& base_uint<256>::operator*=(uint32_t b32);
template base_uint<256>& base_uint<256>::operator*=(const base_uint<256>& b);
template base_uint<256>& base_uint<256>::operator/=(const base_uint<256>& b);
template int base_uint<256>::CompareTo(const base_uint<256>&) const;
template bool base_uint<256>::EqualTo(uint64_t) const;
template double base_uint<256>::getdouble() const;
template std::string base_uint<256>::GetHex() const;
template std::string base_uint<256>::ToString() const;
template void base_uint<256>::SetHex(const char*);
template void base_uint<256>::SetHex(const std::string&);
template unsigned int base_uint<256>::bits() const;

// This implementation directly uses shifts instead of going
// through an intermediate MPI representation.
arith_uint256& arith_uint256::SetCompact(uint32_t nCompact, bool* pfNegative, bool* pfOverflow)
{
    int nSize = nCompact >> 24;
    uint32_t nWord = nCompact & 0x007fffff;
    if (nSize <= 3) {
        nWord >>= 8 * (3 - nSize);
        *this = nWord;
    } else {
        *this = nWord;
        *this <<= 8 * (nSize - 3);
    }
    if (pfNegative)
        *pfNegative = nWord != 0 && (nCompact & 0x00800000) != 0;
    if (pfOverflow)
        *pfOverflow = nWord != 0 && ((nSize > 34) ||
                                     (nWord > 0xff && nSize > 33) ||
                                     (nWord > 0xffff && nSize > 32));
    return *this;
}

uint32_t arith_uint256::GetCompact(bool fNegative) const
{
    int nSize = (bits() + 7) / 8;
    uint32_t nCompact = 0;
    if (nSize <= 3) {
        nCompact = GetLow64() << 8 * (3 - nSize);
    } else {
        arith_uint256 bn = *this >> 8 * (nSize - 3);
        nCompact = bn.GetLow64();
    }
    // The 0x00800000 bit denotes the sign.
    // Thus, if it is already set, divide the mantissa by 256 and increase the exponent.
    if (nCompact & 0x00800000) {
        nCompact >>= 8;
        nSize++;
    }
    assert((nCompact & ~0x007fffff) == 0);
    assert(nSize < 256);
    nCompact |= nSize << 24;
    nCompact |= (fNegative && (nCompact & 0x007fffff) ? 0x00800000 : 0);
    return nCompact;
}

uint256 ArithToUint256(const arith_uint256 &a)
{
    uint256 b;
    for(int x=0; x<a.WIDTH; ++x)
        WriteLE32(b.begin() + x*4, a.pn[x]);
    return b;
}
arith_uint256 UintToArith256(const uint256 &a)
{
    arith_uint256 b;
    for(int x=0; x<b.WIDTH; ++x)
        b.pn[x] = ReadLE32(a.begin() + x*4);
    return b;
}
<|endoftext|>


<commit_before>///
/// @file  pi_deleglise_rivat2.cpp
/// @brief Implementation of the Deleglise-Rivat prime counting
///        algorithm. Compared to pi_deleglise_rivat1.cpp this version
///        uses compression (FactorTable & PiTable) to reduce the
///        memory usage.
///
///        This implementation is based on the paper:
///        Tomás Oliveira e Silva, Computing pi(x): the combinatorial
///        method, Revista do DETUA, vol. 4, no. 6, March 2006,
///        pp. 759-768.
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <PiTable.hpp>
#include <FactorTable.hpp>
#include <primecount-internal.hpp>
#include <BitSieve.hpp>
#include <generate.hpp>
#include <pmath.hpp>
#include <PhiTiny.hpp>
#include <S1.hpp>
#include <tos_counters.hpp>

#include <stdint.h>
#include <algorithm>
#include <vector>

using namespace std;
using namespace primecount;

namespace {

/// Cross-off the multiples of prime in the sieve array.
/// For each element that is unmarked the first time update
/// the special counters tree data structure.
///
template <typename T>
void cross_off(int64_t prime,
               int64_t low,
               int64_t high,
               int64_t& next_multiple,
               BitSieve& sieve,
               T& counters)
{
  int64_t segment_size = sieve.size();
  int64_t k = next_multiple;

  for (; k < high; k += prime * 2)
  {
    if (sieve[k - low])
    {
      sieve.unset(k - low);
      cnt_update(counters, k - low, segment_size);
    }
  }
  next_multiple = k;
}

/// Calculate the contribution of the trivial leaves.
///
int64_t S2_trivial(int64_t x,
                   int64_t y,
                   int64_t z,
                   int64_t c,
                   PiTable& pi,
                   vector<int32_t>& primes)
{
  int64_t pi_y = pi(y);
  int64_t pi_sqrtz = pi(min(isqrt(z), y));
  int64_t S2_result = 0;

  // Find all trivial leaves: n = primes[b] * primes[l]
  // which satisfy phi(x / n), b - 1) = 1
  for (int64_t b = max(c, pi_sqrtz + 1); b < pi_y; b++)
  {
    int64_t prime = primes[b];
    S2_result += pi_y - pi(max(x / (prime * prime), prime));
  }

  return S2_result;
}

/// Calculate the contribution of the trivial leaves, the clustered
/// easy leaves and the sparse easy leaves.
///
int64_t S2_easy(int64_t x,
                int64_t y,
                int64_t z,
                int64_t c,
                PiTable& pi,
                vector<int32_t>& primes)
{
  int64_t pi_sqrty = pi(isqrt(y));
  int64_t pi_x13 = pi(iroot<3>(x));
  int64_t S2_result = 0;

  for (int64_t b = max(c, pi_sqrty) + 1; b <= pi_x13; b++)
  {
    int64_t prime = primes[b];
    int64_t min_trivial_leaf = x / (prime * prime);
    int64_t min_clustered_easy_leaf = isqrt(x / prime);
    int64_t min_sparse_easy_leaf = z / prime;
    int64_t min_hard_leaf = max(y / prime, prime);

    min_sparse_easy_leaf = max(min_sparse_easy_leaf, min_hard_leaf);
    min_clustered_easy_leaf = max(min_clustered_easy_leaf, min_hard_leaf);
    int64_t l = pi(min(min_trivial_leaf, y));

    // Find all clustered easy leaves:
    // x / n <= y and phi(x / n, b - 1) == phi(x / m, b - 1)
    // where phi(x / n, b - 1) = pi(x / n) - b + 2
    while (primes[l] > min_clustered_easy_leaf)
    {
      int64_t n = prime * primes[l];
      int64_t xn = x / n;
      assert(xn < isquare(primes[b]));
      int64_t phi_xn = pi(xn) - b + 2;
      int64_t m = prime * primes[b + phi_xn - 1];
      int64_t xm = max(x / m, min_clustered_easy_leaf);
      int64_t l2 = pi(xm);
      S2_result += phi_xn * (l - l2);
      l = l2;
    }

    // Find all sparse easy leaves:
    // x / n <= y and phi(x / n, b - 1) = pi(x / n) - b + 2
    for (; primes[l] > min_sparse_easy_leaf; l--)
    {
      int64_t n = prime * primes[l];
      int64_t xn = x / n;
      assert(xn < isquare(primes[b]));
      S2_result += pi(xn) - b + 2;
    }
  }

  return S2_result;
}

/// Calculate the contribution of the special leaves which require
/// a sieve (in order to reduce the memory usage).
///
int64_t S2_sieve(int64_t x,
                 int64_t y,
                 int64_t z,
                 int64_t c,
                 PiTable& pi,
                 vector<int32_t>& primes,
                 FactorTable<uint16_t>& factors)
{
  int64_t limit = z + 1;
  int64_t segment_size = next_power_of_2(isqrt(limit));
  int64_t pi_sqrty = pi(isqrt(y));
  int64_t pi_sqrtz = pi(min(isqrt(z), y));
  int64_t S2_result = 0;

  BitSieve sieve(segment_size);
  vector<int32_t> counters(segment_size);
  vector<int64_t> next(primes.begin(), primes.end());
  vector<int64_t> phi(primes.size(), 0);

  // Segmented sieve of Eratosthenes
  for (int64_t low = 1; low < limit; low += segment_size)
  {
    // Current segment = interval [low, high[
    int64_t high = min(low + segment_size, limit);
    int64_t b = 2;

    sieve.fill(low, high);

    // phi(y, b) nodes with b <= c do not contribute to S2, so we
    // simply sieve out the multiples of the first c primes
    for (; b <= c; b++)
    {
      int64_t k = next[b];
      for (int64_t prime = primes[b]; k < high; k += prime * 2)
        sieve.unset(k - low);
      next[b] = k;
    }

    // Initialize special tree data structure from sieve
    cnt_finit(sieve, counters, segment_size);

    // For c + 1 <= b <= pi_sqrty
    // Find all special leaves: n = primes[b] * m, with mu[m] != 0 and primes[b] < lpf[m]
    // which satisfy: low <= (x / n) < high
    for (; b <= pi_sqrty; b++)
    {
      int64_t prime = primes[b];
      int64_t min_m = max(x / (prime * high), y / prime);
      int64_t max_m = min(x / (prime * low), y);

      if (prime >= max_m)
        goto next_segment;

      factors.to_index(&min_m);
      factors.to_index(&max_m);

      for (int64_t m = max_m; m > min_m; m--)
      {
        if (prime < factors.lpf(m))
        {
          int64_t n = prime * factors.get_number(m);
          int64_t count = cnt_query(counters, (x / n) - low);
          int64_t phi_xn = phi[b] + count;
          S2_result -= factors.mu(m) * phi_xn;
        }
      }

      phi[b] += cnt_query(counters, (high - 1) - low);
      cross_off(prime, low, high, next[b], sieve, counters);
    }

    // For pi_sqrty <= b <= pi_sqrtz
    // Find all hard special leaves: n = primes[b] * primes[l]
    // which satisfy: low <= (x / n) < high
    for (; b <= pi_sqrtz; b++)
    {
      int64_t prime = primes[b];
      int64_t l = pi(min3(x / (prime * low), z / prime, y));
      int64_t min_hard_leaf = max3(x / (prime * high), y / prime, prime);

      if (prime >= primes[l])
        goto next_segment;

      for (; primes[l] > min_hard_leaf; l--)
      {
        int64_t n = prime * primes[l];
        int64_t xn = x / n;
        int64_t count = cnt_query(counters, xn - low);
        int64_t phi_xn = phi[b] + count;
        S2_result += phi_xn;
      }

      phi[b] += cnt_query(counters, (high - 1) - low);
      cross_off(prime, low, high, next[b], sieve, counters);
    }

    next_segment:;
  }

  return S2_result;
}

/// Calculate the contribution of the special leaves.
/// @pre y > 0 && c > 1
///
int64_t S2(int64_t x,
           int64_t y,
           int64_t z,
           int64_t c,
           vector<int32_t>& primes,
           FactorTable<uint16_t>& factors)
{
  int64_t S2_total = 0;
  PiTable pi(y);

  S2_total += S2_trivial(x, y, z, c, pi, primes);
  S2_total += S2_easy(x, y, z, c, pi, primes);
  S2_total += S2_sieve(x, y, z, c, pi, primes, factors);

  return S2_total;
}

/// alpha is a tuning factor which should grow like (log(x))^3
/// for the Deleglise-Rivat prime counting algorithm.
///
double compute_alpha(int64_t x)
{
  double d = (double) x;
  double alpha = log(d) * log(d) * log(d) / 1200;
  return in_between(1, alpha, iroot<6>(x));
}

} // namespace

namespace primecount {

/// Calculate the number of primes below x using the
/// Deleglise-Rivat algorithm.
/// Run time: O(x^(2/3) / (log x)^2) operations, O(x^(1/3) * (log x)^3) space.
///
int64_t pi_deleglise_rivat2(int64_t x)
{
  if (x < 2)
    return 0;

  double alpha = compute_alpha(x);
  int64_t y = (int64_t) (alpha * iroot<3>(x));
  int64_t z = x / y;
  int64_t p2 = P2(x, y, 1);

  vector<int32_t> primes = generate_primes(y);
  FactorTable<uint16_t> factors(y);

  int64_t pi_y = pi_bsearch(primes, y);
  int64_t c = min(pi_y, PhiTiny::max_a());
  int64_t s1 = S1(x, y, c, primes[c], factors, 1);
  int64_t s2 = S2(x, y, z, c, primes, factors);
  int64_t phi = s1 + s2;
  int64_t sum = phi + pi_y - 1 - p2;

  return sum;
}

} // namespace primecount
<commit_msg>Update pi_deleglise_rivat2.cpp<commit_after>///
/// @file  pi_deleglise_rivat2.cpp
/// @brief Implementation of the Deleglise-Rivat prime counting
///        algorithm. Compared to pi_deleglise_rivat1.cpp this version
///        uses compression (FactorTable & PiTable) to reduce the
///        memory usage.
///
///        This implementation is based on the paper:
///        Tomás Oliveira e Silva, Computing pi(x): the combinatorial
///        method, Revista do DETUA, vol. 4, no. 6, March 2006,
///        pp. 759-768.
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <PiTable.hpp>
#include <FactorTable.hpp>
#include <primecount-internal.hpp>
#include <BitSieve.hpp>
#include <generate.hpp>
#include <pmath.hpp>
#include <PhiTiny.hpp>
#include <S1.hpp>
#include <tos_counters.hpp>

#include <stdint.h>
#include <algorithm>
#include <vector>

using namespace std;
using namespace primecount;

namespace {

/// Cross-off the multiples of prime in the sieve array.
/// For each element that is unmarked the first time update
/// the special counters tree data structure.
///
template <typename T>
void cross_off(int64_t prime,
               int64_t low,
               int64_t high,
               int64_t& next_multiple,
               BitSieve& sieve,
               T& counters)
{
  int64_t segment_size = sieve.size();
  int64_t k = next_multiple;

  for (; k < high; k += prime * 2)
  {
    if (sieve[k - low])
    {
      sieve.unset(k - low);
      cnt_update(counters, k - low, segment_size);
    }
  }
  next_multiple = k;
}

/// Calculate the contribution of the trivial leaves.
///
int64_t S2_trivial(int64_t x,
                   int64_t y,
                   int64_t z,
                   int64_t c,
                   PiTable& pi,
                   vector<int32_t>& primes)
{
  int64_t pi_y = pi(y);
  int64_t pi_sqrtz = pi(min(isqrt(z), y));
  int64_t S2_result = 0;

  // Find all trivial leaves: n = primes[b] * primes[l]
  // which satisfy phi(x / n), b - 1) = 1
  for (int64_t b = max(c, pi_sqrtz + 1); b < pi_y; b++)
  {
    int64_t prime = primes[b];
    S2_result += pi_y - pi(max(x / (prime * prime), prime));
  }

  return S2_result;
}

/// Calculate the contribution of the clustered easy
/// leaves and the sparse easy leaves.
///
int64_t S2_easy(int64_t x,
                int64_t y,
                int64_t z,
                int64_t c,
                PiTable& pi,
                vector<int32_t>& primes)
{
  int64_t pi_sqrty = pi(isqrt(y));
  int64_t pi_x13 = pi(iroot<3>(x));
  int64_t S2_result = 0;

  for (int64_t b = max(c, pi_sqrty) + 1; b <= pi_x13; b++)
  {
    int64_t prime = primes[b];
    int64_t min_trivial_leaf = x / (prime * prime);
    int64_t min_clustered_easy_leaf = isqrt(x / prime);
    int64_t min_sparse_easy_leaf = z / prime;
    int64_t min_hard_leaf = max(y / prime, prime);

    min_sparse_easy_leaf = max(min_sparse_easy_leaf, min_hard_leaf);
    min_clustered_easy_leaf = max(min_clustered_easy_leaf, min_hard_leaf);
    int64_t l = pi(min(min_trivial_leaf, y));

    // Find all clustered easy leaves:
    // x / n <= y and phi(x / n, b - 1) == phi(x / m, b - 1)
    // where phi(x / n, b - 1) = pi(x / n) - b + 2
    while (primes[l] > min_clustered_easy_leaf)
    {
      int64_t n = prime * primes[l];
      int64_t xn = x / n;
      assert(xn < isquare(primes[b]));
      int64_t phi_xn = pi(xn) - b + 2;
      int64_t m = prime * primes[b + phi_xn - 1];
      int64_t xm = max(x / m, min_clustered_easy_leaf);
      int64_t l2 = pi(xm);
      S2_result += phi_xn * (l - l2);
      l = l2;
    }

    // Find all sparse easy leaves:
    // x / n <= y and phi(x / n, b - 1) = pi(x / n) - b + 2
    for (; primes[l] > min_sparse_easy_leaf; l--)
    {
      int64_t n = prime * primes[l];
      int64_t xn = x / n;
      assert(xn < isquare(primes[b]));
      S2_result += pi(xn) - b + 2;
    }
  }

  return S2_result;
}

/// Calculate the contribution of the special leaves which require
/// a sieve (in order to reduce the memory usage).
///
int64_t S2_sieve(int64_t x,
                 int64_t y,
                 int64_t z,
                 int64_t c,
                 PiTable& pi,
                 vector<int32_t>& primes,
                 FactorTable<uint16_t>& factors)
{
  int64_t limit = z + 1;
  int64_t segment_size = next_power_of_2(isqrt(limit));
  int64_t pi_sqrty = pi(isqrt(y));
  int64_t pi_sqrtz = pi(min(isqrt(z), y));
  int64_t S2_result = 0;

  BitSieve sieve(segment_size);
  vector<int32_t> counters(segment_size);
  vector<int64_t> next(primes.begin(), primes.end());
  vector<int64_t> phi(primes.size(), 0);

  // Segmented sieve of Eratosthenes
  for (int64_t low = 1; low < limit; low += segment_size)
  {
    // Current segment = interval [low, high[
    int64_t high = min(low + segment_size, limit);
    int64_t b = 2;

    sieve.fill(low, high);

    // phi(y, b) nodes with b <= c do not contribute to S2, so we
    // simply sieve out the multiples of the first c primes
    for (; b <= c; b++)
    {
      int64_t k = next[b];
      for (int64_t prime = primes[b]; k < high; k += prime * 2)
        sieve.unset(k - low);
      next[b] = k;
    }

    // Initialize special tree data structure from sieve
    cnt_finit(sieve, counters, segment_size);

    // For c + 1 <= b <= pi_sqrty
    // Find all special leaves: n = primes[b] * m, with mu[m] != 0 and primes[b] < lpf[m]
    // which satisfy: low <= (x / n) < high
    for (; b <= pi_sqrty; b++)
    {
      int64_t prime = primes[b];
      int64_t min_m = max(x / (prime * high), y / prime);
      int64_t max_m = min(x / (prime * low), y);

      if (prime >= max_m)
        goto next_segment;

      factors.to_index(&min_m);
      factors.to_index(&max_m);

      for (int64_t m = max_m; m > min_m; m--)
      {
        if (prime < factors.lpf(m))
        {
          int64_t n = prime * factors.get_number(m);
          int64_t count = cnt_query(counters, (x / n) - low);
          int64_t phi_xn = phi[b] + count;
          S2_result -= factors.mu(m) * phi_xn;
        }
      }

      phi[b] += cnt_query(counters, (high - 1) - low);
      cross_off(prime, low, high, next[b], sieve, counters);
    }

    // For pi_sqrty <= b <= pi_sqrtz
    // Find all hard special leaves: n = primes[b] * primes[l]
    // which satisfy: low <= (x / n) < high
    for (; b <= pi_sqrtz; b++)
    {
      int64_t prime = primes[b];
      int64_t l = pi(min3(x / (prime * low), z / prime, y));
      int64_t min_hard_leaf = max3(x / (prime * high), y / prime, prime);

      if (prime >= primes[l])
        goto next_segment;

      for (; primes[l] > min_hard_leaf; l--)
      {
        int64_t n = prime * primes[l];
        int64_t xn = x / n;
        int64_t count = cnt_query(counters, xn - low);
        int64_t phi_xn = phi[b] + count;
        S2_result += phi_xn;
      }

      phi[b] += cnt_query(counters, (high - 1) - low);
      cross_off(prime, low, high, next[b], sieve, counters);
    }

    next_segment:;
  }

  return S2_result;
}

/// Calculate the contribution of the special leaves.
/// @pre y > 0 && c > 1
///
int64_t S2(int64_t x,
           int64_t y,
           int64_t z,
           int64_t c,
           vector<int32_t>& primes,
           FactorTable<uint16_t>& factors)
{
  int64_t S2_total = 0;
  PiTable pi(y);

  S2_total += S2_trivial(x, y, z, c, pi, primes);
  S2_total += S2_easy(x, y, z, c, pi, primes);
  S2_total += S2_sieve(x, y, z, c, pi, primes, factors);

  return S2_total;
}

/// alpha is a tuning factor which should grow like (log(x))^3
/// for the Deleglise-Rivat prime counting algorithm.
///
double compute_alpha(int64_t x)
{
  double d = (double) x;
  double alpha = log(d) * log(d) * log(d) / 1200;
  return in_between(1, alpha, iroot<6>(x));
}

} // namespace

namespace primecount {

/// Calculate the number of primes below x using the
/// Deleglise-Rivat algorithm.
/// Run time: O(x^(2/3) / (log x)^2) operations, O(x^(1/3) * (log x)^3) space.
///
int64_t pi_deleglise_rivat2(int64_t x)
{
  if (x < 2)
    return 0;

  double alpha = compute_alpha(x);
  int64_t y = (int64_t) (alpha * iroot<3>(x));
  int64_t z = x / y;
  int64_t p2 = P2(x, y, 1);

  vector<int32_t> primes = generate_primes(y);
  FactorTable<uint16_t> factors(y);

  int64_t pi_y = pi_bsearch(primes, y);
  int64_t c = min(pi_y, PhiTiny::max_a());
  int64_t s1 = S1(x, y, c, primes[c], factors, 1);
  int64_t s2 = S2(x, y, z, c, primes, factors);
  int64_t phi = s1 + s2;
  int64_t sum = phi + pi_y - 1 - p2;

  return sum;
}

} // namespace primecount
<|endoftext|>


<commit_before>/**
 * @file grAdapter.cc
 * @author Konrad Zemek
 * @copyright (C) 2014 ACK CYFRONET AGH
 * @copyright This software is released under the MIT license cited in
 * 'LICENSE.txt'
 */

#include "auth/grAdapter.h"

#include "auth/authException.h"
#include "config.h"
#include "context.h"
#include "logging.h"

#include <boost/algorithm/string.hpp>
#include <boost/archive/iterators/binary_from_base64.hpp>
#include <boost/archive/iterators/transform_width.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <json11.hpp>

#include <array>
#include <chrono>
#include <fstream>
#include <istream>
#include <ostream>
#include <sstream>

using namespace std::literals::chrono_literals;

namespace one {
namespace client {

static constexpr const char *OPENID_CLIENT_TOKENS_ENDPOINT =
    "/openid/client/tokens";

namespace auth {

GRAdapter::GRAdapter(std::string clientName,
    boost::filesystem::path userDataDir, std::string hostname,
    const unsigned int port, const bool checkCertificate)
    : m_clientName{std::move(clientName)}
    , m_userDataDir{std::move(userDataDir)}
    , m_hostname{std::move(hostname)}
    , m_port{port}
    , m_checkCertificate{checkCertificate}
{
}

boost::optional<TokenAuthDetails> GRAdapter::retrieveToken() const
{
    const auto accessTokenFile = tokenFilePath();

    boost::system::error_code ec;
    const auto exists = boost::filesystem::exists(accessTokenFile, ec);
    if (ec || !exists) {
        LOG(INFO) << "No previously saved authorization details exist under "
                     "path " << accessTokenFile.string();
        return {};
    }

    boost::filesystem::ifstream stream{accessTokenFile};

    TokenAuthDetails auth;
    stream >> auth;
    if (!stream) {
        LOG(WARNING) << "Failed to retrieve authorization details from "
                     << accessTokenFile.string();
        return {};
    }

    if (auth.expirationTime() < std::chrono::system_clock::now() + 1min) {
        LOG(INFO) << "Saved Access Token expired. Refreshing";
        try {
            return refreshAccess(auth);
        }
        catch (const BadAccess &e) {
            LOG(WARNING) << "Authorization error: " << e.what();
            return {}; // Try with new credentials
        }
    }

    return auth;
}

TokenAuthDetails GRAdapter::exchangeCode(const std::string &code) const
{
    using namespace json11;

    LOG(INFO) << "Exchanging OpenID Authorization Code for authorization "
                 "details. Identifying as '" << m_clientName << "'";

    const auto content =
        Json{Json::object{{"grant_type", "authorization_code"}, {"code", code},
                 {"client_name", m_clientName}}}.dump();

    return communicate(content);
}

TokenAuthDetails GRAdapter::refreshAccess(const TokenAuthDetails &details) const
{
    using namespace json11;

    LOG(INFO) << "Refreshing OpenID Access Token";

    const auto content =
        Json{Json::object{{"grant_type", "refresh_token"},
                 {"refresh_token", details.refreshToken()}}}.dump();

    return communicate(content);
}

TokenAuthDetails GRAdapter::communicate(const std::string &content) const
{
    boost::asio::io_service ioService;
    const auto socket = connect(ioService);
    requestToken(content, *socket);
    const auto response = getResponse(*socket);
    return parseToken(response);
}

void GRAdapter::requestToken(
    const std::string &content, GRAdapter::Socket &socket) const
{
    boost::asio::streambuf request;
    std::ostream requestStream(&request);
    requestStream << "POST " << OPENID_CLIENT_TOKENS_ENDPOINT << " HTTP/1.1\r\n"
                  << "Host: " << m_hostname << ":" << m_port << "\r\n"
                  << "User-Agent: oneclient\r\n"
                  << "Connection: close\r\n"
                  << "Accept: application/json\r\n"
                  << "Content-Type: application/json\r\n"
                  << "Content-Length: " << content.size() << "\r\n"
                  << "\r\n" << content;

    requestStream.flush();

    const auto requestSize = request.size();
    const auto writtenSize = boost::asio::write(socket, request);
    if (writtenSize != requestSize)
        throw AuthException{"error while sending a request"};
}

std::string GRAdapter::getResponse(GRAdapter::Socket &socket) const
{
    boost::asio::streambuf response;
    boost::asio::read_until(socket, response, "\r\n");

    std::istream responseStream(&response);

    std::string httpVersion;
    unsigned int statusCode;
    std::string statusMessage;
    responseStream >> httpVersion >> statusCode;
    std::getline(responseStream, statusMessage);

    if (!responseStream || !boost::algorithm::starts_with(httpVersion, "HTTP/"))
        throw AuthException{"malformed response headers"};

    const auto headersSize =
        boost::asio::read_until(socket, response, "\r\n\r\n");
    response.consume(headersSize);

    boost::system::error_code ec;
    boost::asio::read(socket, response, boost::asio::transfer_all(), ec);
    if (ec != boost::asio::error::eof)
        throw AuthException{"malformed response: " + ec.message()};

    std::istreambuf_iterator<char> eos;
    std::string content{std::istreambuf_iterator<char>{responseStream}, eos};

    if (statusCode >= 400 && statusCode <= 499)
        throw BadAccess{"invalid data used to access Global Registry. "
                        "Status: " +
            std::to_string(statusCode) + ". Response: '" + content + "'"};

    if (statusCode != 200)
        throw AuthException{"Global Registry responded with non-ok code " +
            std::to_string(statusCode) + ". Response: '" + content +
                    "'"};

    return content;
}

TokenAuthDetails GRAdapter::parseToken(const std::string &response) const
{
    std::string err;
    const auto json = json11::Json::parse(response, err);

    if (!err.empty())
        throw AuthException{"malformed JSON response: " + err};

    const auto accessToken = json["access_token"].string_value();
    const auto refreshToken = json["refresh_token"].string_value();
    const auto jwt = json["id_token"].string_value();
    const auto expiresIn = json["expires_in"].int_value();

    using unbase = boost::archive::iterators::transform_width<
        boost::archive::iterators::binary_from_base64<
            std::string::const_iterator>,
        8, 6>;

    std::vector<std::string> items;
    boost::algorithm::split(items, jwt, boost::is_any_of("."));
    const std::string idTokenRaw{
        unbase{items[1].begin()}, unbase{items[1].end()}};

    const auto idTokenJson = json11::Json::parse(idTokenRaw, err);

    if (!err.empty())
        throw AuthException{"malformed id_token: " + err};

    TokenAuthDetails auth{accessToken, refreshToken,
        idTokenJson["sub"].string_value(), expiresIn};

    boost::filesystem::ofstream stream{tokenFilePath(), std::ios_base::trunc};
    stream << auth;
    if (!stream)
        LOG(WARNING) << "Failed to save authorization details to a file: "
                     << tokenFilePath().string();

    return auth;
}

std::unique_ptr<GRAdapter::Socket> GRAdapter::connect(
    boost::asio::io_service &ioService) const
{
    namespace ssl = boost::asio::ssl;
    using boost::asio::ip::tcp;

    tcp::resolver resolver{ioService};
    tcp::resolver::query query{m_hostname, std::to_string(m_port),
        boost::asio::ip::resolver_query_base::numeric_service};

    auto iterator = resolver.resolve(query);

    ssl::context ctx{ssl::context::method::tlsv12_client};
    ctx.set_default_verify_paths();

    auto socket = std::make_unique<Socket>(ioService, ctx);
    socket->set_verify_mode(m_checkCertificate ? boost::asio::ssl::verify_peer
                                               : boost::asio::ssl::verify_none);
    socket->set_verify_callback(ssl::rfc2818_verification{m_hostname});

    boost::asio::connect(socket->lowest_layer(), iterator);
    socket->lowest_layer().set_option(tcp::no_delay(true));
    socket->handshake(ssl::stream_base::client);

    return socket;
}

boost::filesystem::path GRAdapter::tokenFilePath() const
{
    return m_userDataDir / "accessToken";
}

} // namespace auth
} // namespace client
} // namespace one
<commit_msg>VFS-1142 Remove unused config.h import.<commit_after>/**
 * @file grAdapter.cc
 * @author Konrad Zemek
 * @copyright (C) 2014 ACK CYFRONET AGH
 * @copyright This software is released under the MIT license cited in
 * 'LICENSE.txt'
 */

#include "auth/grAdapter.h"

#include "auth/authException.h"
#include "context.h"
#include "logging.h"

#include <boost/algorithm/string.hpp>
#include <boost/archive/iterators/binary_from_base64.hpp>
#include <boost/archive/iterators/transform_width.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <json11.hpp>

#include <array>
#include <chrono>
#include <fstream>
#include <istream>
#include <ostream>
#include <sstream>

using namespace std::literals::chrono_literals;

namespace one {
namespace client {

static constexpr const char *OPENID_CLIENT_TOKENS_ENDPOINT =
    "/openid/client/tokens";

namespace auth {

GRAdapter::GRAdapter(std::string clientName,
    boost::filesystem::path userDataDir, std::string hostname,
    const unsigned int port, const bool checkCertificate)
    : m_clientName{std::move(clientName)}
    , m_userDataDir{std::move(userDataDir)}
    , m_hostname{std::move(hostname)}
    , m_port{port}
    , m_checkCertificate{checkCertificate}
{
}

boost::optional<TokenAuthDetails> GRAdapter::retrieveToken() const
{
    const auto accessTokenFile = tokenFilePath();

    boost::system::error_code ec;
    const auto exists = boost::filesystem::exists(accessTokenFile, ec);
    if (ec || !exists) {
        LOG(INFO) << "No previously saved authorization details exist under "
                     "path " << accessTokenFile.string();
        return {};
    }

    boost::filesystem::ifstream stream{accessTokenFile};

    TokenAuthDetails auth;
    stream >> auth;
    if (!stream) {
        LOG(WARNING) << "Failed to retrieve authorization details from "
                     << accessTokenFile.string();
        return {};
    }

    if (auth.expirationTime() < std::chrono::system_clock::now() + 1min) {
        LOG(INFO) << "Saved Access Token expired. Refreshing";
        try {
            return refreshAccess(auth);
        }
        catch (const BadAccess &e) {
            LOG(WARNING) << "Authorization error: " << e.what();
            return {}; // Try with new credentials
        }
    }

    return auth;
}

TokenAuthDetails GRAdapter::exchangeCode(const std::string &code) const
{
    using namespace json11;

    LOG(INFO) << "Exchanging OpenID Authorization Code for authorization "
                 "details. Identifying as '" << m_clientName << "'";

    const auto content =
        Json{Json::object{{"grant_type", "authorization_code"}, {"code", code},
                 {"client_name", m_clientName}}}.dump();

    return communicate(content);
}

TokenAuthDetails GRAdapter::refreshAccess(const TokenAuthDetails &details) const
{
    using namespace json11;

    LOG(INFO) << "Refreshing OpenID Access Token";

    const auto content =
        Json{Json::object{{"grant_type", "refresh_token"},
                 {"refresh_token", details.refreshToken()}}}.dump();

    return communicate(content);
}

TokenAuthDetails GRAdapter::communicate(const std::string &content) const
{
    boost::asio::io_service ioService;
    const auto socket = connect(ioService);
    requestToken(content, *socket);
    const auto response = getResponse(*socket);
    return parseToken(response);
}

void GRAdapter::requestToken(
    const std::string &content, GRAdapter::Socket &socket) const
{
    boost::asio::streambuf request;
    std::ostream requestStream(&request);
    requestStream << "POST " << OPENID_CLIENT_TOKENS_ENDPOINT << " HTTP/1.1\r\n"
                  << "Host: " << m_hostname << ":" << m_port << "\r\n"
                  << "User-Agent: oneclient\r\n"
                  << "Connection: close\r\n"
                  << "Accept: application/json\r\n"
                  << "Content-Type: application/json\r\n"
                  << "Content-Length: " << content.size() << "\r\n"
                  << "\r\n" << content;

    requestStream.flush();

    const auto requestSize = request.size();
    const auto writtenSize = boost::asio::write(socket, request);
    if (writtenSize != requestSize)
        throw AuthException{"error while sending a request"};
}

std::string GRAdapter::getResponse(GRAdapter::Socket &socket) const
{
    boost::asio::streambuf response;
    boost::asio::read_until(socket, response, "\r\n");

    std::istream responseStream(&response);

    std::string httpVersion;
    unsigned int statusCode;
    std::string statusMessage;
    responseStream >> httpVersion >> statusCode;
    std::getline(responseStream, statusMessage);

    if (!responseStream || !boost::algorithm::starts_with(httpVersion, "HTTP/"))
        throw AuthException{"malformed response headers"};

    const auto headersSize =
        boost::asio::read_until(socket, response, "\r\n\r\n");
    response.consume(headersSize);

    boost::system::error_code ec;
    boost::asio::read(socket, response, boost::asio::transfer_all(), ec);
    if (ec != boost::asio::error::eof)
        throw AuthException{"malformed response: " + ec.message()};

    std::istreambuf_iterator<char> eos;
    std::string content{std::istreambuf_iterator<char>{responseStream}, eos};

    if (statusCode >= 400 && statusCode <= 499)
        throw BadAccess{"invalid data used to access Global Registry. "
                        "Status: " +
            std::to_string(statusCode) + ". Response: '" + content + "'"};

    if (statusCode != 200)
        throw AuthException{"Global Registry responded with non-ok code " +
            std::to_string(statusCode) + ". Response: '" + content +
                    "'"};

    return content;
}

TokenAuthDetails GRAdapter::parseToken(const std::string &response) const
{
    std::string err;
    const auto json = json11::Json::parse(response, err);

    if (!err.empty())
        throw AuthException{"malformed JSON response: " + err};

    const auto accessToken = json["access_token"].string_value();
    const auto refreshToken = json["refresh_token"].string_value();
    const auto jwt = json["id_token"].string_value();
    const auto expiresIn = json["expires_in"].int_value();

    using unbase = boost::archive::iterators::transform_width<
        boost::archive::iterators::binary_from_base64<
            std::string::const_iterator>,
        8, 6>;

    std::vector<std::string> items;
    boost::algorithm::split(items, jwt, boost::is_any_of("."));
    const std::string idTokenRaw{
        unbase{items[1].begin()}, unbase{items[1].end()}};

    const auto idTokenJson = json11::Json::parse(idTokenRaw, err);

    if (!err.empty())
        throw AuthException{"malformed id_token: " + err};

    TokenAuthDetails auth{accessToken, refreshToken,
        idTokenJson["sub"].string_value(), expiresIn};

    boost::filesystem::ofstream stream{tokenFilePath(), std::ios_base::trunc};
    stream << auth;
    if (!stream)
        LOG(WARNING) << "Failed to save authorization details to a file: "
                     << tokenFilePath().string();

    return auth;
}

std::unique_ptr<GRAdapter::Socket> GRAdapter::connect(
    boost::asio::io_service &ioService) const
{
    namespace ssl = boost::asio::ssl;
    using boost::asio::ip::tcp;

    tcp::resolver resolver{ioService};
    tcp::resolver::query query{m_hostname, std::to_string(m_port),
        boost::asio::ip::resolver_query_base::numeric_service};

    auto iterator = resolver.resolve(query);

    ssl::context ctx{ssl::context::method::tlsv12_client};
    ctx.set_default_verify_paths();

    auto socket = std::make_unique<Socket>(ioService, ctx);
    socket->set_verify_mode(m_checkCertificate ? boost::asio::ssl::verify_peer
                                               : boost::asio::ssl::verify_none);
    socket->set_verify_callback(ssl::rfc2818_verification{m_hostname});

    boost::asio::connect(socket->lowest_layer(), iterator);
    socket->lowest_layer().set_option(tcp::no_delay(true));
    socket->handshake(ssl::stream_base::client);

    return socket;
}

boost::filesystem::path GRAdapter::tokenFilePath() const
{
    return m_userDataDir / "accessToken";
}

} // namespace auth
} // namespace client
} // namespace one
<|endoftext|>