<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: dptabdat.cxx,v $
 * $Revision: 1.17 $
 *
 * 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_sc.hxx"

// INCLUDE ---------------------------------------------------------------

#include <cstdio>
#include <rtl/math.hxx>
#include <tools/debug.hxx>
#include <tools/date.hxx>
#include <unotools/transliterationwrapper.hxx>
#include <unotools/collatorwrapper.hxx>

#include <com/sun/star/sheet/DataPilotFieldFilter.hpp>

#include "dptabdat.hxx"
#include "global.hxx"
#include "dpcachetable.hxx"
#include "dptabres.hxx"

using namespace ::com::sun::star;
using ::com::sun::star::uno::Sequence;
using ::com::sun::star::uno::Any;
using ::std::vector;
using ::std::set;
using ::std::hash_map;

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

BOOL ScDPItemData::IsCaseInsEqual( const ScDPItemData& r ) const
{
    //! pass Transliteration?
    //! inline?
    return bHasValue ? ( r.bHasValue && rtl::math::approxEqual( fValue, r.fValue ) ) :
                       ( !r.bHasValue &&
                        ScGlobal::pTransliteration->isEqual( aString, r.aString ) );
}

size_t ScDPItemData::Hash() const
{
    if ( bHasValue )
        return (size_t) rtl::math::approxFloor( fValue );
    else
        // If we do unicode safe case insensitive hash we can drop
        // ScDPItemData::operator== and use ::IsCasInsEqual
        return rtl_ustr_hashCode_WithLength( aString.GetBuffer(), aString.Len() );
}

BOOL ScDPItemData::operator==( const ScDPItemData& r ) const
{
    if ( bHasValue )
    {
        if ( r.bHasValue )
            return rtl::math::approxEqual( fValue, r.fValue );
        else
            return FALSE;
    }
    else if ( r.bHasValue )
        return FALSE;
    else
        // need exact equality until we have a safe case insensitive string hash
        return aString == r.aString;
}

sal_Int32 ScDPItemData::Compare( const ScDPItemData& rA,
                                 const ScDPItemData& rB )
{
    if ( rA.bHasValue )
    {
        if ( rB.bHasValue )
        {
            if ( rtl::math::approxEqual( rA.fValue, rB.fValue ) )
                return 0;
            else if ( rA.fValue < rB.fValue )
                return -1;
            else
                return 1;
        }
        else
            return -1;           // values first
    }
    else if ( rB.bHasValue )
        return 1;                // values first
    else
        return ScGlobal::pCollator->compareString( rA.aString, rB.aString );
}

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

ScDPTableData::CalcInfo::CalcInfo() :
    bRepeatIfEmpty(false)
{
}

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

ScDPTableData::ScDPTableData()
{
    nLastDateVal = nLastHier = nLastLevel = nLastRet = -1;      // invalid

    //! reset before new calculation (in case the base date is changed)
}

ScDPTableData::~ScDPTableData()
{
}

long ScDPTableData::GetDatePart( long nDateVal, long nHierarchy, long nLevel )
{
    if ( nDateVal == nLastDateVal && nHierarchy == nLastHier && nLevel == nLastLevel )
        return nLastRet;

    Date aDate( 30,12,1899 );                   //! get from source data (and cache here)
    aDate += nDateVal;

    long nRet = 0;
    switch (nHierarchy)
    {
        case SC_DAPI_HIERARCHY_QUARTER:
            switch (nLevel)
            {
                case 0: nRet = aDate.GetYear();                 break;
                case 1: nRet = (aDate.GetMonth()-1) / 3 + 1;    break;
                case 2: nRet = aDate.GetMonth();                break;
                case 3: nRet = aDate.GetDay();                  break;
                default:
                    DBG_ERROR("GetDatePart: wrong level");
            }
            break;
        case SC_DAPI_HIERARCHY_WEEK:
            switch (nLevel)
            {
                //! use settings for different definitions
                case 0: nRet = aDate.GetYear();                 break;      //!...
                case 1: nRet = aDate.GetWeekOfYear();           break;
                case 2: nRet = (long)aDate.GetDayOfWeek();      break;
                default:
                    DBG_ERROR("GetDatePart: wrong level");
            }
            break;
        default:
            DBG_ERROR("GetDatePart: wrong hierarchy");
    }

    nLastDateVal = nDateVal;
    nLastHier    = nHierarchy;
    nLastLevel   = nLevel;
    nLastRet     = nRet;

    return nRet;
}

bool ScDPTableData::IsRepeatIfEmpty()
{
    return false;
}

void ScDPTableData::CreateCacheTable()
{
    fprintf(stdout, "ScDPTableData::CreateCacheTable: un-implemented...\n");fflush(stdout);
}

void ScDPTableData::FilterCacheTable(const vector<ScDPCacheTable::Criterion>&)
{
    fprintf(stdout, "ScDPTableData::FilterCacheTable: un-implemented...\n");
}

void ScDPTableData::GetDrillDownData(const vector<ScDPCacheTable::Criterion>&, Sequence< Sequence<Any> >&)
{
    fprintf(stdout, "ScDPTableData::GetDrillDownData: un-implemented...\n");fflush(stdout);
}

void ScDPTableData::CalcResults(CalcInfo&, bool)
{
    fprintf(stdout, "ScDPTableData::CalcResults: un-implemented...\n");fflush(stdout);
}

UINT32 ScDPTableData::GetNumberFormat(long)
{
    return 0;           // default format
}

BOOL ScDPTableData::IsBaseForGroup(long) const
{
    return FALSE;       // always false
}

long ScDPTableData::GetGroupBase(long) const
{
    return -1;          // always none
}

BOOL ScDPTableData::IsNumOrDateGroup(long) const
{
    return FALSE;       // always false
}

BOOL ScDPTableData::IsInGroup( const ScDPItemData&, long,
                               const ScDPItemData&, long ) const
{
    DBG_ERROR("IsInGroup shouldn't be called for non-group data");
    return FALSE;
}

BOOL ScDPTableData::HasCommonElement( const ScDPItemData&, long,
                                      const ScDPItemData&, long ) const
{
    DBG_ERROR("HasCommonElement shouldn't be called for non-group data");
    return FALSE;
}

void ScDPTableData::FillRowDataFromCacheTable(sal_Int32 nRow, const ScDPCacheTable& rCacheTable,
                                        const CalcInfo& rInfo, CalcRowData& rData)
{
    // column dimensions
    GetItemData(rCacheTable, nRow, rInfo.aColLevelDims, rData.aColData);

    // row dimensions
    GetItemData(rCacheTable, nRow, rInfo.aRowLevelDims, rData.aRowData);

    // page dimensions
    GetItemData(rCacheTable, nRow, rInfo.aPageDims, rData.aPageData);

    sal_Int32 n = rInfo.aDataSrcCols.size();
    for (sal_Int32 i = 0; i < n; ++i)
    {
        long nDim = rInfo.aDataSrcCols[i];
        rData.aValues.push_back( ScDPValueData() );
        ScDPValueData& rVal = rData.aValues.back();
        const ScDPCacheTable::Cell* pCell = rCacheTable.getCell(static_cast<SCCOL>(nDim), static_cast<SCROW>(nRow));
        if (pCell)
        {
            rVal.fValue = pCell->mbNumeric ? pCell->mfValue : 0.0;
            rVal.nType = pCell->mnType;
        }
        else
            rVal.Set(0.0, SC_VALTYPE_EMPTY);
    }
}

void ScDPTableData::ProcessRowData(CalcInfo& rInfo, CalcRowData& rData, bool bAutoShow)
{
    if (!bAutoShow)
    {
        rInfo.pColRoot->LateInitFrom(rInfo.aColDims, rInfo.aColLevels, rData.aColData, 0, *rInfo.pInitState);
        rInfo.pRowRoot->LateInitFrom(rInfo.aRowDims, rInfo.aRowLevels, rData.aRowData, 0, *rInfo.pInitState);
    }

    if ( ( !rInfo.pColRoot->GetChildDimension() || rInfo.pColRoot->GetChildDimension()->IsValidEntry(rData.aColData) ) &&
         ( !rInfo.pRowRoot->GetChildDimension() || rInfo.pRowRoot->GetChildDimension()->IsValidEntry(rData.aRowData) ) )
    {
        //! single process method with ColMembers, RowMembers and data !!!
        if (rInfo.pColRoot->GetChildDimension())
        {
            vector<ScDPItemData> aEmptyData;
            rInfo.pColRoot->GetChildDimension()->ProcessData(rData.aColData, NULL, aEmptyData, rData.aValues);
        }

        rInfo.pRowRoot->ProcessData(rData.aRowData, rInfo.pColRoot->GetChildDimension(),
                                    rData.aColData, rData.aValues);
    }
}

void ScDPTableData::CalcResultsFromCacheTable(const ScDPCacheTable& rCacheTable, CalcInfo& rInfo, bool bAutoShow)
{
    sal_Int32 nRowSize = rCacheTable.getRowSize();
    for (sal_Int32 nRow = 0; nRow < nRowSize; ++nRow)
    {
        if (!rCacheTable.isRowActive(nRow))
            continue;

        CalcRowData aData;
        FillRowDataFromCacheTable(nRow, rCacheTable, rInfo, aData);
        ProcessRowData(rInfo, aData, bAutoShow);
    }
}

void ScDPTableData::GetItemData(const ScDPCacheTable& rCacheTable, sal_Int32 nRow,
                                const vector<long>& rDims, vector<ScDPItemData>& rItemData)
{
    sal_Int32 nDimSize = rDims.size();
    for (sal_Int32 i = 0; i < nDimSize; ++i)
    {
        long nDim = rDims[i];
        rItemData.push_back( ScDPItemData() );
        ScDPItemData& rData = rItemData.back();
        if (getIsDataLayoutDimension(nDim))
        {
            rData.SetString(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("x")));
            continue;
        }

        const ScDPCacheTable::Cell* pCell = rCacheTable.getCell(static_cast<SCCOL>(nDim), static_cast<SCROW>(nRow), IsRepeatIfEmpty());
        if (!pCell || pCell->mnType == SC_VALTYPE_EMPTY)
            continue;

        const String* pString = ScSharedString::getString(pCell->mnStrId);
        if (!pString)
            continue;

        rData.aString = *pString;
        rData.bHasValue = false;
        if (pCell->mbNumeric)
        {
            rData.bHasValue = true;
            rData.fValue = pCell->mfValue;
        }
    }
}

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

<commit_msg>INTEGRATION: CWS sb91 (1.16.82); FILE MERGED 2008/07/11 09:38:10 sb 1.16.82.1: #i91042# #include <cXXX> vs. <XXX.h> and using identifiers without std:: prefix (which is necessary for old MSVC versions)<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: dptabdat.cxx,v $
 * $Revision: 1.18 $
 *
 * 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_sc.hxx"

// INCLUDE ---------------------------------------------------------------

#include <stdio.h>
#include <rtl/math.hxx>
#include <tools/debug.hxx>
#include <tools/date.hxx>
#include <unotools/transliterationwrapper.hxx>
#include <unotools/collatorwrapper.hxx>

#include <com/sun/star/sheet/DataPilotFieldFilter.hpp>

#include "dptabdat.hxx"
#include "global.hxx"
#include "dpcachetable.hxx"
#include "dptabres.hxx"

using namespace ::com::sun::star;
using ::com::sun::star::uno::Sequence;
using ::com::sun::star::uno::Any;
using ::std::vector;
using ::std::set;
using ::std::hash_map;

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

BOOL ScDPItemData::IsCaseInsEqual( const ScDPItemData& r ) const
{
    //! pass Transliteration?
    //! inline?
    return bHasValue ? ( r.bHasValue && rtl::math::approxEqual( fValue, r.fValue ) ) :
                       ( !r.bHasValue &&
                        ScGlobal::pTransliteration->isEqual( aString, r.aString ) );
}

size_t ScDPItemData::Hash() const
{
    if ( bHasValue )
        return (size_t) rtl::math::approxFloor( fValue );
    else
        // If we do unicode safe case insensitive hash we can drop
        // ScDPItemData::operator== and use ::IsCasInsEqual
        return rtl_ustr_hashCode_WithLength( aString.GetBuffer(), aString.Len() );
}

BOOL ScDPItemData::operator==( const ScDPItemData& r ) const
{
    if ( bHasValue )
    {
        if ( r.bHasValue )
            return rtl::math::approxEqual( fValue, r.fValue );
        else
            return FALSE;
    }
    else if ( r.bHasValue )
        return FALSE;
    else
        // need exact equality until we have a safe case insensitive string hash
        return aString == r.aString;
}

sal_Int32 ScDPItemData::Compare( const ScDPItemData& rA,
                                 const ScDPItemData& rB )
{
    if ( rA.bHasValue )
    {
        if ( rB.bHasValue )
        {
            if ( rtl::math::approxEqual( rA.fValue, rB.fValue ) )
                return 0;
            else if ( rA.fValue < rB.fValue )
                return -1;
            else
                return 1;
        }
        else
            return -1;           // values first
    }
    else if ( rB.bHasValue )
        return 1;                // values first
    else
        return ScGlobal::pCollator->compareString( rA.aString, rB.aString );
}

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

ScDPTableData::CalcInfo::CalcInfo() :
    bRepeatIfEmpty(false)
{
}

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

ScDPTableData::ScDPTableData()
{
    nLastDateVal = nLastHier = nLastLevel = nLastRet = -1;      // invalid

    //! reset before new calculation (in case the base date is changed)
}

ScDPTableData::~ScDPTableData()
{
}

long ScDPTableData::GetDatePart( long nDateVal, long nHierarchy, long nLevel )
{
    if ( nDateVal == nLastDateVal && nHierarchy == nLastHier && nLevel == nLastLevel )
        return nLastRet;

    Date aDate( 30,12,1899 );                   //! get from source data (and cache here)
    aDate += nDateVal;

    long nRet = 0;
    switch (nHierarchy)
    {
        case SC_DAPI_HIERARCHY_QUARTER:
            switch (nLevel)
            {
                case 0: nRet = aDate.GetYear();                 break;
                case 1: nRet = (aDate.GetMonth()-1) / 3 + 1;    break;
                case 2: nRet = aDate.GetMonth();                break;
                case 3: nRet = aDate.GetDay();                  break;
                default:
                    DBG_ERROR("GetDatePart: wrong level");
            }
            break;
        case SC_DAPI_HIERARCHY_WEEK:
            switch (nLevel)
            {
                //! use settings for different definitions
                case 0: nRet = aDate.GetYear();                 break;      //!...
                case 1: nRet = aDate.GetWeekOfYear();           break;
                case 2: nRet = (long)aDate.GetDayOfWeek();      break;
                default:
                    DBG_ERROR("GetDatePart: wrong level");
            }
            break;
        default:
            DBG_ERROR("GetDatePart: wrong hierarchy");
    }

    nLastDateVal = nDateVal;
    nLastHier    = nHierarchy;
    nLastLevel   = nLevel;
    nLastRet     = nRet;

    return nRet;
}

bool ScDPTableData::IsRepeatIfEmpty()
{
    return false;
}

void ScDPTableData::CreateCacheTable()
{
    fprintf(stdout, "ScDPTableData::CreateCacheTable: un-implemented...\n");fflush(stdout);
}

void ScDPTableData::FilterCacheTable(const vector<ScDPCacheTable::Criterion>&)
{
    fprintf(stdout, "ScDPTableData::FilterCacheTable: un-implemented...\n");
}

void ScDPTableData::GetDrillDownData(const vector<ScDPCacheTable::Criterion>&, Sequence< Sequence<Any> >&)
{
    fprintf(stdout, "ScDPTableData::GetDrillDownData: un-implemented...\n");fflush(stdout);
}

void ScDPTableData::CalcResults(CalcInfo&, bool)
{
    fprintf(stdout, "ScDPTableData::CalcResults: un-implemented...\n");fflush(stdout);
}

UINT32 ScDPTableData::GetNumberFormat(long)
{
    return 0;           // default format
}

BOOL ScDPTableData::IsBaseForGroup(long) const
{
    return FALSE;       // always false
}

long ScDPTableData::GetGroupBase(long) const
{
    return -1;          // always none
}

BOOL ScDPTableData::IsNumOrDateGroup(long) const
{
    return FALSE;       // always false
}

BOOL ScDPTableData::IsInGroup( const ScDPItemData&, long,
                               const ScDPItemData&, long ) const
{
    DBG_ERROR("IsInGroup shouldn't be called for non-group data");
    return FALSE;
}

BOOL ScDPTableData::HasCommonElement( const ScDPItemData&, long,
                                      const ScDPItemData&, long ) const
{
    DBG_ERROR("HasCommonElement shouldn't be called for non-group data");
    return FALSE;
}

void ScDPTableData::FillRowDataFromCacheTable(sal_Int32 nRow, const ScDPCacheTable& rCacheTable,
                                        const CalcInfo& rInfo, CalcRowData& rData)
{
    // column dimensions
    GetItemData(rCacheTable, nRow, rInfo.aColLevelDims, rData.aColData);

    // row dimensions
    GetItemData(rCacheTable, nRow, rInfo.aRowLevelDims, rData.aRowData);

    // page dimensions
    GetItemData(rCacheTable, nRow, rInfo.aPageDims, rData.aPageData);

    sal_Int32 n = rInfo.aDataSrcCols.size();
    for (sal_Int32 i = 0; i < n; ++i)
    {
        long nDim = rInfo.aDataSrcCols[i];
        rData.aValues.push_back( ScDPValueData() );
        ScDPValueData& rVal = rData.aValues.back();
        const ScDPCacheTable::Cell* pCell = rCacheTable.getCell(static_cast<SCCOL>(nDim), static_cast<SCROW>(nRow));
        if (pCell)
        {
            rVal.fValue = pCell->mbNumeric ? pCell->mfValue : 0.0;
            rVal.nType = pCell->mnType;
        }
        else
            rVal.Set(0.0, SC_VALTYPE_EMPTY);
    }
}

void ScDPTableData::ProcessRowData(CalcInfo& rInfo, CalcRowData& rData, bool bAutoShow)
{
    if (!bAutoShow)
    {
        rInfo.pColRoot->LateInitFrom(rInfo.aColDims, rInfo.aColLevels, rData.aColData, 0, *rInfo.pInitState);
        rInfo.pRowRoot->LateInitFrom(rInfo.aRowDims, rInfo.aRowLevels, rData.aRowData, 0, *rInfo.pInitState);
    }

    if ( ( !rInfo.pColRoot->GetChildDimension() || rInfo.pColRoot->GetChildDimension()->IsValidEntry(rData.aColData) ) &&
         ( !rInfo.pRowRoot->GetChildDimension() || rInfo.pRowRoot->GetChildDimension()->IsValidEntry(rData.aRowData) ) )
    {
        //! single process method with ColMembers, RowMembers and data !!!
        if (rInfo.pColRoot->GetChildDimension())
        {
            vector<ScDPItemData> aEmptyData;
            rInfo.pColRoot->GetChildDimension()->ProcessData(rData.aColData, NULL, aEmptyData, rData.aValues);
        }

        rInfo.pRowRoot->ProcessData(rData.aRowData, rInfo.pColRoot->GetChildDimension(),
                                    rData.aColData, rData.aValues);
    }
}

void ScDPTableData::CalcResultsFromCacheTable(const ScDPCacheTable& rCacheTable, CalcInfo& rInfo, bool bAutoShow)
{
    sal_Int32 nRowSize = rCacheTable.getRowSize();
    for (sal_Int32 nRow = 0; nRow < nRowSize; ++nRow)
    {
        if (!rCacheTable.isRowActive(nRow))
            continue;

        CalcRowData aData;
        FillRowDataFromCacheTable(nRow, rCacheTable, rInfo, aData);
        ProcessRowData(rInfo, aData, bAutoShow);
    }
}

void ScDPTableData::GetItemData(const ScDPCacheTable& rCacheTable, sal_Int32 nRow,
                                const vector<long>& rDims, vector<ScDPItemData>& rItemData)
{
    sal_Int32 nDimSize = rDims.size();
    for (sal_Int32 i = 0; i < nDimSize; ++i)
    {
        long nDim = rDims[i];
        rItemData.push_back( ScDPItemData() );
        ScDPItemData& rData = rItemData.back();
        if (getIsDataLayoutDimension(nDim))
        {
            rData.SetString(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("x")));
            continue;
        }

        const ScDPCacheTable::Cell* pCell = rCacheTable.getCell(static_cast<SCCOL>(nDim), static_cast<SCROW>(nRow), IsRepeatIfEmpty());
        if (!pCell || pCell->mnType == SC_VALTYPE_EMPTY)
            continue;

        const String* pString = ScSharedString::getString(pCell->mnStrId);
        if (!pString)
            continue;

        rData.aString = *pString;
        rData.bHasValue = false;
        if (pCell->mbNumeric)
        {
            rData.bHasValue = true;
            rData.fValue = pCell->mfValue;
        }
    }
}

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

<|endoftext|>


<commit_before>//===-- Use.cpp - Implement the Use class ---------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/IR/Use.h"
#include "llvm/IR/Value.h"
#include <new>

namespace llvm {

void Use::swap(Use &RHS) {
  Value *V1(Val);
  Value *V2(RHS.Val);
  if (V1 != V2) {
    if (V1) {
      removeFromList();
    }

    if (V2) {
      RHS.removeFromList();
      Val = V2;
      V2->addUse(*this);
    } else {
      Val = 0;
    }

    if (V1) {
      RHS.Val = V1;
      V1->addUse(RHS);
    } else {
      RHS.Val = 0;
    }
  }
}

User *Use::getUser() const {
  const Use *End = getImpliedUser();
  const UserRef *ref = reinterpret_cast<const UserRef *>(End);
  return ref->getInt() ? ref->getPointer()
                       : reinterpret_cast<User *>(const_cast<Use *>(End));
}

// Sets up the waymarking algoritm's tags for a series of Uses. See the
// algorithm details here:
//
//   http://www.llvm.org/docs/ProgrammersManual.html#UserLayout
//
Use *Use::initTags(Use *const Start, Use *Stop) {
  ptrdiff_t Done = 0;
  while (Done < 20) {
    if (Start == Stop--)
      return Start;
    static const PrevPtrTag tags[20] = {
        fullStopTag,  oneDigitTag,  stopTag,      oneDigitTag, oneDigitTag,
        stopTag,      zeroDigitTag, oneDigitTag,  oneDigitTag, stopTag,
        zeroDigitTag, oneDigitTag,  zeroDigitTag, oneDigitTag, stopTag,
        oneDigitTag,  oneDigitTag,  oneDigitTag,  oneDigitTag, stopTag};
    new (Stop) Use(tags[Done++]);
  }

  ptrdiff_t Count = Done;
  while (Start != Stop) {
    --Stop;
    if (!Count) {
      new (Stop) Use(stopTag);
      ++Done;
      Count = Done;
    } else {
      new (Stop) Use(PrevPtrTag(Count & 1));
      Count >>= 1;
      ++Done;
    }
  }

  return Start;
}

void Use::zap(Use *Start, const Use *Stop, bool del) {
  while (Start != Stop)
    (--Stop)->~Use();
  if (del)
    ::operator delete(Start);
}

const Use *Use::getImpliedUser() const {
  const Use *Current = this;

  while (true) {
    unsigned Tag = (Current++)->Prev.getInt();
    switch (Tag) {
    case zeroDigitTag:
    case oneDigitTag:
      continue;

    case stopTag: {
      ++Current;
      ptrdiff_t Offset = 1;
      while (true) {
        unsigned Tag = Current->Prev.getInt();
        switch (Tag) {
        case zeroDigitTag:
        case oneDigitTag:
          ++Current;
          Offset = (Offset << 1) + Tag;
          continue;
        default:
          return Current + Offset;
        }
      }
    }

    case fullStopTag:
      return Current;
    }
  }
}

} // End llvm namespace
<commit_msg>[cleanup] Use early exit and simpler temporary variables to clarify the swap implementation.<commit_after>//===-- Use.cpp - Implement the Use class ---------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/IR/Use.h"
#include "llvm/IR/Value.h"
#include <new>

namespace llvm {

void Use::swap(Use &RHS) {
  if (Val == RHS.Val)
    return;

  if (Val)
    removeFromList();

  Value *OldVal = Val;
  if (RHS.Val) {
    RHS.removeFromList();
    Val = RHS.Val;
    Val->addUse(*this);
  } else {
    Val = 0;
  }

  if (OldVal) {
    RHS.Val = OldVal;
    RHS.Val->addUse(RHS);
  } else {
    RHS.Val = 0;
  }
}

User *Use::getUser() const {
  const Use *End = getImpliedUser();
  const UserRef *ref = reinterpret_cast<const UserRef *>(End);
  return ref->getInt() ? ref->getPointer()
                       : reinterpret_cast<User *>(const_cast<Use *>(End));
}

// Sets up the waymarking algoritm's tags for a series of Uses. See the
// algorithm details here:
//
//   http://www.llvm.org/docs/ProgrammersManual.html#UserLayout
//
Use *Use::initTags(Use *const Start, Use *Stop) {
  ptrdiff_t Done = 0;
  while (Done < 20) {
    if (Start == Stop--)
      return Start;
    static const PrevPtrTag tags[20] = {
        fullStopTag,  oneDigitTag,  stopTag,      oneDigitTag, oneDigitTag,
        stopTag,      zeroDigitTag, oneDigitTag,  oneDigitTag, stopTag,
        zeroDigitTag, oneDigitTag,  zeroDigitTag, oneDigitTag, stopTag,
        oneDigitTag,  oneDigitTag,  oneDigitTag,  oneDigitTag, stopTag};
    new (Stop) Use(tags[Done++]);
  }

  ptrdiff_t Count = Done;
  while (Start != Stop) {
    --Stop;
    if (!Count) {
      new (Stop) Use(stopTag);
      ++Done;
      Count = Done;
    } else {
      new (Stop) Use(PrevPtrTag(Count & 1));
      Count >>= 1;
      ++Done;
    }
  }

  return Start;
}

void Use::zap(Use *Start, const Use *Stop, bool del) {
  while (Start != Stop)
    (--Stop)->~Use();
  if (del)
    ::operator delete(Start);
}

const Use *Use::getImpliedUser() const {
  const Use *Current = this;

  while (true) {
    unsigned Tag = (Current++)->Prev.getInt();
    switch (Tag) {
    case zeroDigitTag:
    case oneDigitTag:
      continue;

    case stopTag: {
      ++Current;
      ptrdiff_t Offset = 1;
      while (true) {
        unsigned Tag = Current->Prev.getInt();
        switch (Tag) {
        case zeroDigitTag:
        case oneDigitTag:
          ++Current;
          Offset = (Offset << 1) + Tag;
          continue;
        default:
          return Current + Offset;
        }
      }
    }

    case fullStopTag:
      return Current;
    }
  }
}

} // End llvm namespace
<|endoftext|>


<commit_before>#include "gvki/Logger.h"
#include <cstdlib>
#include <cstdio>
#include <cassert>
#include <errno.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include "string.h"
#include "gvki/Debug.h"

// For mkdir(). FIXME: Make windows compatible
#include <sys/stat.h>
// For opendir(). FIXME: Make windows compatible
#include <dirent.h>

// For getcwd()
#include <unistd.h>
#define FILE_SEP "/"

using namespace std;
using namespace gvki;

// Maximum number of files or directories
// that can be created
static const int maxFiles = 10000;

Logger& Logger::Singleton()
{
    static Logger l;
    return l;
}

Logger::Logger()
{
    int count = 0;
    bool success= false;

    // FIXME: Reading from the environment probably doesn't belong in here
    // but it makes implementing the singleton a lot easier
    std::string directoryPrefix;

    const char* envTemp = getenv("GVKI_ROOT");
    if (envTemp)
    {
        DEBUG_MSG("Using GVKI_ROOT value as destination for directories");
        DIR* dh = opendir(envTemp);
        if (dh == NULL)
        {
            ERROR_MSG(strerror(errno) << ". Directory was :" << envTemp);
            exit(1);
        }
        else
            closedir(dh);

        directoryPrefix = envTemp;

    }
    else
    {
        // Use the current working directory
        DEBUG_MSG("Using current working directory as destination for directories");

        // FIXME: Hard-coding this size is gross
        char cwdArray[1024];
        char* cwdResult = getcwd(cwdArray, sizeof(cwdArray)/sizeof(char));
        if (!cwdResult)
        {
            ERROR_MSG(strerror(errno) << ". Could not read the current working directory");
            exit(1);
        }
        else
            directoryPrefix = cwdResult;

    }
    directoryPrefix += FILE_SEP "gvki";
    DEBUG_MSG("Directory prefix is \"" << directoryPrefix << "\"");

    // Keep trying a directoryPrefix name with a number as suffix
    // until we find an available one or we exhaust the maximum
    // allowed number
    while (count < maxFiles)
    {
        stringstream ss;
        ss <<  directoryPrefix << "-" << count;
        ++count;

        // Make the directoryPrefix
        if (mkdir(ss.str().c_str(), 0770) != 0)
        {
            if (errno != EEXIST)
            {
                ERROR_MSG(strerror(errno) << ". Directory was :" << directoryPrefix);
                exit(1);
            }

            // It already exists, try again
            continue;
        }

        this->directory = ss.str();
        success = true;
        break;
    }

    if (!success)
    {
        ERROR_MSG("Exhausted available directory names or couldn't create any");
        exit(1);
    }

    DEBUG_MSG("Directory used for logging is \"" << this->directory << "\"");

    openLog();
}

void Logger::openLog()
{
    // FIXME: We should use mkstemp() or something
    std::stringstream ss;
    ss << directory << FILE_SEP << "log.json";
    output = new std::ofstream(ss.str().c_str(), std::ofstream::out | std::ofstream::ate);

    if (! output->good())
    {
        ERROR_MSG("Failed to create file (" << ss.str() <<  ") to write log to");
        exit(1);
    }

    // Start of JSON array
    *output << "[" << std::endl;
}

void Logger::closeLog()
{
    // End of JSON array
    *output << std::endl << "]" << std::endl;
    output->close();
}

Logger::~Logger()
{
    closeLog();
    delete output;
}

void Logger::dump(cl_kernel k)
{
    // Output JSON format defined by
    // http://multicore.doc.ic.ac.uk/tools/GPUVerify/docs/json_format.html
    KernelInfo& ki = kernels[k];

    static bool isFirst = true;

    if (!isFirst)
    {
        // Emit array element seperator
        // to seperate from previous dump
        *output << "," << endl;
    }
    isFirst = false;

    *output << "{" << endl << "\"language\": \"OpenCL\"," << endl;

    std::string kernelSourceFile = dumpKernelSource(ki);

    *output << "\"kernel_file\": \"" << kernelSourceFile << "\"," << endl;

    // FIXME: Teach GPUVerify how to handle non zero global_offset
    // FIXME: Document this json attribute!
    // Only emit global_offset if its non zero
    bool hasNonZeroGlobalOffset = false;
    for (int index=0; index < ki.globalWorkOffset.size() ; ++index)
    {
        if (ki.globalWorkOffset[index] != 0)
            hasNonZeroGlobalOffset = true;
    }
    if (hasNonZeroGlobalOffset)
    {
        *output << "\"global_offset\": ";
        printJSONArray(ki.globalWorkOffset);
        *output << "," << endl;
    }

    *output << "\"global_size\": ";
    printJSONArray(ki.globalWorkSize);
    *output << "," << endl;

    *output << "\"local_size\": ";
    printJSONArray(ki.localWorkSize);
    *output << "," << endl;

    assert(ki.globalWorkOffset.size() == ki.globalWorkSize.size() == ki.localWorkSize.size() &&
            "dimension mismatch");

    *output << "\"entry_point\": \"" << ki.entryPointName << "\"";

    // entry_point might be the last entry is there were no kernel args
    if (ki.arguments.size() == 0)
        *output << endl;
    else
    {
        *output << "," << endl << "\"kernel_arguments\": [ " << endl;
        for (int argIndex=0; argIndex < ki.arguments.size() ; ++argIndex)
        {
            printJSONKernelArgumentInfo(ki.arguments[argIndex]);
            if (argIndex != (ki.arguments.size() -1))
                *output << "," << endl;
        }
        *output << endl << "]" << endl;
    }

    *output << "}";
}

void Logger::printJSONArray(std::vector<size_t>& array)
{
    *output << "[ ";
    for (int index=0; index < array.size(); ++index)
    {
        *output << array[index];

        if (index != (array.size() -1))
            *output << ", ";
    }
    *output << "]";
}

void Logger::printJSONKernelArgumentInfo(ArgInfo& ai)
{
    *output << "{";
    if (ai.argValue == NULL)
    {
        // NULL was passed to clSetKernelArg()
        // That implies its for unallocated memory
        *output << "\"type\": \"array\",";

        // If the arg is for local memory
        if (ai.argSize != sizeof(cl_mem) && ai.argSize != sizeof(cl_sampler))
        {
            // We assume this means this arguments is for local memory
            // where size actually means the sizeof the underlying buffer
            // rather than the size of the type.
            *output << "\"size\" : " << ai.argSize;
        }
        *output << "}";
        return;
    }

    // FIXME:
    // Eurgh... the spec says
    // ```
    // If the argument is a buffer object, the arg_value pointer can be NULL or
    // point to a NULL value in which case a NULL value will be used as the
    // value for the argument declared as a pointer to __global or __constant
    // memory in the kernel.  ```
    //
    // This makes it impossible (seeing as we don't know which address space
    // the arguments are in) to work out the argument type once derefencing the
    // pointer and finding it's equal zero because it could be a scalar constant
    // (of value 0) or it could be an unintialised array!

    DEBUG_MSG("Note sizeof(cl_mem) == " << sizeof(cl_mem));
    // Hack:
    // It's hard to determine what type the argument is.
    // We can't dereference the void* to check if
    // it points to cl_mem we previously stored
    //
    // In some implementations cl_mem will be a pointer
    // which poses a risk if a scalar parameter of the same size
    // as the pointer type.
    if (ai.argSize == sizeof(cl_mem))
    {
       cl_mem mightBecl_mem = *((cl_mem*) ai.argValue);

       // We might be reading invalid data now
       if (buffers.count(mightBecl_mem) == 1)
       {
           // We're going to assume it's cl_mem that we saw before
           *output << "\"type\": \"array\",";
           BufferInfo& bi = buffers[mightBecl_mem];

           *output << "\"size\": " << bi.size << "}";
           return;
       }

    }

    // Hack: a similar hack of the image types
    if (ai.argSize == sizeof(cl_mem))
    {
       cl_mem mightBecl_mem = *((cl_mem*) ai.argValue);

       // We might be reading invalid data now
       if (images.count(mightBecl_mem) == 1)
       {
           // We're going to assume it's cl_mem that we saw before
           *output << "\"type\": \"image\"}";
           return;
       }

    }

    // Hack: a similar hack for the samplers
    if (ai.argSize == sizeof(cl_sampler))
    {
       cl_sampler mightBecl_sampler = *((cl_sampler*) ai.argValue);

       // We might be reading invalid data now
       if (samplers.count(mightBecl_sampler) == 1)
       {
           // We're going to assume it's cl_mem that we saw before
           *output << "\"type\": \"sampler\"}";
           return;
       }

    }

    // I guess it's scalar???
    *output << "\"type\": \"scalar\",";
    *output << " \"value\": \"0x";
    // Print the value as hex
    uint8_t* asByte = (uint8_t*) ai.argValue;
    // We assume the host is little endian so to print the values
    // we need to go through the array bytes backwards
    for (int byteIndex= ai.argSize -1; byteIndex >=0 ; --byteIndex)
    {
       *output << std::hex << std::setfill('0') << std::setw(2) << ( (unsigned) asByte[byteIndex]);
    }
    *output << "\"" << std::dec; //std::hex is sticky so switch back to decimal

    *output << "}";
    return;

}

static bool file_exists(std::string& name) {
	ifstream f(name.c_str());
	bool result = f.good();
	f.close();
	return result;
}

// Define the strict weak ordering over ProgramInfo instances
// Is this correct?
bool ProgramInfoCacheCompare::operator() (const ProgramInfo& lhs, const ProgramInfo& rhs) const
{
    // Use the fact that a strict-weak order is already defined over std::vector<>
    return lhs.sources < rhs.sources;
}

std::string Logger::dumpKernelSource(KernelInfo& ki)
{
    ProgramInfo& pi = programs[ki.program];

    // See if we can used a file that we already printed.
    // This avoid writing duplicate files.
    ProgCacheMapTy::iterator it = WrittenKernelFileCache.find(pi);
    if ( it != WrittenKernelFileCache.end() )
    {
        return it->second;
    }

    int count = 0;
    bool success = false;
    // FIXME: I really want a std::unique_ptr
    std::ofstream* kos = 0;
    std::string theKernelPath;
    while (count < maxFiles)
    {
        stringstream ss;
        ss << ki.entryPointName << "." << count << ".cl";

        ++count;

        std::string withDir = (directory + FILE_SEP) + ss.str();
        if (!file_exists(withDir))
        {
           kos = new std::ofstream(withDir.c_str());

           if (!kos->good())
           {
                kos->close();
                delete kos;
                continue;
           }

           success = true;
           theKernelPath = ss.str();
           break;
        }
    }

    if (!success)
    {
        ERROR_MSG("Failed to log kernel output");
        return std::string("FIXME");
    }

    // Write kernel source

    for (vector<string>::const_iterator b = pi.sources.begin(), e = pi.sources.end(); b != e; ++b)
    {
        *kos << *b;
    }

    // Urgh this is bad, need RAII!
    kos->close();
    delete kos;

    // Store in cache
    assert(WrittenKernelFileCache.count(pi) == 0 && "ProgramInfo already in cache!");
    WrittenKernelFileCache[pi] = theKernelPath;

    return theKernelPath;
}
<commit_msg>Fix incorrectly written assert. This assert would pass if the work_dim was 1 but would fail for larger dimensions. We should add a test case!<commit_after>#include "gvki/Logger.h"
#include <cstdlib>
#include <cstdio>
#include <cassert>
#include <errno.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include "string.h"
#include "gvki/Debug.h"

// For mkdir(). FIXME: Make windows compatible
#include <sys/stat.h>
// For opendir(). FIXME: Make windows compatible
#include <dirent.h>

// For getcwd()
#include <unistd.h>
#define FILE_SEP "/"

using namespace std;
using namespace gvki;

// Maximum number of files or directories
// that can be created
static const int maxFiles = 10000;

Logger& Logger::Singleton()
{
    static Logger l;
    return l;
}

Logger::Logger()
{
    int count = 0;
    bool success= false;

    // FIXME: Reading from the environment probably doesn't belong in here
    // but it makes implementing the singleton a lot easier
    std::string directoryPrefix;

    const char* envTemp = getenv("GVKI_ROOT");
    if (envTemp)
    {
        DEBUG_MSG("Using GVKI_ROOT value as destination for directories");
        DIR* dh = opendir(envTemp);
        if (dh == NULL)
        {
            ERROR_MSG(strerror(errno) << ". Directory was :" << envTemp);
            exit(1);
        }
        else
            closedir(dh);

        directoryPrefix = envTemp;

    }
    else
    {
        // Use the current working directory
        DEBUG_MSG("Using current working directory as destination for directories");

        // FIXME: Hard-coding this size is gross
        char cwdArray[1024];
        char* cwdResult = getcwd(cwdArray, sizeof(cwdArray)/sizeof(char));
        if (!cwdResult)
        {
            ERROR_MSG(strerror(errno) << ". Could not read the current working directory");
            exit(1);
        }
        else
            directoryPrefix = cwdResult;

    }
    directoryPrefix += FILE_SEP "gvki";
    DEBUG_MSG("Directory prefix is \"" << directoryPrefix << "\"");

    // Keep trying a directoryPrefix name with a number as suffix
    // until we find an available one or we exhaust the maximum
    // allowed number
    while (count < maxFiles)
    {
        stringstream ss;
        ss <<  directoryPrefix << "-" << count;
        ++count;

        // Make the directoryPrefix
        if (mkdir(ss.str().c_str(), 0770) != 0)
        {
            if (errno != EEXIST)
            {
                ERROR_MSG(strerror(errno) << ". Directory was :" << directoryPrefix);
                exit(1);
            }

            // It already exists, try again
            continue;
        }

        this->directory = ss.str();
        success = true;
        break;
    }

    if (!success)
    {
        ERROR_MSG("Exhausted available directory names or couldn't create any");
        exit(1);
    }

    DEBUG_MSG("Directory used for logging is \"" << this->directory << "\"");

    openLog();
}

void Logger::openLog()
{
    // FIXME: We should use mkstemp() or something
    std::stringstream ss;
    ss << directory << FILE_SEP << "log.json";
    output = new std::ofstream(ss.str().c_str(), std::ofstream::out | std::ofstream::ate);

    if (! output->good())
    {
        ERROR_MSG("Failed to create file (" << ss.str() <<  ") to write log to");
        exit(1);
    }

    // Start of JSON array
    *output << "[" << std::endl;
}

void Logger::closeLog()
{
    // End of JSON array
    *output << std::endl << "]" << std::endl;
    output->close();
}

Logger::~Logger()
{
    closeLog();
    delete output;
}

void Logger::dump(cl_kernel k)
{
    // Output JSON format defined by
    // http://multicore.doc.ic.ac.uk/tools/GPUVerify/docs/json_format.html
    KernelInfo& ki = kernels[k];

    static bool isFirst = true;

    if (!isFirst)
    {
        // Emit array element seperator
        // to seperate from previous dump
        *output << "," << endl;
    }
    isFirst = false;

    *output << "{" << endl << "\"language\": \"OpenCL\"," << endl;

    std::string kernelSourceFile = dumpKernelSource(ki);

    *output << "\"kernel_file\": \"" << kernelSourceFile << "\"," << endl;

    // FIXME: Teach GPUVerify how to handle non zero global_offset
    // FIXME: Document this json attribute!
    // Only emit global_offset if its non zero
    bool hasNonZeroGlobalOffset = false;
    for (int index=0; index < ki.globalWorkOffset.size() ; ++index)
    {
        if (ki.globalWorkOffset[index] != 0)
            hasNonZeroGlobalOffset = true;
    }
    if (hasNonZeroGlobalOffset)
    {
        *output << "\"global_offset\": ";
        printJSONArray(ki.globalWorkOffset);
        *output << "," << endl;
    }

    *output << "\"global_size\": ";
    printJSONArray(ki.globalWorkSize);
    *output << "," << endl;

    *output << "\"local_size\": ";
    printJSONArray(ki.localWorkSize);
    *output << "," << endl;

    assert( (ki.globalWorkOffset.size() == ki.globalWorkSize.size()) &&
            (ki.globalWorkSize.size() == ki.localWorkSize.size()) &&
            "dimension mismatch");

    *output << "\"entry_point\": \"" << ki.entryPointName << "\"";

    // entry_point might be the last entry is there were no kernel args
    if (ki.arguments.size() == 0)
        *output << endl;
    else
    {
        *output << "," << endl << "\"kernel_arguments\": [ " << endl;
        for (int argIndex=0; argIndex < ki.arguments.size() ; ++argIndex)
        {
            printJSONKernelArgumentInfo(ki.arguments[argIndex]);
            if (argIndex != (ki.arguments.size() -1))
                *output << "," << endl;
        }
        *output << endl << "]" << endl;
    }

    *output << "}";
}

void Logger::printJSONArray(std::vector<size_t>& array)
{
    *output << "[ ";
    for (int index=0; index < array.size(); ++index)
    {
        *output << array[index];

        if (index != (array.size() -1))
            *output << ", ";
    }
    *output << "]";
}

void Logger::printJSONKernelArgumentInfo(ArgInfo& ai)
{
    *output << "{";
    if (ai.argValue == NULL)
    {
        // NULL was passed to clSetKernelArg()
        // That implies its for unallocated memory
        *output << "\"type\": \"array\",";

        // If the arg is for local memory
        if (ai.argSize != sizeof(cl_mem) && ai.argSize != sizeof(cl_sampler))
        {
            // We assume this means this arguments is for local memory
            // where size actually means the sizeof the underlying buffer
            // rather than the size of the type.
            *output << "\"size\" : " << ai.argSize;
        }
        *output << "}";
        return;
    }

    // FIXME:
    // Eurgh... the spec says
    // ```
    // If the argument is a buffer object, the arg_value pointer can be NULL or
    // point to a NULL value in which case a NULL value will be used as the
    // value for the argument declared as a pointer to __global or __constant
    // memory in the kernel.  ```
    //
    // This makes it impossible (seeing as we don't know which address space
    // the arguments are in) to work out the argument type once derefencing the
    // pointer and finding it's equal zero because it could be a scalar constant
    // (of value 0) or it could be an unintialised array!

    DEBUG_MSG("Note sizeof(cl_mem) == " << sizeof(cl_mem));
    // Hack:
    // It's hard to determine what type the argument is.
    // We can't dereference the void* to check if
    // it points to cl_mem we previously stored
    //
    // In some implementations cl_mem will be a pointer
    // which poses a risk if a scalar parameter of the same size
    // as the pointer type.
    if (ai.argSize == sizeof(cl_mem))
    {
       cl_mem mightBecl_mem = *((cl_mem*) ai.argValue);

       // We might be reading invalid data now
       if (buffers.count(mightBecl_mem) == 1)
       {
           // We're going to assume it's cl_mem that we saw before
           *output << "\"type\": \"array\",";
           BufferInfo& bi = buffers[mightBecl_mem];

           *output << "\"size\": " << bi.size << "}";
           return;
       }

    }

    // Hack: a similar hack of the image types
    if (ai.argSize == sizeof(cl_mem))
    {
       cl_mem mightBecl_mem = *((cl_mem*) ai.argValue);

       // We might be reading invalid data now
       if (images.count(mightBecl_mem) == 1)
       {
           // We're going to assume it's cl_mem that we saw before
           *output << "\"type\": \"image\"}";
           return;
       }

    }

    // Hack: a similar hack for the samplers
    if (ai.argSize == sizeof(cl_sampler))
    {
       cl_sampler mightBecl_sampler = *((cl_sampler*) ai.argValue);

       // We might be reading invalid data now
       if (samplers.count(mightBecl_sampler) == 1)
       {
           // We're going to assume it's cl_mem that we saw before
           *output << "\"type\": \"sampler\"}";
           return;
       }

    }

    // I guess it's scalar???
    *output << "\"type\": \"scalar\",";
    *output << " \"value\": \"0x";
    // Print the value as hex
    uint8_t* asByte = (uint8_t*) ai.argValue;
    // We assume the host is little endian so to print the values
    // we need to go through the array bytes backwards
    for (int byteIndex= ai.argSize -1; byteIndex >=0 ; --byteIndex)
    {
       *output << std::hex << std::setfill('0') << std::setw(2) << ( (unsigned) asByte[byteIndex]);
    }
    *output << "\"" << std::dec; //std::hex is sticky so switch back to decimal

    *output << "}";
    return;

}

static bool file_exists(std::string& name) {
	ifstream f(name.c_str());
	bool result = f.good();
	f.close();
	return result;
}

// Define the strict weak ordering over ProgramInfo instances
// Is this correct?
bool ProgramInfoCacheCompare::operator() (const ProgramInfo& lhs, const ProgramInfo& rhs) const
{
    // Use the fact that a strict-weak order is already defined over std::vector<>
    return lhs.sources < rhs.sources;
}

std::string Logger::dumpKernelSource(KernelInfo& ki)
{
    ProgramInfo& pi = programs[ki.program];

    // See if we can used a file that we already printed.
    // This avoid writing duplicate files.
    ProgCacheMapTy::iterator it = WrittenKernelFileCache.find(pi);
    if ( it != WrittenKernelFileCache.end() )
    {
        return it->second;
    }

    int count = 0;
    bool success = false;
    // FIXME: I really want a std::unique_ptr
    std::ofstream* kos = 0;
    std::string theKernelPath;
    while (count < maxFiles)
    {
        stringstream ss;
        ss << ki.entryPointName << "." << count << ".cl";

        ++count;

        std::string withDir = (directory + FILE_SEP) + ss.str();
        if (!file_exists(withDir))
        {
           kos = new std::ofstream(withDir.c_str());

           if (!kos->good())
           {
                kos->close();
                delete kos;
                continue;
           }

           success = true;
           theKernelPath = ss.str();
           break;
        }
    }

    if (!success)
    {
        ERROR_MSG("Failed to log kernel output");
        return std::string("FIXME");
    }

    // Write kernel source

    for (vector<string>::const_iterator b = pi.sources.begin(), e = pi.sources.end(); b != e; ++b)
    {
        *kos << *b;
    }

    // Urgh this is bad, need RAII!
    kos->close();
    delete kos;

    // Store in cache
    assert(WrittenKernelFileCache.count(pi) == 0 && "ProgramInfo already in cache!");
    WrittenKernelFileCache[pi] = theKernelPath;

    return theKernelPath;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: interpr6.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: kz $ $Date: 2008-03-06 15:34:40 $
 *
 *  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_sc.hxx"

#include <math.h>

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

#include "interpre.hxx"

//! #66556# for os2icci3 this function MUST be compiled without optimizations,
//! otherwise it won't work at all or even worse will produce false results!
double ScInterpreter::GetGammaDist(double x, double alpha, double beta)
{
    if (x == 0.0)
        return 0.0;

    x /= beta;
    double gamma = alpha;

    double c = 0.918938533204672741;
    double d[10] = {
        0.833333333333333333E-1,
        -0.277777777777777778E-2,
        0.793650793650793651E-3,
        -0.595238095238095238E-3,
        0.841750841750841751E-3,
        -0.191752691752691753E-2,
        0.641025641025641025E-2,
        -0.295506535947712418E-1,
        0.179644372368830573,
        -0.139243221690590111E1
    };

    double dx = x;
    double dgamma = gamma;
    int maxit = 10000;

    double z = dgamma;
    double den = 1.0;
    while ( z < 10.0 )      //! approx?
    {
        den *= z;
        z += 1.0;
    }

    double z2 = z*z;
    double z3 = z*z2;
    double z4 = z2*z2;
    double z5 = z2*z3;
    double a = ( z - 0.5 ) * log(z) - z + c;
    double b = d[0]/z + d[1]/z3 + d[2]/z5 + d[3]/(z2*z5) + d[4]/(z4*z5) +
               d[5]/(z*z5*z5) + d[6]/(z3*z5*z5) + d[7]/(z5*z5*z5) + d[8]/(z2*z5*z5*z5);
    // double g = exp(a+b) / den;

    double sum = 1.0 / dgamma;
    double term = 1.0 / dgamma;
    double cut1 = dx - dgamma;
    double cut2 = dx * 10000000000.0;

    for ( int i=1; i<=maxit; i++ )
    {
        double ai = i;
        term = dx * term / ( dgamma + ai );
        sum += term;
        double cutoff = cut1 + ( cut2 * term / sum );
        if ( ai > cutoff )
        {
            double t = sum;
            // return pow( dx, dgamma ) * exp( -dx ) * t / g;
            return exp( dgamma * log(dx) - dx - a - b ) * t * den;
        }
    }

//  DBG_ERROR("GetGammaDist bricht nicht ab");

    return 1.0;     // should not happen ...
}

#if 0
//! this algorithm doesn't work right in every cases!
double ScInterpreter::GetGammaDist(double x, double alpha, double beta)
{
    if (x == 0.0)
        return 0.0;
    double fEps = 1.0E-6;
    double fGamma;
    double G = GetLogGamma(alpha);
    x /= beta;
    G = alpha*log(x)-x-G;
    if (x <= alpha+1.0)
    {
        if (x < fEps || fabs(G) >= 500.0)
            fGamma = 0.0;
        else
        {
            double fF = 1.0/alpha;
            double fS = fF;
            double anum = alpha;
            for (USHORT i = 0; i < 100; i++)
            {
                anum += 1.0;
                fF *= x/anum;
                fS += fF;
                if (fF < fEps)
                    i = 100;
            }
            fGamma = fS*exp(G);
        }
    }
    else
    {
        if (fabs(G) >= 500.0)
            fGamma = 1.0;
        else
        {
            double a0, b0, a1, b1, cf, fnorm, a2j, a2j1, cfnew;
            a0 = 0.0; b0 = 1.0; a1 = 1.0;
            b1 = x;
            cf = fEps;
            fnorm = 1.0;
            cfnew = 0.0;
            for (USHORT j = 1; j <= 100; j++)
            {
                a2j = ((double) j) - alpha;
                a2j1 = (double) j;
                a0 = (a1+a2j*a0); // *fnorm;
                b0 = (b1+a2j*b0); // *fnorm;
                a1 = (x*a0+a2j1*a1)*fnorm;
                b1 = (x*b0+a2j1*b1)*fnorm;
                if (b1 != 0.0)
                {
                    fnorm = 1.0/b1;
                    cfnew = a1*fnorm;
                    if (fabs(cf-cfnew)/cf < fEps)
                        j = 101;
                    else
                        cf = cfnew;
                }
            }
            fGamma = 1.0 - exp(G)*cfnew;
        }
    }
    return fGamma;
}
#endif

<commit_msg>INTEGRATION: CWS changefileheader (1.6.32); FILE MERGED 2008/04/01 15:30:02 thb 1.6.32.2: #i85898# Stripping all external header guards 2008/03/31 17:14:17 rt 1.6.32.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: interpr6.cxx,v $
 * $Revision: 1.7 $
 *
 * 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_sc.hxx"

#include <math.h>
#include <tools/debug.hxx>

#include "interpre.hxx"

//! #66556# for os2icci3 this function MUST be compiled without optimizations,
//! otherwise it won't work at all or even worse will produce false results!
double ScInterpreter::GetGammaDist(double x, double alpha, double beta)
{
    if (x == 0.0)
        return 0.0;

    x /= beta;
    double gamma = alpha;

    double c = 0.918938533204672741;
    double d[10] = {
        0.833333333333333333E-1,
        -0.277777777777777778E-2,
        0.793650793650793651E-3,
        -0.595238095238095238E-3,
        0.841750841750841751E-3,
        -0.191752691752691753E-2,
        0.641025641025641025E-2,
        -0.295506535947712418E-1,
        0.179644372368830573,
        -0.139243221690590111E1
    };

    double dx = x;
    double dgamma = gamma;
    int maxit = 10000;

    double z = dgamma;
    double den = 1.0;
    while ( z < 10.0 )      //! approx?
    {
        den *= z;
        z += 1.0;
    }

    double z2 = z*z;
    double z3 = z*z2;
    double z4 = z2*z2;
    double z5 = z2*z3;
    double a = ( z - 0.5 ) * log(z) - z + c;
    double b = d[0]/z + d[1]/z3 + d[2]/z5 + d[3]/(z2*z5) + d[4]/(z4*z5) +
               d[5]/(z*z5*z5) + d[6]/(z3*z5*z5) + d[7]/(z5*z5*z5) + d[8]/(z2*z5*z5*z5);
    // double g = exp(a+b) / den;

    double sum = 1.0 / dgamma;
    double term = 1.0 / dgamma;
    double cut1 = dx - dgamma;
    double cut2 = dx * 10000000000.0;

    for ( int i=1; i<=maxit; i++ )
    {
        double ai = i;
        term = dx * term / ( dgamma + ai );
        sum += term;
        double cutoff = cut1 + ( cut2 * term / sum );
        if ( ai > cutoff )
        {
            double t = sum;
            // return pow( dx, dgamma ) * exp( -dx ) * t / g;
            return exp( dgamma * log(dx) - dx - a - b ) * t * den;
        }
    }

//  DBG_ERROR("GetGammaDist bricht nicht ab");

    return 1.0;     // should not happen ...
}

#if 0
//! this algorithm doesn't work right in every cases!
double ScInterpreter::GetGammaDist(double x, double alpha, double beta)
{
    if (x == 0.0)
        return 0.0;
    double fEps = 1.0E-6;
    double fGamma;
    double G = GetLogGamma(alpha);
    x /= beta;
    G = alpha*log(x)-x-G;
    if (x <= alpha+1.0)
    {
        if (x < fEps || fabs(G) >= 500.0)
            fGamma = 0.0;
        else
        {
            double fF = 1.0/alpha;
            double fS = fF;
            double anum = alpha;
            for (USHORT i = 0; i < 100; i++)
            {
                anum += 1.0;
                fF *= x/anum;
                fS += fF;
                if (fF < fEps)
                    i = 100;
            }
            fGamma = fS*exp(G);
        }
    }
    else
    {
        if (fabs(G) >= 500.0)
            fGamma = 1.0;
        else
        {
            double a0, b0, a1, b1, cf, fnorm, a2j, a2j1, cfnew;
            a0 = 0.0; b0 = 1.0; a1 = 1.0;
            b1 = x;
            cf = fEps;
            fnorm = 1.0;
            cfnew = 0.0;
            for (USHORT j = 1; j <= 100; j++)
            {
                a2j = ((double) j) - alpha;
                a2j1 = (double) j;
                a0 = (a1+a2j*a0); // *fnorm;
                b0 = (b1+a2j*b0); // *fnorm;
                a1 = (x*a0+a2j1*a1)*fnorm;
                b1 = (x*b0+a2j1*b1)*fnorm;
                if (b1 != 0.0)
                {
                    fnorm = 1.0/b1;
                    cfnew = a1*fnorm;
                    if (fabs(cf-cfnew)/cf < fEps)
                        j = 101;
                    else
                        cf = cfnew;
                }
            }
            fGamma = 1.0 - exp(G)*cfnew;
        }
    }
    return fGamma;
}
#endif

<|endoftext|>


<commit_before>#include "amuse/Studio.hpp"

#include <algorithm>

#include "amuse/Engine.hpp"

namespace amuse {

#ifndef NDEBUG
bool Studio::_cyclicCheck(const Studio* leaf) const {
  return std::any_of(m_studiosOut.cbegin(), m_studiosOut.cend(), [leaf](const auto& studio) {
    return leaf == studio.m_targetStudio.get() || studio.m_targetStudio->_cyclicCheck(leaf);
  });
}
#endif

Studio::Studio(Engine& engine, bool mainOut) : m_engine(engine), m_master(engine), m_auxA(engine), m_auxB(engine) {
  if (mainOut && engine.m_defaultStudioReady)
    addStudioSend(engine.getDefaultStudio(), 1.f, 1.f, 1.f);
}

void Studio::addStudioSend(ObjToken<Studio> studio, float dry, float auxA, float auxB) {
  m_studiosOut.emplace_back(studio, dry, auxA, auxB);

  /* Cyclic check */
  assert(!_cyclicCheck(this));
}

void Studio::resetOutputSampleRate(double sampleRate) {
  m_master.resetOutputSampleRate(sampleRate);
  m_auxA.resetOutputSampleRate(sampleRate);
  m_auxB.resetOutputSampleRate(sampleRate);
}
} // namespace amuse
<commit_msg>Studio: std::move studio instance in addStudioSend()<commit_after>#include "amuse/Studio.hpp"

#include <algorithm>

#include "amuse/Engine.hpp"

namespace amuse {

#ifndef NDEBUG
bool Studio::_cyclicCheck(const Studio* leaf) const {
  return std::any_of(m_studiosOut.cbegin(), m_studiosOut.cend(), [leaf](const auto& studio) {
    return leaf == studio.m_targetStudio.get() || studio.m_targetStudio->_cyclicCheck(leaf);
  });
}
#endif

Studio::Studio(Engine& engine, bool mainOut) : m_engine(engine), m_master(engine), m_auxA(engine), m_auxB(engine) {
  if (mainOut && engine.m_defaultStudioReady)
    addStudioSend(engine.getDefaultStudio(), 1.f, 1.f, 1.f);
}

void Studio::addStudioSend(ObjToken<Studio> studio, float dry, float auxA, float auxB) {
  m_studiosOut.emplace_back(std::move(studio), dry, auxA, auxB);

  /* Cyclic check */
  assert(!_cyclicCheck(this));
}

void Studio::resetOutputSampleRate(double sampleRate) {
  m_master.resetOutputSampleRate(sampleRate);
  m_auxA.resetOutputSampleRate(sampleRate);
  m_auxB.resetOutputSampleRate(sampleRate);
}
} // namespace amuse
<|endoftext|>


<commit_before>#include "xchainer/memory.h"

#include <cassert>

#ifdef XCHAINER_ENABLE_CUDA
#include <cuda.h>
#include <cuda_runtime.h>
#endif  // XCHAINER_ENABLE_CUDA

#ifdef XCHAINER_ENABLE_CUDA
#include "xchainer/cuda/cuda_runtime.h"
#endif  // XCHAINER_ENABLE_CUDA
#include "xchainer/device.h"
#include "xchainer/error.h"

namespace xchainer {
namespace internal {

bool IsPointerCudaMemory(const void* ptr) {
#ifdef XCHAINER_ENABLE_CUDA
    cudaPointerAttributes attr = {};
    cudaError_t status = cudaPointerGetAttributes(&attr, ptr);
    switch (status) {
        case cudaSuccess:
            if (attr.isManaged) {
                return true;
            } else {
                throw XchainerError("Non-managed GPU memory is not supported");
            }
        case cudaErrorInvalidValue:
            return false;
        default:
            cuda::CheckError(status);
            break;
    }
    assert(false);  // should never be reached
#else
    (void)ptr;  // unused
    return false;
#endif  // XCHAINER_ENABLE_CUDA
}

std::shared_ptr<void> Allocate(const Device& device, size_t bytesize) {
    if (device == MakeDevice("cpu")) {
        return std::make_unique<uint8_t[]>(bytesize);
#ifdef XCHAINER_ENABLE_CUDA
    } else if (device == MakeDevice("cuda")) {
        void* raw_ptr = nullptr;
        // Be careful to be exception-safe, i.e., do not throw before creating shared_ptr
        cudaError_t status = cudaMallocManaged(&raw_ptr, bytesize, cudaMemAttachGlobal);
        if (status == cudaSuccess) {
            return std::shared_ptr<void>{raw_ptr, cudaFree};
        } else {
            cuda::Throw(status);
        }
        assert(false);  // should never be reached
#endif                  // XCHAINER_ENABLE_CUDA
    } else {
        throw DeviceError("invalid device");
    }
}

void MemoryCopy(void* dst_ptr, const void* src_ptr, size_t bytesize) {
#ifdef XCHAINER_ENABLE_CUDA
    bool is_dst_cuda_memory = IsPointerCudaMemory(dst_ptr);
    bool is_src_cuda_memory = IsPointerCudaMemory(src_ptr);
    if (is_dst_cuda_memory) {
        if (is_src_cuda_memory) {
            // Copy from device to device is faster even in unified memory
            cuda::CheckError(cudaMemcpy(dst_ptr, src_ptr, bytesize, cudaMemcpyDeviceToDevice));
        } else {
            // For pre-6.x GPU architecture, we encountered SEGV with std::memcpy
            // ref. https://github.com/pfnet/xchainer/pull/74
            cuda::CheckError(cudaMemcpy(dst_ptr, src_ptr, bytesize, cudaMemcpyHostToDevice));
        }
    } else {
        if (is_src_cuda_memory) {
            // For pre-6.x GPU architecture, we encountered SEGV with std::memcpy
            // ref. https://github.com/pfnet/xchainer/pull/74
            cuda::CheckError(cudaMemcpy(dst_ptr, src_ptr, bytesize, cudaMemcpyDeviceToHost));
        } else {
            std::memcpy(dst_ptr, src_ptr, bytesize);
        }
    }
#else
    std::memcpy(dst_ptr, src_ptr, bytesize);
#endif  // XCHAINER_ENABLE_CUDA
}

std::shared_ptr<void> MemoryFromBuffer(const Device& device, const std::shared_ptr<void>& src_ptr, size_t bytesize) {
#ifdef XCHAINER_ENABLE_CUDA
    if (device == MakeDevice("cpu")) {
        if (IsPointerCudaMemory(src_ptr.get())) {
            std::shared_ptr<void> dst_ptr = Allocate(device, bytesize);
            cuda::CheckError(cudaMemcpy(dst_ptr.get(), src_ptr.get(), bytesize, cudaMemcpyDeviceToHost));
            return dst_ptr;
        } else {
            return src_ptr;
        }
    } else if (device == MakeDevice("cuda")) {
        if (IsPointerCudaMemory(src_ptr.get())) {
            return src_ptr;
        } else {
            std::shared_ptr<void> dst_ptr = Allocate(device, bytesize);
            cuda::CheckError(cudaMemcpy(dst_ptr.get(), src_ptr.get(), bytesize, cudaMemcpyHostToDevice));
            return dst_ptr;
        }
    } else {
        throw DeviceError("invalid device");
    }
#else
    if (device == MakeDevice("cpu")) {
        return src_ptr;
    } else {
        throw DeviceError("invalid device");
    }
#endif  // XCHAINER_ENABLE_CUDA
}

}  // namespace internal
}  // namespace xchainer
<commit_msg>Avoid unused-parameter warning<commit_after>#include "xchainer/memory.h"

#include <cassert>

#ifdef XCHAINER_ENABLE_CUDA
#include <cuda.h>
#include <cuda_runtime.h>
#endif  // XCHAINER_ENABLE_CUDA

#ifdef XCHAINER_ENABLE_CUDA
#include "xchainer/cuda/cuda_runtime.h"
#endif  // XCHAINER_ENABLE_CUDA
#include "xchainer/device.h"
#include "xchainer/error.h"

namespace xchainer {
namespace internal {

bool IsPointerCudaMemory(const void* ptr) {
#ifdef XCHAINER_ENABLE_CUDA
    cudaPointerAttributes attr = {};
    cudaError_t status = cudaPointerGetAttributes(&attr, ptr);
    switch (status) {
        case cudaSuccess:
            if (attr.isManaged) {
                return true;
            } else {
                throw XchainerError("Non-managed GPU memory is not supported");
            }
        case cudaErrorInvalidValue:
            return false;
        default:
            cuda::CheckError(status);
            break;
    }
    assert(false);  // should never be reached
#else
    (void)ptr;  // unused
    return false;
#endif  // XCHAINER_ENABLE_CUDA
}

std::shared_ptr<void> Allocate(const Device& device, size_t bytesize) {
    if (device == MakeDevice("cpu")) {
        return std::make_unique<uint8_t[]>(bytesize);
#ifdef XCHAINER_ENABLE_CUDA
    } else if (device == MakeDevice("cuda")) {
        void* raw_ptr = nullptr;
        // Be careful to be exception-safe, i.e., do not throw before creating shared_ptr
        cudaError_t status = cudaMallocManaged(&raw_ptr, bytesize, cudaMemAttachGlobal);
        if (status == cudaSuccess) {
            return std::shared_ptr<void>{raw_ptr, cudaFree};
        } else {
            cuda::Throw(status);
        }
        assert(false);  // should never be reached
#endif                  // XCHAINER_ENABLE_CUDA
    } else {
        throw DeviceError("invalid device");
    }
}

void MemoryCopy(void* dst_ptr, const void* src_ptr, size_t bytesize) {
#ifdef XCHAINER_ENABLE_CUDA
    bool is_dst_cuda_memory = IsPointerCudaMemory(dst_ptr);
    bool is_src_cuda_memory = IsPointerCudaMemory(src_ptr);
    if (is_dst_cuda_memory) {
        if (is_src_cuda_memory) {
            // Copy from device to device is faster even in unified memory
            cuda::CheckError(cudaMemcpy(dst_ptr, src_ptr, bytesize, cudaMemcpyDeviceToDevice));
        } else {
            // For pre-6.x GPU architecture, we encountered SEGV with std::memcpy
            // ref. https://github.com/pfnet/xchainer/pull/74
            cuda::CheckError(cudaMemcpy(dst_ptr, src_ptr, bytesize, cudaMemcpyHostToDevice));
        }
    } else {
        if (is_src_cuda_memory) {
            // For pre-6.x GPU architecture, we encountered SEGV with std::memcpy
            // ref. https://github.com/pfnet/xchainer/pull/74
            cuda::CheckError(cudaMemcpy(dst_ptr, src_ptr, bytesize, cudaMemcpyDeviceToHost));
        } else {
            std::memcpy(dst_ptr, src_ptr, bytesize);
        }
    }
#else
    std::memcpy(dst_ptr, src_ptr, bytesize);
#endif  // XCHAINER_ENABLE_CUDA
}

std::shared_ptr<void> MemoryFromBuffer(const Device& device, const std::shared_ptr<void>& src_ptr, size_t bytesize) {
#ifdef XCHAINER_ENABLE_CUDA
    if (device == MakeDevice("cpu")) {
        if (IsPointerCudaMemory(src_ptr.get())) {
            std::shared_ptr<void> dst_ptr = Allocate(device, bytesize);
            cuda::CheckError(cudaMemcpy(dst_ptr.get(), src_ptr.get(), bytesize, cudaMemcpyDeviceToHost));
            return dst_ptr;
        } else {
            return src_ptr;
        }
    } else if (device == MakeDevice("cuda")) {
        if (IsPointerCudaMemory(src_ptr.get())) {
            return src_ptr;
        } else {
            std::shared_ptr<void> dst_ptr = Allocate(device, bytesize);
            cuda::CheckError(cudaMemcpy(dst_ptr.get(), src_ptr.get(), bytesize, cudaMemcpyHostToDevice));
            return dst_ptr;
        }
    } else {
        throw DeviceError("invalid device");
    }
#else
    (void)bytesize;  // unused
    if (device == MakeDevice("cpu")) {
        return src_ptr;
    } else {
        throw DeviceError("invalid device");
    }
#endif  // XCHAINER_ENABLE_CUDA
}

}  // namespace internal
}  // namespace xchainer
<|endoftext|>


<commit_before>#define DEBUG 1
/**
 * File    : C.cpp
 * Author  : Kazune Takahashi
 * Created : 2020/6/28 20:51:44
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/integer/common_factor_rt.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/rational.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::integer::gcd; // for C++14 or for cpp_int
using boost::integer::lcm; // for C++14 or for cpp_int
using boost::multiprecision::cpp_int;
using ll = long long;
using ld = long double;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1'000'000'007LL};
// constexpr ll MOD{998'244'353LL}; // be careful
constexpr ll MAX_SIZE{3'000'010LL};
// constexpr ll MAX_SIZE{30'000'010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
bool ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
    return true;
  }
  return false;
}
template <typename T>
bool ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
    return true;
  }
  return false;
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(Mint const &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(Mint const &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(Mint const &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(Mint const &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(Mint const &a) const { return Mint(*this) += a; }
  Mint operator-(Mint const &a) const { return Mint(*this) -= a; }
  Mint operator*(Mint const &a) const { return Mint(*this) *= a; }
  Mint operator/(Mint const &a) const { return Mint(*this) /= a; }
  bool operator<(Mint const &a) const { return x < a.x; }
  bool operator<=(Mint const &a) const { return x <= a.x; }
  bool operator>(Mint const &a) const { return x > a.x; }
  bool operator>=(Mint const &a) const { return x >= a.x; }
  bool operator==(Mint const &a) const { return x == a.x; }
  bool operator!=(Mint const &a) const { return !(*this == a); }
  Mint power(ll N) const
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, Mint<MOD> const &rhs) { return rhs + lhs; }
template <ll MOD>
Mint<MOD> operator-(ll lhs, Mint<MOD> const &rhs) { return -rhs + lhs; }
template <ll MOD>
Mint<MOD> operator*(ll lhs, Mint<MOD> const &rhs) { return rhs * lhs; }
template <ll MOD>
Mint<MOD> operator/(ll lhs, Mint<MOD> const &rhs) { return Mint<MOD>{lhs} / rhs; }
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a) { return stream >> a.x; }
template <ll MOD>
ostream &operator<<(ostream &stream, Mint<MOD> const &a) { return stream << a.x; }
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i{2LL}; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i{1LL}; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
// ----- for C++17 -----
template <typename T, typename enable_if<is_integral<T>::value>::type * = nullptr>
size_t popcount(T x) { return bitset<64>(x).count(); }
size_t popcount(string const &S) { return bitset<200010>{S}.count(); }
// ----- Infty -----
template <typename T>
constexpr T Infty() { return numeric_limits<T>::max(); }
template <typename T>
constexpr T mInfty() { return numeric_limits<T>::min(); }
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1'000'000'000'000'010LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}

// ----- Solve -----

#if DEBUG == 1
constexpr int D = 5;
#else
constexpr int D = 365;
#endif
constexpr int C = 26;

class Solve
{
  vector<ll> c;
  vector<vector<ll>> s;
  vector<int> t;
  vector<set<int>> contestDays;
  ll totalScore;

public:
  Solve() : c(C), s(D, vector<ll>(C, 0)), t(D), contestDays(C), totalScore{0}
  {
    for (auto i{0}; i < C; ++i)
    {
      cin >> c[i];
    }
    for (auto i{0}; i < D; ++i)
    {
      for (auto j{0}; j < C; ++j)
      {
        cin >> s[i][j];
      }
    }
    for (auto i{0}; i < C; ++i)
    {
      contestDays[i].insert(0);
      contestDays[i].insert(D + 1);
    }
  }

  void flush()
  {
    for (auto i{0}; i < D; ++i)
    {
      cin >> t[i];
      t[i]--;
    }
    calc_score();
    int M;
    cin >> M;
    for (auto i{0}; i < M; ++i)
    {
      int d, q;
      cin >> d >> q;
      --q;
      totalScore = change_score(d, q);
      cout << totalScore << endl;
    }
  }

private:
  ll change_score(int d, int q)
  {
    int p{t[d]};
    if (p == q)
    {
      return totalScore;
    }
    ll newScore{totalScore};
    t[d] = q;
    newScore -= s[d][p];
    newScore += s[d][q];
    {
      auto it{contestDays[p].find(d)};
      --it;
      auto x{*it};
      ++it;
      ++it;
      auto y{*it};
      auto dif{(y - d) * (d - x)};
      newScore += c[p] * dif;
#if DEBUG == 1
      cerr << "x = " << x << ", d = " << d << ", y = " << y << endl;
#endif
    }
    contestDays[p].erase(d);
    contestDays[q].insert(d);
    {
      auto it{contestDays[q].find(d)};
      --it;
      auto x{*it};
      ++it;
      ++it;
      auto y{*it};
      auto dif{(y - d) * (d - x)};
      newScore -= c[q] * dif;
    }
    return newScore;
  }

  vector<ll> calc_score()
  {
    vector<ll> ans(D);
    vector<vector<int>> last(D + 1, vector<int>(C, 0));
    ll now{0};
    for (auto d{0}; d < D; ++d)
    {
      now += s[d][t[d]];
      contestDays[t[d]].insert(d + 1);
      last[d + 1] = last[d];
      last[d + 1][t[d]] = d + 1;
      ll penalty{0};
      for (auto i{0}; i < C; ++i)
      {
        penalty += c[i] * (d + 1 - last[d + 1][i]);
      }
      now -= penalty;
      ans[d] = now;
    }
    totalScore = now;
    return ans;
  }
};

// ----- main() -----

int main()
{
  ll d;
  cin >> d;
  Solve solve;
  solve.flush();
}
<commit_msg>tried C.cpp to 'C'<commit_after>#define DEBUG 1
/**
 * File    : C.cpp
 * Author  : Kazune Takahashi
 * Created : 2020/6/28 20:51:44
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/integer/common_factor_rt.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/rational.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::integer::gcd; // for C++14 or for cpp_int
using boost::integer::lcm; // for C++14 or for cpp_int
using boost::multiprecision::cpp_int;
using ll = long long;
using ld = long double;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1'000'000'007LL};
// constexpr ll MOD{998'244'353LL}; // be careful
constexpr ll MAX_SIZE{3'000'010LL};
// constexpr ll MAX_SIZE{30'000'010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
bool ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
    return true;
  }
  return false;
}
template <typename T>
bool ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
    return true;
  }
  return false;
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(Mint const &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(Mint const &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(Mint const &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(Mint const &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(Mint const &a) const { return Mint(*this) += a; }
  Mint operator-(Mint const &a) const { return Mint(*this) -= a; }
  Mint operator*(Mint const &a) const { return Mint(*this) *= a; }
  Mint operator/(Mint const &a) const { return Mint(*this) /= a; }
  bool operator<(Mint const &a) const { return x < a.x; }
  bool operator<=(Mint const &a) const { return x <= a.x; }
  bool operator>(Mint const &a) const { return x > a.x; }
  bool operator>=(Mint const &a) const { return x >= a.x; }
  bool operator==(Mint const &a) const { return x == a.x; }
  bool operator!=(Mint const &a) const { return !(*this == a); }
  Mint power(ll N) const
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, Mint<MOD> const &rhs) { return rhs + lhs; }
template <ll MOD>
Mint<MOD> operator-(ll lhs, Mint<MOD> const &rhs) { return -rhs + lhs; }
template <ll MOD>
Mint<MOD> operator*(ll lhs, Mint<MOD> const &rhs) { return rhs * lhs; }
template <ll MOD>
Mint<MOD> operator/(ll lhs, Mint<MOD> const &rhs) { return Mint<MOD>{lhs} / rhs; }
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a) { return stream >> a.x; }
template <ll MOD>
ostream &operator<<(ostream &stream, Mint<MOD> const &a) { return stream << a.x; }
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i{2LL}; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i{1LL}; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
// ----- for C++17 -----
template <typename T, typename enable_if<is_integral<T>::value>::type * = nullptr>
size_t popcount(T x) { return bitset<64>(x).count(); }
size_t popcount(string const &S) { return bitset<200010>{S}.count(); }
// ----- Infty -----
template <typename T>
constexpr T Infty() { return numeric_limits<T>::max(); }
template <typename T>
constexpr T mInfty() { return numeric_limits<T>::min(); }
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1'000'000'000'000'010LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}

// ----- Solve -----

#if DEBUG == 1
constexpr int D = 5;
#else
constexpr int D = 365;
#endif
constexpr int C = 26;

class Solve
{
  vector<ll> c;
  vector<vector<ll>> s;
  vector<int> t;
  vector<set<int>> contestDays;
  ll totalScore;

public:
  Solve() : c(C), s(D, vector<ll>(C, 0)), t(D), contestDays(C), totalScore{0}
  {
    for (auto i{0}; i < C; ++i)
    {
      cin >> c[i];
    }
    for (auto i{0}; i < D; ++i)
    {
      for (auto j{0}; j < C; ++j)
      {
        cin >> s[i][j];
      }
    }
    for (auto i{0}; i < C; ++i)
    {
      contestDays[i].insert(0);
      contestDays[i].insert(D + 1);
    }
  }

  void flush()
  {
    for (auto i{0}; i < D; ++i)
    {
      cin >> t[i];
      t[i]--;
    }
    calc_score();
    int M;
    cin >> M;
    for (auto i{0}; i < M; ++i)
    {
      int d, q;
      cin >> d >> q;
      --q;
      totalScore = change_score(d, q);
      cout << totalScore << endl;
    }
  }

private:
  ll change_score(int d, int q)
  {
    int p{t[d - 1]};
    if (p == q)
    {
      return totalScore;
    }
    ll newScore{totalScore};
    t[d] = q;
    newScore -= s[d][p];
    newScore += s[d][q];
    {
      auto it{contestDays[p].find(d)};
      --it;
      auto x{*it};
      ++it;
      ++it;
      auto y{*it};
      auto dif{(y - d) * (d - x)};
      newScore += c[p] * dif;
#if DEBUG == 1
      cerr << "x = " << x << ", d = " << d << ", y = " << y << endl;
#endif
    }
    contestDays[p].erase(d);
    contestDays[q].insert(d);
    {
      auto it{contestDays[q].find(d)};
      --it;
      auto x{*it};
      ++it;
      ++it;
      auto y{*it};
      auto dif{(y - d) * (d - x)};
      newScore -= c[q] * dif;
    }
    return newScore;
  }

  vector<ll> calc_score()
  {
    vector<ll> ans(D);
    vector<vector<int>> last(D + 1, vector<int>(C, 0));
    ll now{0};
    for (auto d{0}; d < D; ++d)
    {
      now += s[d][t[d]];
      contestDays[t[d]].insert(d + 1);
      last[d + 1] = last[d];
      last[d + 1][t[d]] = d + 1;
      ll penalty{0};
      for (auto i{0}; i < C; ++i)
      {
        penalty += c[i] * (d + 1 - last[d + 1][i]);
      }
      now -= penalty;
      ans[d] = now;
    }
    totalScore = now;
    return ans;
  }
};

// ----- main() -----

int main()
{
  ll d;
  cin >> d;
  Solve solve;
  solve.flush();
}
<|endoftext|>


<commit_before>/*
 * SimulationFitnessCalculator.cpp
 *
 *  Created on: 19/05/2015
 *      Author: vitor
 */

#include "SimulationFitnessCalculator.h"

void SimulationFitnessCalculator::fitness(std::vector<Cromossomo>& populacao) {
	std::vector<std::vector<std::bitset<8>>> result;

}

std::bitset<8> SimulationFitnessCalculator::calcular_entrada(
		const Cromossomo& individuo, std::bitset<8> entrada) {
	std::bitset<8> resultado;
	auto matriz_resultados = matriz_resultados_inicial();

	for (unsigned int j = 0; j < genetic_params.c; j++) {
		for (unsigned int i = 0; i < genetic_params.r; i++) {
			auto& individuo_atual = individuo.elementos_logicos[i][j];
			auto funcao = escolher_funcao(
					individuo_atual.function);
			auto input0 = escolher_input(individuo_atual.inputs[0], matriz_resultados, entrada);
			auto input1 = escolher_input(individuo_atual.inputs[1], matriz_resultados, entrada);
			matriz_resultados[i][j] = funcao(input0, input1);
		}
	}

	for (unsigned int i = 0; i < genetic_params.num_out; i++) {
		resultado[i] = escolher_input(individuo.saidas[i].input, matriz_resultados, entrada);
	}

	return resultado;
}

std::vector<std::vector<bool>> SimulationFitnessCalculator::matriz_resultados_inicial() {
	std::vector<std::vector<bool>> matriz_inicial(genetic_params.r);

	for (unsigned int i = 0; i < genetic_params.r; i++) {
		matriz_inicial[i].reserve(genetic_params.c);
	}
	return matriz_inicial;
}

std::function<bool(const bool&, const bool&)> SimulationFitnessCalculator::escolher_funcao(
		int funcao) {
	std::vector<std::function<bool(const bool&, const bool&)>> funcoes = {
					std::logical_and<bool>(),
					std::logical_or<bool>(),
					std::not_equal_to<bool>(),
					[](const bool& a, const bool& b) {return !a;},
					[](const bool& a, const bool& b) {return !(a && b);},
					std::equal_to<bool>(),
					[](const bool& a, const bool& b) {return !(a || b);}
			};

	return funcoes[funcao];
}

bool SimulationFitnessCalculator::escolher_input(unsigned int input,
		const std::vector<std::vector<bool>>& matriz_resultados,
		const std::bitset<8>& entrada) {
	if (input >= genetic_params.num_in) {
		input -= genetic_params.num_in;
		return matriz_resultados[input / genetic_params.c][input % genetic_params.c];
	}
	return entrada[input];
}
<commit_msg>Implementado método de fitness.<commit_after>/*
 * SimulationFitnessCalculator.cpp
 *
 *  Created on: 19/05/2015
 *      Author: vitor
 */

#include "SimulationFitnessCalculator.h"

void SimulationFitnessCalculator::fitness(std::vector<Cromossomo>& populacao) {
	for (auto& individuo : populacao) {
		std::vector<std::vector<std::bitset<8>>> result;
		for (unsigned int i = 0; i < (unsigned int) pow(2, genetic_params.num_in); i++) {
			result.push_back(std::vector<std::bitset<8>>());
			result[i].push_back(calcular_entrada(individuo, std::bitset<8>(i)));
		}
		individuo.set_fitness(fitness_calculator(result));
	}
}

std::bitset<8> SimulationFitnessCalculator::calcular_entrada(
		const Cromossomo& individuo, std::bitset<8> entrada) {
	std::bitset<8> resultado;
	auto matriz_resultados = matriz_resultados_inicial();

	for (unsigned int j = 0; j < genetic_params.c; j++) {
		for (unsigned int i = 0; i < genetic_params.r; i++) {
			auto& individuo_atual = individuo.elementos_logicos[i][j];
			auto funcao = escolher_funcao(
					individuo_atual.function);
			auto input0 = escolher_input(individuo_atual.inputs[0], matriz_resultados, entrada);
			auto input1 = escolher_input(individuo_atual.inputs[1], matriz_resultados, entrada);
			matriz_resultados[i][j] = funcao(input0, input1);
		}
	}

	for (unsigned int i = 0; i < genetic_params.num_out; i++) {
		resultado[i] = escolher_input(individuo.saidas[i].input, matriz_resultados, entrada);
	}

	return resultado;
}

std::vector<std::vector<bool>> SimulationFitnessCalculator::matriz_resultados_inicial() {
	std::vector<std::vector<bool>> matriz_inicial(genetic_params.r);

	for (unsigned int i = 0; i < genetic_params.r; i++) {
		matriz_inicial[i].reserve(genetic_params.c);
	}
	return matriz_inicial;
}

std::function<bool(const bool&, const bool&)> SimulationFitnessCalculator::escolher_funcao(
		int funcao) {
	std::vector<std::function<bool(const bool&, const bool&)>> funcoes = {
					std::logical_and<bool>(),
					std::logical_or<bool>(),
					std::not_equal_to<bool>(),
					[](const bool& a, const bool& b) {return !a;},
					[](const bool& a, const bool& b) {return !(a && b);},
					std::equal_to<bool>(),
					[](const bool& a, const bool& b) {return !(a || b);}
			};

	return funcoes[funcao];
}

bool SimulationFitnessCalculator::escolher_input(unsigned int input,
		const std::vector<std::vector<bool>>& matriz_resultados,
		const std::bitset<8>& entrada) {
	if (input >= genetic_params.num_in) {
		input -= genetic_params.num_in;
		return matriz_resultados[input / genetic_params.c][input % genetic_params.c];
	}
	return entrada[input];
}
<|endoftext|>