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

#include "open_spiel/algorithms/state_distribution.h"

#include "open_spiel/abseil-cpp/absl/algorithm/container.h"
#include "open_spiel/policy.h"
#include "open_spiel/spiel.h"
#include "open_spiel/spiel_utils.h"

namespace open_spiel {
namespace algorithms {
namespace {

void KuhnStateDistributionTest() {
  std::shared_ptr<const Game> game = LoadGame("kuhn_poker");
  std::unique_ptr<State> state = game->NewInitialState();
  TabularPolicy uniform_policy = GetUniformPolicy(*game);

  // Construct the state 1b
  state->ApplyAction(0);  // p0 card: jack
  state->ApplyAction(1);  // p1 card: queen
  state->ApplyAction(1);  // player 0 bet
  SPIEL_CHECK_EQ(state->CurrentPlayer(), 1);
  SPIEL_CHECK_EQ(state->InformationStateString(), "1b");
  HistoryDistribution dist = GetStateDistribution(*state, &uniform_policy);

  SPIEL_CHECK_EQ(dist.first.size(), 2);
  SPIEL_CHECK_EQ(dist.second.size(), 2);

  // Check that sampled states have private cards jack and king for the opponent
  SPIEL_CHECK_TRUE(dist.first[0]->InformationStateString(0) == "0b" ||
                   dist.first[0]->InformationStateString(0) == "2b");
  SPIEL_CHECK_TRUE(dist.first[1]->InformationStateString(0) == "0b" ||
                   dist.first[1]->InformationStateString(0) == "2b");
  SPIEL_CHECK_NE(dist.first[0]->InformationStateString(0),
                 dist.first[1]->InformationStateString(0));

  // Check that they are equally likely, and sum to 1
  SPIEL_CHECK_EQ(dist.second[0], 0.5);
  SPIEL_CHECK_EQ(dist.second[0], 0.5);
}

void CompareDists(const HistoryDistribution& lhs,
                  const HistoryDistribution& rhs) {
  for (int i = 0; i < lhs.first.size(); ++i) {
    std::cerr << "lhs[" << i << "]: " << lhs.first[i]->HistoryString()
              << ", p: " << lhs.second[i] << std::endl;
    std::cerr << "rhs[" << i << "]: " << rhs.first[i]->HistoryString()
              << ", p: " << rhs.second[i] << std::endl;
  }
  for (int i = 0; i < lhs.first.size(); ++i) {
    for (int j = 0; j < rhs.first.size(); ++j) {
      if (lhs.first[i]->History() == rhs.first[j]->History()) {
        SPIEL_CHECK_FLOAT_EQ(lhs.second[i], rhs.second[j]);
        break;
      }
    }
  }
}

void LeducStateDistributionTest() {
  std::shared_ptr<const Game> game = LoadGame("leduc_poker");
  std::unique_ptr<State> state = game->NewInitialState();
  TabularPolicy uniform_policy = GetUniformPolicy(*game);
  state->ApplyAction(0);  // p0 card: jack of first suit
  state->ApplyAction(1);  // p1 card: queen of first suit
  state->ApplyAction(1);  // player 0 bet
  std::string info_state_string = state->InformationStateString();
  std::string state_history_string = state->HistoryString();
  SPIEL_CHECK_EQ(state->CurrentPlayer(), 1);
  HistoryDistribution dist = GetStateDistribution(*state, &uniform_policy);
  HistoryDistribution incremental_dist = UpdateIncrementalStateDistribution(
      *state, &uniform_policy, /*player_id=*/1);
  std::cerr << "Comparing dists 1..." << std::endl;
  CompareDists(dist, incremental_dist);

  std::vector<double> correct_distribution(5, 0.2);
  SPIEL_CHECK_EQ(dist.first.size(), 5);
  SPIEL_CHECK_EQ(dist.second, correct_distribution);

  // Check that none of the states are equal, that one of them is equal to the
  // state used to generate the distribution, and that they are all equally
  // likely with probability 0.2.
  int state_matches = 0;
  for (int i = 0; i < dist.first.size(); ++i) {
    SPIEL_CHECK_EQ(dist.first[i]->InformationStateString(), info_state_string);
    if (dist.first[i]->HistoryString() == state_history_string) {
      state_matches++;
    }
    for (int j = i + 1; j < dist.first.size(); ++j) {
      SPIEL_CHECK_NE(dist.first[i]->HistoryString(),
                     dist.first[j]->HistoryString());
    }
  }
  SPIEL_CHECK_EQ(state_matches, 1);

  // Now, it's a chance node...
  state->ApplyAction(state->LegalActions()[0]);
  incremental_dist =
      UpdateIncrementalStateDistribution(*state, &uniform_policy,
                                         /*player_id=*/1, incremental_dist);
  state->ApplyAction(state->LegalActions()[0]);
  dist = GetStateDistribution(*state, &uniform_policy);
  incremental_dist =
      UpdateIncrementalStateDistribution(*state, &uniform_policy,
                                         /*player_id=*/1, incremental_dist);
  std::cerr << "Comparing dists 2..." << std::endl;
  SPIEL_CHECK_FLOAT_EQ(absl::c_accumulate(dist.second, 0.), 1.);
  SPIEL_CHECK_FLOAT_EQ(absl::c_accumulate(incremental_dist.second, 0.), 1.);
  CompareDists(dist, incremental_dist);
}

constexpr absl::string_view kHUNLGameString =
    ("universal_poker(betting=limit,numPlayers=2,numRounds=4,stack=1200 "
     "1200,blind=50 100,firstPlayer=2 "
     "1,numSuits=4,numRanks=13,numHoleCards=2,numBoardCards=0 3 1 "
     "1,raiseSize=100 100 100 100)");

void HULIncrementalTest() {
  std::shared_ptr<const Game> game = LoadGame(std::string(kHUNLGameString));
  UniformPolicy policy;
  std::unique_ptr<State> state = game->NewInitialState();
  while (state->IsChanceNode()) state->ApplyAction(state->LegalActions()[0]);
  HistoryDistribution inc_dist =
      UpdateIncrementalStateDistribution(*state, &policy, /*player_id=*/0);
  SPIEL_CHECK_EQ(inc_dist.second.size(), 1225);
  SPIEL_CHECK_FLOAT_EQ(absl::c_accumulate(inc_dist.second, 0.), 1.);
}

}  // namespace
}  // namespace algorithms
}  // namespace open_spiel

namespace algorithms = open_spiel::algorithms;

int main(int argc, char** argv) {
  algorithms::KuhnStateDistributionTest();
  algorithms::LeducStateDistributionTest();
  algorithms::HULIncrementalTest();
}
<commit_msg>Fix state_distribution_test when ACPC is not enabled.<commit_after>// Copyright 2019 DeepMind Technologies Ltd. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "open_spiel/algorithms/state_distribution.h"

#include "open_spiel/abseil-cpp/absl/algorithm/container.h"
#include "open_spiel/policy.h"
#include "open_spiel/spiel.h"
#include "open_spiel/spiel_utils.h"

namespace open_spiel {
namespace algorithms {
namespace {

void KuhnStateDistributionTest() {
  std::shared_ptr<const Game> game = LoadGame("kuhn_poker");
  std::unique_ptr<State> state = game->NewInitialState();
  TabularPolicy uniform_policy = GetUniformPolicy(*game);

  // Construct the state 1b
  state->ApplyAction(0);  // p0 card: jack
  state->ApplyAction(1);  // p1 card: queen
  state->ApplyAction(1);  // player 0 bet
  SPIEL_CHECK_EQ(state->CurrentPlayer(), 1);
  SPIEL_CHECK_EQ(state->InformationStateString(), "1b");
  HistoryDistribution dist = GetStateDistribution(*state, &uniform_policy);

  SPIEL_CHECK_EQ(dist.first.size(), 2);
  SPIEL_CHECK_EQ(dist.second.size(), 2);

  // Check that sampled states have private cards jack and king for the opponent
  SPIEL_CHECK_TRUE(dist.first[0]->InformationStateString(0) == "0b" ||
                   dist.first[0]->InformationStateString(0) == "2b");
  SPIEL_CHECK_TRUE(dist.first[1]->InformationStateString(0) == "0b" ||
                   dist.first[1]->InformationStateString(0) == "2b");
  SPIEL_CHECK_NE(dist.first[0]->InformationStateString(0),
                 dist.first[1]->InformationStateString(0));

  // Check that they are equally likely, and sum to 1
  SPIEL_CHECK_EQ(dist.second[0], 0.5);
  SPIEL_CHECK_EQ(dist.second[0], 0.5);
}

void CompareDists(const HistoryDistribution& lhs,
                  const HistoryDistribution& rhs) {
  for (int i = 0; i < lhs.first.size(); ++i) {
    std::cerr << "lhs[" << i << "]: " << lhs.first[i]->HistoryString()
              << ", p: " << lhs.second[i] << std::endl;
    std::cerr << "rhs[" << i << "]: " << rhs.first[i]->HistoryString()
              << ", p: " << rhs.second[i] << std::endl;
  }
  for (int i = 0; i < lhs.first.size(); ++i) {
    for (int j = 0; j < rhs.first.size(); ++j) {
      if (lhs.first[i]->History() == rhs.first[j]->History()) {
        SPIEL_CHECK_FLOAT_EQ(lhs.second[i], rhs.second[j]);
        break;
      }
    }
  }
}

void LeducStateDistributionTest() {
  std::shared_ptr<const Game> game = LoadGame("leduc_poker");
  std::unique_ptr<State> state = game->NewInitialState();
  TabularPolicy uniform_policy = GetUniformPolicy(*game);
  state->ApplyAction(0);  // p0 card: jack of first suit
  state->ApplyAction(1);  // p1 card: queen of first suit
  state->ApplyAction(1);  // player 0 bet
  std::string info_state_string = state->InformationStateString();
  std::string state_history_string = state->HistoryString();
  SPIEL_CHECK_EQ(state->CurrentPlayer(), 1);
  HistoryDistribution dist = GetStateDistribution(*state, &uniform_policy);
  HistoryDistribution incremental_dist = UpdateIncrementalStateDistribution(
      *state, &uniform_policy, /*player_id=*/1);
  std::cerr << "Comparing dists 1..." << std::endl;
  CompareDists(dist, incremental_dist);

  std::vector<double> correct_distribution(5, 0.2);
  SPIEL_CHECK_EQ(dist.first.size(), 5);
  SPIEL_CHECK_EQ(dist.second, correct_distribution);

  // Check that none of the states are equal, that one of them is equal to the
  // state used to generate the distribution, and that they are all equally
  // likely with probability 0.2.
  int state_matches = 0;
  for (int i = 0; i < dist.first.size(); ++i) {
    SPIEL_CHECK_EQ(dist.first[i]->InformationStateString(), info_state_string);
    if (dist.first[i]->HistoryString() == state_history_string) {
      state_matches++;
    }
    for (int j = i + 1; j < dist.first.size(); ++j) {
      SPIEL_CHECK_NE(dist.first[i]->HistoryString(),
                     dist.first[j]->HistoryString());
    }
  }
  SPIEL_CHECK_EQ(state_matches, 1);

  // Now, it's a chance node...
  state->ApplyAction(state->LegalActions()[0]);
  incremental_dist =
      UpdateIncrementalStateDistribution(*state, &uniform_policy,
                                         /*player_id=*/1, incremental_dist);
  state->ApplyAction(state->LegalActions()[0]);
  dist = GetStateDistribution(*state, &uniform_policy);
  incremental_dist =
      UpdateIncrementalStateDistribution(*state, &uniform_policy,
                                         /*player_id=*/1, incremental_dist);
  std::cerr << "Comparing dists 2..." << std::endl;
  SPIEL_CHECK_FLOAT_EQ(absl::c_accumulate(dist.second, 0.), 1.);
  SPIEL_CHECK_FLOAT_EQ(absl::c_accumulate(incremental_dist.second, 0.), 1.);
  CompareDists(dist, incremental_dist);
}

constexpr absl::string_view kHUNLGameString =
    ("universal_poker(betting=limit,numPlayers=2,numRounds=4,stack=1200 "
     "1200,blind=50 100,firstPlayer=2 "
     "1,numSuits=4,numRanks=13,numHoleCards=2,numBoardCards=0 3 1 "
     "1,raiseSize=100 100 100 100)");

void HUNLIncrementalTest() {
  std::shared_ptr<const Game> game = LoadGame(std::string(kHUNLGameString));
  UniformPolicy policy;
  std::unique_ptr<State> state = game->NewInitialState();
  while (state->IsChanceNode()) state->ApplyAction(state->LegalActions()[0]);
  HistoryDistribution inc_dist =
      UpdateIncrementalStateDistribution(*state, &policy, /*player_id=*/0);
  SPIEL_CHECK_EQ(inc_dist.second.size(), 1225);
  SPIEL_CHECK_FLOAT_EQ(absl::c_accumulate(inc_dist.second, 0.), 1.);
}

}  // namespace
}  // namespace algorithms
}  // namespace open_spiel

namespace algorithms = open_spiel::algorithms;

int main(int argc, char** argv) {
  algorithms::KuhnStateDistributionTest();
  algorithms::LeducStateDistributionTest();

  // ACPC is an optional dependency. Only test HUNL if it is registered.
  if (open_spiel::IsGameRegistered(std::string(algorithms::kHUNLGameString))) {
    algorithms::HUNLIncrementalTest();
  }

}
<|endoftext|>


<commit_before><commit_msg>GPU Calc: Fix Not support multiple data types of KURT<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: basmethnode.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2004-10-22 14:01:40 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef SCRIPTING_BASMETHNODE_HXX
#define SCRIPTING_BASMETHNODE_HXX

#ifndef SCRIPTING_BCHOLDER_HXX
#include "bcholder.hxx"
#endif

#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#ifndef _COM_SUN_STAR_SCRIPT_XINVOCATION_HPP_
#include <com/sun/star/script/XInvocation.hpp>
#endif
#ifndef _COM_SUN_STAR_SCRIPT_BROWSE_XBROWSENODE_HPP_
#include <com/sun/star/script/browse/XBrowseNode.hpp>
#endif
#ifndef _COM_SUN_STAR_UNO_XCOMPONENTCONTEXT_HPP_
#include <com/sun/star/uno/XComponentContext.hpp>
#endif

#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_
#include <comphelper/proparrhlp.hxx>
#endif
#ifndef _COMPHELPER_PROPERTYCONTAINER_HXX_
#include <comphelper/propertycontainer.hxx>
#endif
#ifndef _COMPHELPER_UNO3_HXX_
#include <comphelper/uno3.hxx>
#endif
#ifndef _CPPUHELPER_IMPLBASE2_HXX_
#include <cppuhelper/implbase2.hxx>
#endif

class SbMethod;

//.........................................................................
namespace basprov
{
//.........................................................................

    //  ----------------------------------------------------
    //  class BasicMethodNodeImpl
    //  ----------------------------------------------------

    typedef ::cppu::WeakImplHelper2<
        ::com::sun::star::script::browse::XBrowseNode,
        ::com::sun::star::script::XInvocation > BasicMethodNodeImpl_BASE;

    class BasicMethodNodeImpl : public BasicMethodNodeImpl_BASE,
                                public ::scripting_helper::OBroadcastHelperHolder,
                                public ::comphelper::OPropertyContainer,
                                public ::comphelper::OPropertyArrayUsageHelper< BasicMethodNodeImpl >
    {
    private:
        ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >    m_xContext;
    ::rtl::OUString m_sScriptingContext;
        SbMethod* m_pMethod;
        bool m_bIsAppScript;

        // properties
        ::rtl::OUString m_sURI;
        sal_Bool m_bEditable;

    protected:
        // OPropertySetHelper
        virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(  );

        // OPropertyArrayUsageHelper
        virtual ::cppu::IPropertyArrayHelper* createArrayHelper(  ) const;

    public:
        BasicMethodNodeImpl( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext,
            const ::rtl::OUString& sScriptingContext,
            SbMethod* pMethod, bool isAppScript = true );
        virtual ~BasicMethodNodeImpl();

        // XInterface
        DECLARE_XINTERFACE()

        // XTypeProvider
        DECLARE_XTYPEPROVIDER()

        // XBrowseNode
        virtual ::rtl::OUString SAL_CALL getName(  )
            throw (::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::script::browse::XBrowseNode > > SAL_CALL getChildNodes(  )
            throw (::com::sun::star::uno::RuntimeException);
        virtual sal_Bool SAL_CALL hasChildNodes(  )
            throw (::com::sun::star::uno::RuntimeException);
        virtual sal_Int16 SAL_CALL getType(  )
            throw (::com::sun::star::uno::RuntimeException);

        // XPropertySet
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo(  )
            throw (::com::sun::star::uno::RuntimeException);

        // XInvocation
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XIntrospectionAccess > SAL_CALL getIntrospection(  )
            throw (::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Any SAL_CALL invoke(
            const ::rtl::OUString& aFunctionName,
            const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aParams,
            ::com::sun::star::uno::Sequence< sal_Int16 >& aOutParamIndex,
            ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aOutParam )
            throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::script::CannotConvertException,
                   ::com::sun::star::reflection::InvocationTargetException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL setValue( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Any& aValue )
            throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::script::CannotConvertException,
                   ::com::sun::star::reflection::InvocationTargetException, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Any SAL_CALL getValue( const ::rtl::OUString& aPropertyName )
            throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException);
        virtual sal_Bool SAL_CALL hasMethod( const ::rtl::OUString& aName )
            throw (::com::sun::star::uno::RuntimeException);
        virtual sal_Bool SAL_CALL hasProperty( const ::rtl::OUString& aName )
            throw (::com::sun::star::uno::RuntimeException);
    };

//.........................................................................
}   // namespace basprov
//.........................................................................

#endif // SCRIPTING_BASMETHNODE_HXX
<commit_msg>INTEGRATION: CWS tbe15 (1.6.12); FILE MERGED 2004/12/03 16:23:07 tbe 1.6.12.1: #i38139# Tools/Macro/Run Macro freezes office when Basic macro is already running<commit_after>/*************************************************************************
 *
 *  $RCSfile: basmethnode.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: kz $ $Date: 2005-01-13 17:42:44 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef SCRIPTING_BASMETHNODE_HXX
#define SCRIPTING_BASMETHNODE_HXX

#ifndef SCRIPTING_BCHOLDER_HXX
#include "bcholder.hxx"
#endif

#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#ifndef _COM_SUN_STAR_SCRIPT_XINVOCATION_HPP_
#include <com/sun/star/script/XInvocation.hpp>
#endif
#ifndef _COM_SUN_STAR_SCRIPT_BROWSE_XBROWSENODE_HPP_
#include <com/sun/star/script/browse/XBrowseNode.hpp>
#endif
#ifndef _COM_SUN_STAR_UNO_XCOMPONENTCONTEXT_HPP_
#include <com/sun/star/uno/XComponentContext.hpp>
#endif

#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_
#include <comphelper/proparrhlp.hxx>
#endif
#ifndef _COMPHELPER_PROPERTYCONTAINER_HXX_
#include <comphelper/propertycontainer.hxx>
#endif
#ifndef _COMPHELPER_UNO3_HXX_
#include <comphelper/uno3.hxx>
#endif
#ifndef _CPPUHELPER_IMPLBASE2_HXX_
#include <cppuhelper/implbase2.hxx>
#endif

class SbMethod;

//.........................................................................
namespace basprov
{
//.........................................................................

    //  ----------------------------------------------------
    //  class BasicMethodNodeImpl
    //  ----------------------------------------------------

    typedef ::cppu::WeakImplHelper2<
        ::com::sun::star::script::browse::XBrowseNode,
        ::com::sun::star::script::XInvocation > BasicMethodNodeImpl_BASE;

    class BasicMethodNodeImpl : public BasicMethodNodeImpl_BASE,
                                public ::scripting_helper::OMutexHolder,
                                public ::scripting_helper::OBroadcastHelperHolder,
                                public ::comphelper::OPropertyContainer,
                                public ::comphelper::OPropertyArrayUsageHelper< BasicMethodNodeImpl >
    {
    private:
        ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >    m_xContext;
    ::rtl::OUString m_sScriptingContext;
        SbMethod* m_pMethod;
        bool m_bIsAppScript;

        // properties
        ::rtl::OUString m_sURI;
        sal_Bool m_bEditable;

    protected:
        // OPropertySetHelper
        virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(  );

        // OPropertyArrayUsageHelper
        virtual ::cppu::IPropertyArrayHelper* createArrayHelper(  ) const;

    public:
        BasicMethodNodeImpl( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext,
            const ::rtl::OUString& sScriptingContext,
            SbMethod* pMethod, bool isAppScript = true );
        virtual ~BasicMethodNodeImpl();

        // XInterface
        DECLARE_XINTERFACE()

        // XTypeProvider
        DECLARE_XTYPEPROVIDER()

        // XBrowseNode
        virtual ::rtl::OUString SAL_CALL getName(  )
            throw (::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::script::browse::XBrowseNode > > SAL_CALL getChildNodes(  )
            throw (::com::sun::star::uno::RuntimeException);
        virtual sal_Bool SAL_CALL hasChildNodes(  )
            throw (::com::sun::star::uno::RuntimeException);
        virtual sal_Int16 SAL_CALL getType(  )
            throw (::com::sun::star::uno::RuntimeException);

        // XPropertySet
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo(  )
            throw (::com::sun::star::uno::RuntimeException);

        // XInvocation
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XIntrospectionAccess > SAL_CALL getIntrospection(  )
            throw (::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Any SAL_CALL invoke(
            const ::rtl::OUString& aFunctionName,
            const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aParams,
            ::com::sun::star::uno::Sequence< sal_Int16 >& aOutParamIndex,
            ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aOutParam )
            throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::script::CannotConvertException,
                   ::com::sun::star::reflection::InvocationTargetException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL setValue( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Any& aValue )
            throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::script::CannotConvertException,
                   ::com::sun::star::reflection::InvocationTargetException, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Any SAL_CALL getValue( const ::rtl::OUString& aPropertyName )
            throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException);
        virtual sal_Bool SAL_CALL hasMethod( const ::rtl::OUString& aName )
            throw (::com::sun::star::uno::RuntimeException);
        virtual sal_Bool SAL_CALL hasProperty( const ::rtl::OUString& aName )
            throw (::com::sun::star::uno::RuntimeException);
    };

//.........................................................................
}   // namespace basprov
//.........................................................................

#endif // SCRIPTING_BASMETHNODE_HXX
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "likely.hpp"

#include "mtac/BranchOptimizations.hpp"
#include "mtac/Function.hpp"
#include "mtac/ControlFlowGraph.hpp"
#include "mtac/Statement.hpp"

using namespace eddic;

bool mtac::optimize_branches::operator()(mtac::Function& function){
    bool optimized = false;

    for(auto& block : function){
        for(auto& statement : block->statements){
            if(auto* ptr = boost::get<std::shared_ptr<mtac::Quadruple>>(&statement)){
                if(boost::get<int>(&*(*ptr)->arg1)){
                    int value = boost::get<int>(*(*ptr)->arg1);

                    if((*ptr)->op == mtac::Operator::IF_FALSE_UNARY){

                        if(value == 0){
                            auto goto_ = std::make_shared<mtac::Quadruple>((*ptr)->label(), mtac::Operator::GOTO);
                            goto_->block = (*ptr)->block;

                            statement = goto_;
                            optimized = true;

                            mtac::remove_edge(block, block->next);
                        } else if(value == 1){
                            mtac::remove_edge(block, (*ptr)->block);

                            statement = std::make_shared<mtac::Quadruple>(mtac::Operator::NOP);
                            optimized = true;
                        }
                    } else if((*ptr)->op == mtac::Operator::IF_UNARY){
                        if(value == 0){
                            mtac::remove_edge(block, (*ptr)->block);

                            statement = std::make_shared<mtac::Quadruple>(mtac::Operator::NOP);
                            optimized = true;
                        } else if(value == 1){
                            auto goto_ = std::make_shared<mtac::Quadruple>((*ptr)->label(), mtac::Operator::GOTO);
                            goto_->block = (*ptr)->block;

                            statement = goto_;
                            optimized = true;

                            mtac::remove_edge(block, block->next);
                        }
                    }
                }
            }
        }
    }

    return optimized;
}
<commit_msg>Fix bug: not all quadruple have their first arg set<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "likely.hpp"

#include "mtac/BranchOptimizations.hpp"
#include "mtac/Function.hpp"
#include "mtac/ControlFlowGraph.hpp"
#include "mtac/Statement.hpp"

using namespace eddic;

bool mtac::optimize_branches::operator()(mtac::Function& function){
    bool optimized = false;

    for(auto& block : function){
        for(auto& statement : block->statements){
            if(auto* ptr = boost::get<std::shared_ptr<mtac::Quadruple>>(&statement)){
                if((*ptr)->op == mtac::Operator::IF_FALSE_UNARY && boost::get<int>(&*(*ptr)->arg1)){
                    int value = boost::get<int>(*(*ptr)->arg1);

                    if(value == 0){
                        auto goto_ = std::make_shared<mtac::Quadruple>((*ptr)->label(), mtac::Operator::GOTO);
                        goto_->block = (*ptr)->block;

                        statement = goto_;
                        optimized = true;

                        mtac::remove_edge(block, block->next);
                    } else if(value == 1){
                        mtac::remove_edge(block, (*ptr)->block);

                        statement = std::make_shared<mtac::Quadruple>(mtac::Operator::NOP);
                        optimized = true;
                    }
                } else if((*ptr)->op == mtac::Operator::IF_UNARY && boost::get<int>(&*(*ptr)->arg1)){
                    int value = boost::get<int>(*(*ptr)->arg1);

                    if(value == 0){
                        mtac::remove_edge(block, (*ptr)->block);

                        statement = std::make_shared<mtac::Quadruple>(mtac::Operator::NOP);
                        optimized = true;
                    } else if(value == 1){
                        auto goto_ = std::make_shared<mtac::Quadruple>((*ptr)->label(), mtac::Operator::GOTO);
                        goto_->block = (*ptr)->block;

                        statement = goto_;
                        optimized = true;

                        mtac::remove_edge(block, block->next);
                    }
                }
            }
        }
    }

    return optimized;
}
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007-2016 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//
//    * Neither the name of the author nor the names of other contributors may
//      be used to endorse or promote products derived from this software
//      without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////

#include <stdafx.h>
#include "Colors.h"

using namespace cursespp;

/* if the terminal supports custom colors, these are the palette
indicies we'll use to store them */
#define COLOR_CUSTOM_WHITE 16
#define COLOR_CUSTOM_BLUE 17
#define COLOR_CUSTOM_RED 18
#define COLOR_CUSTOM_YELLOW 19
#define COLOR_CUSTOM_GREEN 20
#define COLOR_CUSTOM_BLACK 21
#define COLOR_CUSTOM_GREY 22
#define COLOR_CUSTOM_SELECTED_LIST_ITEM_BG 23
#define COLOR_CUSTOM_ORANGE 24
#define COLOR_CUSTOM_DARK_RED 25

/* if we can't set custom colors, but we have the full 256 color
palette, use ones that most closely match our desired colors */
#define COLOR_256_GREEN 148
#define COLOR_256_RED 167
#define COLOR_256_DARK_RED 160
#define COLOR_256_YELLOW 185
#define COLOR_256_MEDIUM_GRAY 240
#define COLOR_256_ORANGE 208
#define COLOR_256_BLUE 123
#define COLOR_256_OFFWHITE 251

/* vars that hold our actual color definitions. these may change
later during init if the terminal supports > 8 colors */
static int white = COLOR_WHITE;
static int blue = COLOR_BLUE;
static int red = COLOR_RED;
static int darkRed = COLOR_RED;
static int yellow = COLOR_YELLOW;
static int green = COLOR_GREEN;
static int black = COLOR_BLACK;
static int orange = COLOR_YELLOW;
static int foreground = COLOR_WHITE;
static int background = -1;
static int selected = -1;
static int grey = COLOR_WHITE;

#define SCALE(x) ((x * 1000) / 255)

static int initColor(int id, int r, int g, int b) {
    init_color(id, SCALE(r), SCALE(g), SCALE(b));
    return id;
}

/* some terminals report custom colors are supported, and also
don't error when calling init_color(), but don't actually work. */
static bool customColorsSupported() {
    if (COLORS <= 8) {
        return false;
    }

#ifdef WIN32
    return true;
#else
    const char* termEnv = std::getenv("TERM_PROGRAM");
    std::string term;
    if (termEnv && strlen(termEnv)) {
        term = std::string(termEnv);
    }
    return term != "Apple_Terminal";
#endif
}

Colors::Colors() {
}

void Colors::Init(bool disableCustomColors) {
    start_color();
    use_default_colors();

    bool hasCustomColors = !disableCustomColors && customColorsSupported();

    /* the default colors are a bit harsh for my taste, so
    let's use custom colors if the terminal supports it. in
    the future we'll allow users to configure this via setting */
    if (hasCustomColors) {
        if (can_change_color()) {
            red = initColor(COLOR_CUSTOM_RED, 220, 82, 86);
            darkRed = initColor(COLOR_CUSTOM_DARK_RED, 175, 66, 71);
            green = initColor(COLOR_CUSTOM_GREEN, 166, 226, 46);
            yellow = initColor(COLOR_CUSTOM_YELLOW, 230, 220, 116);
            selected = initColor(COLOR_CUSTOM_SELECTED_LIST_ITEM_BG, 66, 66, 56);
            grey = initColor(COLOR_CUSTOM_GREY, 128, 128, 128);
            orange = initColor(COLOR_CUSTOM_ORANGE, 255, 150, 32);
            blue = initColor(COLOR_CUSTOM_BLUE, 102, 217, 238);
            white = initColor(COLOR_CUSTOM_WHITE, 230, 230, 230);
            foreground = COLOR_CUSTOM_WHITE;
        }
        else {
            green = COLOR_256_GREEN;
            red = COLOR_256_RED;
            darkRed = COLOR_256_DARK_RED;
            yellow = COLOR_256_YELLOW;
            selected = COLOR_256_MEDIUM_GRAY;
            grey = COLOR_256_MEDIUM_GRAY;
            orange = COLOR_256_ORANGE;
            blue = COLOR_256_BLUE;
            white = COLOR_256_OFFWHITE;
            foreground = COLOR_256_OFFWHITE;
        }
    }

    init_pair(CURSESPP_SELECTED_LIST_ITEM, yellow, selected);
    init_pair(CURSESPP_HIGHLIGHTED_LIST_ITEM, black, green);
    init_pair(CURSESPP_HIGHLIGHTED_SELECTED_LIST_ITEM, black, yellow);
    init_pair(CURSESPP_LIST_ITEM_HEADER, green, background);

    init_pair(CURSESPP_DEFAULT_CONTENT_COLOR, foreground, background);
    init_pair(CURSESPP_DEFAULT_FRAME_COLOR, foreground, background);
    init_pair(CURSESPP_FOCUSED_FRAME_COLOR, red, background);

    init_pair(CURSESPP_TEXT_DEFAULT, white, background);
    init_pair(CURSESPP_TEXT_DISABLED, grey, background);
    init_pair(CURSESPP_TEXT_FOCUSED, red, background);
    init_pair(CURSESPP_TEXT_ACTIVE, green, background);
    init_pair(CURSESPP_TEXT_WARNING, yellow, background);
    init_pair(CURSESPP_TEXT_ERROR, red, background);
    init_pair(CURSESPP_TEXT_HIDDEN, black, background);
    init_pair(CURSESPP_TEXT_SEPARATOR, orange, background);

    init_pair(CURSESPP_BUTTON_NORMAL, black, yellow);
    init_pair(CURSESPP_BUTTON_NEGATIVE, white, red);
    init_pair(CURSESPP_BUTTON_HIGHLIGHTED, black, green);

    init_pair(CURSESPP_SHORTCUT_ROW_NORMAL, yellow, selected);
    init_pair(CURSESPP_SHORTCUT_ROW_FOCUSED, white, darkRed);

    init_pair(CURSESPP_OVERLAY_FRAME, blue, selected);
    init_pair(CURSESPP_OVERLAY_BACKGROUND, white, selected);
}
<commit_msg>More work on custom colors. Apple Terminal is now "properly" supported.<commit_after>//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007-2016 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//
//    * Neither the name of the author nor the names of other contributors may
//      be used to endorse or promote products derived from this software
//      without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////

#include <stdafx.h>
#include "Colors.h"

using namespace cursespp;

/* if the terminal supports custom colors, these are the palette
indicies we'll use to store them */
#define COLOR_CUSTOM_WHITE 16
#define COLOR_CUSTOM_BLUE 17
#define COLOR_CUSTOM_RED 18
#define COLOR_CUSTOM_YELLOW 19
#define COLOR_CUSTOM_GREEN 20
#define COLOR_CUSTOM_BLACK 21
#define COLOR_CUSTOM_GREY 22
#define COLOR_CUSTOM_SELECTED_LIST_ITEM_BG 23
#define COLOR_CUSTOM_ORANGE 24
#define COLOR_CUSTOM_DARK_RED 25

/* if we can't set custom colors, but we have the full 256 color
palette, use ones that most closely match our desired colors */
#define COLOR_256_GREEN 148
#define COLOR_256_RED 167
#define COLOR_256_DARK_RED 160
#define COLOR_256_YELLOW 185
#define COLOR_256_MEDIUM_GRAY 240
#define COLOR_256_ORANGE 208
#define COLOR_256_BLUE 123
#define COLOR_256_OFFWHITE 251

/* vars that hold our actual color definitions. these may change
later during init if the terminal supports > 8 colors */
static int white = COLOR_WHITE;
static int blue = COLOR_BLUE;
static int red = COLOR_RED;
static int darkRed = COLOR_RED;
static int yellow = COLOR_YELLOW;
static int green = COLOR_GREEN;
static int black = COLOR_BLACK;
static int orange = COLOR_YELLOW;
static int foreground = COLOR_WHITE;
static int background = -1;
static int selected = -1;
static int grey = COLOR_WHITE;

#define SCALE(x) ((x * 1000) / 255)

static int initColor(int id, int r, int g, int b) {
    init_color(id, SCALE(r), SCALE(g), SCALE(b));
    return id;
}

/* some terminals report custom colors are supported, and also
don't error when calling init_color(), but don't actually work. */
static bool canChangeColors() {
#ifdef __APPLE__
    const char* termEnv = std::getenv("TERM_PROGRAM");
    std::string term;
    if (termEnv && strlen(termEnv)) {
        term = std::string(termEnv);
        if (term == "Apple_Terminal") {
            return false;
        }
    }
    return can_change_color();
#else
    return can_change_color();
#endif
}

Colors::Colors() {
}

void Colors::Init(bool disableCustomColors) {
    start_color();
    use_default_colors();

    /* the default colors are a bit harsh for my taste, so
    let's use custom colors if the terminal supports it. in
    the future we'll allow users to configure this via setting */
    if (!disableCustomColors && COLORS > 8) {
        if (canChangeColors()) {
            red = initColor(COLOR_CUSTOM_RED, 220, 82, 86);
            darkRed = initColor(COLOR_CUSTOM_DARK_RED, 175, 66, 71);
            green = initColor(COLOR_CUSTOM_GREEN, 166, 226, 46);
            yellow = initColor(COLOR_CUSTOM_YELLOW, 230, 220, 116);
            selected = initColor(COLOR_CUSTOM_SELECTED_LIST_ITEM_BG, 66, 66, 56);
            grey = initColor(COLOR_CUSTOM_GREY, 128, 128, 128);
            orange = initColor(COLOR_CUSTOM_ORANGE, 255, 150, 32);
            blue = initColor(COLOR_CUSTOM_BLUE, 102, 217, 238);
            white = initColor(COLOR_CUSTOM_WHITE, 230, 230, 230);
            foreground = COLOR_CUSTOM_WHITE;
        }
        else if (COLORS >= 256) {
            green = COLOR_256_GREEN;
            red = COLOR_256_RED;
            darkRed = COLOR_256_DARK_RED;
            yellow = COLOR_256_YELLOW;
            selected = COLOR_256_MEDIUM_GRAY;
            grey = COLOR_256_MEDIUM_GRAY;
            orange = COLOR_256_ORANGE;
            blue = COLOR_256_BLUE;
            white = COLOR_256_OFFWHITE;
            foreground = COLOR_256_OFFWHITE;
        }
    }

    init_pair(CURSESPP_SELECTED_LIST_ITEM, yellow, selected);
    init_pair(CURSESPP_HIGHLIGHTED_LIST_ITEM, black, green);
    init_pair(CURSESPP_HIGHLIGHTED_SELECTED_LIST_ITEM, black, yellow);
    init_pair(CURSESPP_LIST_ITEM_HEADER, green, background);

    init_pair(CURSESPP_DEFAULT_CONTENT_COLOR, foreground, background);
    init_pair(CURSESPP_DEFAULT_FRAME_COLOR, foreground, background);
    init_pair(CURSESPP_FOCUSED_FRAME_COLOR, red, background);

    init_pair(CURSESPP_TEXT_DEFAULT, white, background);
    init_pair(CURSESPP_TEXT_DISABLED, grey, background);
    init_pair(CURSESPP_TEXT_FOCUSED, red, background);
    init_pair(CURSESPP_TEXT_ACTIVE, green, background);
    init_pair(CURSESPP_TEXT_WARNING, yellow, background);
    init_pair(CURSESPP_TEXT_ERROR, red, background);
    init_pair(CURSESPP_TEXT_HIDDEN, black, background);
    init_pair(CURSESPP_TEXT_SEPARATOR, orange, background);

    init_pair(CURSESPP_BUTTON_NORMAL, black, yellow);
    init_pair(CURSESPP_BUTTON_NEGATIVE, white, red);
    init_pair(CURSESPP_BUTTON_HIGHLIGHTED, black, green);

    init_pair(CURSESPP_SHORTCUT_ROW_NORMAL, yellow, selected);
    init_pair(CURSESPP_SHORTCUT_ROW_FOCUSED, white, darkRed);

    init_pair(CURSESPP_OVERLAY_FRAME, blue, selected);
    init_pair(CURSESPP_OVERLAY_BACKGROUND, white, selected);
}
<|endoftext|>


<commit_before>#include "layer_pool.h"
#include "common/math.hpp"

namespace ncv
{
        template
        <
                typename tscalar,
                typename tsize
        >
        static void _output(
                const tscalar* idata, tsize irows, tsize icols, tscalar alpha,
                tscalar* wdata, tscalar* sdata, tscalar* cdata, tscalar* odata)
        {
                const tsize orows = (irows + 1) / 2;
                const tsize ocols = (icols + 1) / 2;
                const tscalar ialpha = 1 / alpha;

                auto wmap = tensor::make_matrix(wdata, irows, icols);
                auto smap = tensor::make_matrix(sdata, orows, ocols);
                auto cmap = tensor::make_matrix(cdata, orows, ocols);
                auto omap = tensor::make_matrix(odata, orows, ocols);
                auto imap = tensor::make_matrix(idata, irows, icols);

                wmap = (imap.array() * alpha).exp();

                smap.setZero();
		cmap.setZero();

                for (tsize r = 0, rr = 0; r < irows; r ++, rr = r / 2)
                {
                        for (tsize c = 0, cc = 0; c < icols; c ++, cc = c / 2)
                        {
                                smap(rr, cc) += wmap(r, c);
				cmap(rr, cc) += 1;
                        }
                }

                omap = ialpha * (smap.array() / cmap.array()).log();
        }

        template
        <
                typename tscalar,
                typename tsize
        >
        static void _igrad(
                tscalar* idata, tsize irows, tsize icols,
                const tscalar* wdata, const tscalar* sdata, const tscalar*, const tscalar* gdata)
        {
                const tsize orows = (irows + 1) / 2;
                const tsize ocols = (icols + 1) / 2;

                auto wmap = tensor::make_matrix(wdata, irows, icols);
                auto smap = tensor::make_matrix(sdata, orows, ocols);
                auto gmap = tensor::make_matrix(gdata, orows, ocols);
                auto imap = tensor::make_matrix(idata, irows, icols);

                for (tsize r = 0, rr = 0; r < irows; r ++, rr = r / 2)
                {
                        for (tsize c = 0, cc = 0; c < icols; c ++, cc = c / 2)
                        {
                                imap(r, c) = gmap(rr, cc) * wmap(r, c) / smap(rr, cc);
                        }
                }
        }

        pool_layer_t::pool_layer_t(const string_t& parameters)
                :       layer_t(parameters, "pooling layer, parameters: alpha=[-100.0,+100.0]"),
                        m_alpha(math::clamp(text::from_params<scalar_t>(parameters, "dims", 0.1), -100.0, +100.0))
        {
        }

        size_t pool_layer_t::resize(const tensor_t& tensor)
        {
                const size_t idims = tensor.dims();
                const size_t irows = tensor.rows();
                const size_t icols = tensor.cols();

                const size_t odims = idims;
                const size_t orows = (irows + 1) / 2;
                const size_t ocols = (icols + 1) / 2;

                m_idata.resize(idims, irows, icols);
                m_odata.resize(odims, orows, ocols);

                m_wdata.resize(idims, irows, icols);
                m_sdata.resize(odims, orows, ocols);
                m_cdata.resize(odims, orows, ocols);

                return 0;
        }

        const tensor_t& pool_layer_t::output(const tensor_t& input)
        {
                assert(idims() == input.dims());
                assert(irows() <= input.rows());
                assert(icols() <= input.cols());

                m_idata.copy_from(input);

                for (size_t o = 0; o < odims(); o ++)
                {
                        _output(m_idata.plane_data(o), irows(), icols(), m_alpha,
                                 m_wdata.plane_data(o),
                                 m_sdata.plane_data(o),
				 m_cdata.plane_data(o),
                                 m_odata.plane_data(o));
                }

                return m_odata;
        }

        const tensor_t& pool_layer_t::igrad(const tensor_t& output)
        {
                assert(odims() == output.dims());
                assert(orows() == output.rows());
                assert(ocols() == output.cols());

                for (size_t o = 0; o < odims(); o ++)
                {
                        _igrad(m_idata.plane_data(o), irows(), icols(),
                                  m_wdata.plane_data(o),
                                  m_sdata.plane_data(o),
				  m_cdata.plane_data(o),
                                  output.plane_data(o));
                }

                return m_idata;
        }

        void pool_layer_t::pgrad(const tensor_t& output, scalar_t* gradient)
        {
                assert(odims() == output.dims());
                assert(orows() == output.rows());
                assert(ocols() == output.cols());
        }
}

<commit_msg>cleanup<commit_after>#include "layer_pool.h"
#include "common/math.hpp"

namespace ncv
{
        template
        <
                typename tscalar,
                typename tsize
        >
        static void _output(
                const tscalar* idata, tsize irows, tsize icols, tscalar alpha,
                tscalar* wdata, tscalar* sdata, tscalar* cdata, tscalar* odata)
        {
                const tsize orows = (irows + 1) / 2;
                const tsize ocols = (icols + 1) / 2;
                const tscalar ialpha = 1 / alpha;

                auto wmap = tensor::make_matrix(wdata, irows, icols);
                auto smap = tensor::make_matrix(sdata, orows, ocols);
                auto cmap = tensor::make_matrix(cdata, orows, ocols);
                auto omap = tensor::make_matrix(odata, orows, ocols);
                auto imap = tensor::make_matrix(idata, irows, icols);

                wmap = (imap.array() * alpha).exp();

                smap.setZero();
                cmap.setZero();

                for (tsize r = 0, rr = 0; r < irows; r ++, rr = r / 2)
                {
                        for (tsize c = 0, cc = 0; c < icols; c ++, cc = c / 2)
                        {
                                smap(rr, cc) += wmap(r, c);
                                cmap(rr, cc) += 1;
                        }
                }

                omap = ialpha * (smap.array() / cmap.array()).log();
        }

        template
        <
                typename tscalar,
                typename tsize
        >
        static void _igrad(
                tscalar* idata, tsize irows, tsize icols,
                const tscalar* wdata, const tscalar* sdata, const tscalar*, const tscalar* gdata)
        {
                const tsize orows = (irows + 1) / 2;
                const tsize ocols = (icols + 1) / 2;

                auto wmap = tensor::make_matrix(wdata, irows, icols);
                auto smap = tensor::make_matrix(sdata, orows, ocols);
                auto gmap = tensor::make_matrix(gdata, orows, ocols);
                auto imap = tensor::make_matrix(idata, irows, icols);

                for (tsize r = 0, rr = 0; r < irows; r ++, rr = r / 2)
                {
                        for (tsize c = 0, cc = 0; c < icols; c ++, cc = c / 2)
                        {
                                imap(r, c) = gmap(rr, cc) * wmap(r, c) / smap(rr, cc);
                        }
                }
        }

        pool_layer_t::pool_layer_t(const string_t& parameters)
                :       layer_t(parameters, "pooling layer, parameters: alpha=[-100.0,+100.0]"),
                        m_alpha(math::clamp(text::from_params<scalar_t>(parameters, "dims", 0.1), -100.0, +100.0))
        {
        }

        size_t pool_layer_t::resize(const tensor_t& tensor)
        {
                const size_t idims = tensor.dims();
                const size_t irows = tensor.rows();
                const size_t icols = tensor.cols();

                const size_t odims = idims;
                const size_t orows = (irows + 1) / 2;
                const size_t ocols = (icols + 1) / 2;

                m_idata.resize(idims, irows, icols);
                m_odata.resize(odims, orows, ocols);

                m_wdata.resize(idims, irows, icols);
                m_sdata.resize(odims, orows, ocols);
                m_cdata.resize(odims, orows, ocols);

                return 0;
        }

        const tensor_t& pool_layer_t::output(const tensor_t& input)
        {
                assert(idims() == input.dims());
                assert(irows() <= input.rows());
                assert(icols() <= input.cols());

                m_idata.copy_from(input);

                for (size_t o = 0; o < odims(); o ++)
                {
                        _output(m_idata.plane_data(o), irows(), icols(), m_alpha,
                                 m_wdata.plane_data(o),
                                 m_sdata.plane_data(o),
				 m_cdata.plane_data(o),
                                 m_odata.plane_data(o));
                }

                return m_odata;
        }

        const tensor_t& pool_layer_t::igrad(const tensor_t& output)
        {
                assert(odims() == output.dims());
                assert(orows() == output.rows());
                assert(ocols() == output.cols());

                for (size_t o = 0; o < odims(); o ++)
                {
                        _igrad(m_idata.plane_data(o), irows(), icols(),
                                  m_wdata.plane_data(o),
                                  m_sdata.plane_data(o),
				  m_cdata.plane_data(o),
                                  output.plane_data(o));
                }

                return m_idata;
        }

        void pool_layer_t::pgrad(const tensor_t& output, scalar_t* gradient)
        {
                assert(odims() == output.dims());
                assert(orows() == output.rows());
                assert(ocols() == output.cols());
        }
}

<|endoftext|>


<commit_before>//---------------------------------------------------------
// Copyright 2015 Ontario Institute for Cancer Research
// Written by Jared Simpson (jared.simpson@oicr.on.ca)
//---------------------------------------------------------
//
// nanopolish_squiggle_read -- Class holding a squiggle (event)
// space nanopore read
//
#include <algorithm>
#include "nanopolish_common.h"
#include "nanopolish_squiggle_read.h"
#include "src/fast5.hpp"

//
SquiggleRead::SquiggleRead(const std::string& name, const std::string& path) :
    read_name(name),
    drift_correction_performed(false)
{
    load_from_fast5(path);

    // perform drift correction and other scalings
    transform();
}

SquiggleRead::~SquiggleRead()
{
}

// helper for get_closest_event_to
int SquiggleRead::get_next_event(int start, int stop, int stride, uint32_t strand) const
{
    while(start != stop) {

        int ei = base_to_event_map[start].indices[strand].start;
        if(ei != -1)
            return ei;
        start += stride;
    }
    return -1;
}

//
int SquiggleRead::get_closest_event_to(int k_idx, uint32_t strand) const
{
    uint32_t k = pore_model[T_IDX].k;

    int stop_before = std::max(0, k_idx - 1000);
    int stop_after = std::min(k_idx + 1000, (int32_t)read_sequence.size() - (int32_t)k + 1);

    int event_before = get_next_event(k_idx, stop_before, -1, strand);
    int event_after = get_next_event(k_idx, stop_after, 1, strand);

    // TODO: better selection of "best" event to return
    if(event_before == -1)
        return event_after;
    return event_before;
}

//
void SquiggleRead::transform()
{
    for (size_t si = 0; si < 2; ++si) {
        for(size_t ei = 0; ei < events[si].size(); ++ei) {

            SquiggleEvent& event = events[si][ei];

            // correct level by drift
            double time = event.start_time - events[si][0].start_time;
            event.mean -= (time * pore_model[si].drift);
        }
    }

    drift_correction_performed = true;
}

//
void SquiggleRead::load_from_fast5(const std::string& fast5_path)
{
    fast5::File* f_p;
    this->fast5_path = fast5_path;

    f_p = new fast5::File(fast5_path);
    assert(f_p->is_open());

    // Check if an alternative analysis group is present in the read name
    int group_id = -1;
    /*
    size_t bc_2d_pos = read_name.find("Basecall_2D");
    if(bc_2d_pos != std::string::npos) {
        int ret = sscanf(read_name.substr(bc_2d_pos).c_str(), "Basecall_2D_%03d_2d", &group_id);
    }
    */
    // default to 0 group
    if(group_id == -1) {
        group_id = 0;
    }

    f_p->set_basecalled_group_id(group_id);

    // Automatically detect the read type from the name
    // Set the read type based on the suffix and load the sequence
    assert(!read_name.empty());
    if(ends_with(read_name, "_template")) {
        read_type = SRT_TEMPLATE;
        read_sequence = f_p->basecalled_1D(read_type);
    } else if(ends_with(read_name, "_complement")) {
        read_type = SRT_COMPLEMENT;
        read_sequence = f_p->basecalled_1D(read_type);
    } else {
        read_type = SRT_2D;
        read_sequence = f_p->basecalled_2D();
    }

    // Load PoreModel for both strands
    for (size_t si = 0; si < 2; ++si) {

        // Do we want to load this strand?
        if(! (read_type == SRT_2D || read_type == si) ) {
            continue;
        }

        // Load the pore model for this strand
        pore_model[si] = PoreModel( f_p, si );

        // initialize transition parameters
        parameters[si].initialize(pore_model[si].name);

        // Load the events for this strand
        std::vector<fast5::Event_Entry> f5_events = f_p->get_events(si);

        // copy events
        events[si].resize(f5_events.size());
        for(size_t ei = 0; ei < f5_events.size(); ++ei) {
            const fast5::Event_Entry& f5_event = f5_events[ei];
            events[si][ei] = { static_cast<float>(f5_event.mean),
                               static_cast<float>(f5_event.stdv),
                               static_cast<float>(f5_event.start),
                               static_cast<float>(f5_event.length),
                               static_cast<float>(log(f5_event.stdv)) };
        }

        // build the map from k-mers to events if this is a 1D read
        if(read_type != SRT_2D) {
            build_event_map_1d(f_p, si, f5_events);
        }
    }

    // Both strands need to be loaded before the 2D event map is built
    if(read_type == SRT_2D) {
        build_event_map_2d(f_p);
    }

    delete f_p;
}

void SquiggleRead::build_event_map_1d(fast5::File* f_p, uint32_t strand, std::vector<fast5::Event_Entry>& f5_events)
{
    const uint32_t k = pore_model[T_IDX].k;
    assert(f5_events.size() == events[strand].size());

    // initialize - one entry per read kmer
    uint32_t n_read_kmers = read_sequence.size() - k + 1;
    base_to_event_map.resize(n_read_kmers);

    // The range for the first k-mer always starts at event 0
    assert(f5_events[0].move == 0);
    base_to_event_map[0].indices[strand].start = 0;

    size_t curr_k_idx = 0;
    for(size_t ei = 0; ei < f5_events.size(); ++ei) {
        const fast5::Event_Entry& f5_event = f5_events[ei];

        // Does this event correspond to a different k-mer than the previous one?
        if(f5_event.move > 0) {
            assert(ei != 0);

            // end the range for the current k-mer
            base_to_event_map[curr_k_idx].indices[strand].stop = ei - 1;
            curr_k_idx += f5_event.move;

            // start the range for the next kmer
            base_to_event_map[curr_k_idx].indices[strand].start = ei;
        }

        // ensure the traversal matches the read sequence
        assert(read_sequence.compare(curr_k_idx, k, f5_event.model_state) == 0);
    }
}

void SquiggleRead::build_event_map_2d(fast5::File* f_p)
{
    //
    // Build the map from read k-mers to events
    //

    std::vector<fast5::Event_Alignment_Entry> event_alignments = f_p->get_event_alignments();
    assert(!read_sequence.empty());

    const uint32_t k = pore_model[T_IDX].k;
    assert(pore_model[C_IDX].k == k);

    uint32_t n_read_kmers = read_sequence.size() - k + 1;
    base_to_event_map.resize(n_read_kmers);

    uint32_t read_kidx = 0;

    // The alignment format in the fast5 file is slightly bizarre in that it is
    // (template_idx, complement_idx, kmer) tuples. Some read kmers may not have a
    // tuple and some might have multiple tuples. We need to use the read kmer
    // sequences to work out which read base each entry is referring to
    uint32_t start_ea_idx = 0;
    uint32_t end_ea_idx = 0;

    while(start_ea_idx < event_alignments.size()) {

hack:
        uint32_t prev_kidx = read_kidx;

        // Advance the kmer index until we have found the read kmer
        // this tuple refers to
        while(read_kidx < n_read_kmers &&
              strncmp(event_alignments[start_ea_idx].kmer,
                     read_sequence.c_str() + read_kidx, k) != 0) {
            read_kidx += 1;
        }

        // In the most recent version of metrichor occasionally
        // a kmer will be present in the alignment table
        // that is not in the 2D read. This awful hack
        // will skip such k-mers. It is not a long-term
        // solution, only until metrichor is fixed.
        if(read_kidx - prev_kidx > 10) {
            start_ea_idx += 1;
            read_kidx = prev_kidx;
            goto hack;
        }

        // Advance the event alignment end index to the last tuple
        // with the same kmer as the start of this range
        end_ea_idx = start_ea_idx;
        while(end_ea_idx < event_alignments.size() &&
                strcmp(event_alignments[start_ea_idx].kmer,
                    event_alignments[end_ea_idx].kmer) == 0) {
            end_ea_idx += 1;
        }

        //printf("Base-to-event map kidx: %d %s event_tuple [%d %d]\n", read_kidx, read_sequence.substr(read_kidx, k).c_str(), start_ea_idx, end_ea_idx);
        EventRangeForBase& erfb =  base_to_event_map[read_kidx];
        for(uint32_t i = start_ea_idx; i < end_ea_idx; ++i) {

            fast5::Event_Alignment_Entry& eae = event_alignments[i];

            for(uint32_t si = 0; si <= 1; ++si) {
                int incoming_idx = si == 0 ? eae.template_index : eae.complement_index;

                // no event for this strand, nothing to update
                if(incoming_idx == -1) {
                    continue;
                }
                if(erfb.indices[si].start == -1) {
                    erfb.indices[si].start = incoming_idx;
                }
                erfb.indices[si].stop = incoming_idx;

                assert(erfb.indices[si].start < (int)events[si].size());
                assert(erfb.indices[si].stop < (int)events[si].size());
            }
        }
        //printf("\t[%d %d] [%d %d]\n", erfb.indices[0].start, erfb.indices[0].stop, erfb.indices[1].start, erfb.indices[1].stop);
        start_ea_idx = end_ea_idx;
    }
}

void SquiggleRead::replace_models(const ModelMap& map) {

    for(size_t strand_idx = 0; strand_idx < NUM_STRANDS; ++strand_idx) {
        std::string curr_model = this->pore_model[strand_idx].name;
        auto model_iter = map.find(curr_model);
        if(model_iter != map.end()) {
            this->pore_model[strand_idx].update_states( model_iter->second );
        } else {
            fprintf(stderr, "Error, alternative model %s not found\n", curr_model.c_str());
            exit(EXIT_FAILURE);
        }
    }
}
<commit_msg>do not try to replace the model if its not loaded<commit_after>//---------------------------------------------------------
// Copyright 2015 Ontario Institute for Cancer Research
// Written by Jared Simpson (jared.simpson@oicr.on.ca)
//---------------------------------------------------------
//
// nanopolish_squiggle_read -- Class holding a squiggle (event)
// space nanopore read
//
#include <algorithm>
#include "nanopolish_common.h"
#include "nanopolish_squiggle_read.h"
#include "src/fast5.hpp"

//
SquiggleRead::SquiggleRead(const std::string& name, const std::string& path) :
    read_name(name),
    drift_correction_performed(false)
{
    load_from_fast5(path);

    // perform drift correction and other scalings
    transform();
}

SquiggleRead::~SquiggleRead()
{
}

// helper for get_closest_event_to
int SquiggleRead::get_next_event(int start, int stop, int stride, uint32_t strand) const
{
    while(start != stop) {

        int ei = base_to_event_map[start].indices[strand].start;
        if(ei != -1)
            return ei;
        start += stride;
    }
    return -1;
}

//
int SquiggleRead::get_closest_event_to(int k_idx, uint32_t strand) const
{
    uint32_t k = pore_model[T_IDX].k;

    int stop_before = std::max(0, k_idx - 1000);
    int stop_after = std::min(k_idx + 1000, (int32_t)read_sequence.size() - (int32_t)k + 1);

    int event_before = get_next_event(k_idx, stop_before, -1, strand);
    int event_after = get_next_event(k_idx, stop_after, 1, strand);

    // TODO: better selection of "best" event to return
    if(event_before == -1)
        return event_after;
    return event_before;
}

//
void SquiggleRead::transform()
{
    for (size_t si = 0; si < 2; ++si) {
        for(size_t ei = 0; ei < events[si].size(); ++ei) {

            SquiggleEvent& event = events[si][ei];

            // correct level by drift
            double time = event.start_time - events[si][0].start_time;
            event.mean -= (time * pore_model[si].drift);
        }
    }

    drift_correction_performed = true;
}

//
void SquiggleRead::load_from_fast5(const std::string& fast5_path)
{
    fast5::File* f_p;
    this->fast5_path = fast5_path;

    f_p = new fast5::File(fast5_path);
    assert(f_p->is_open());

    // Check if an alternative analysis group is present in the read name
    int group_id = -1;
    /*
    size_t bc_2d_pos = read_name.find("Basecall_2D");
    if(bc_2d_pos != std::string::npos) {
        int ret = sscanf(read_name.substr(bc_2d_pos).c_str(), "Basecall_2D_%03d_2d", &group_id);
    }
    */
    // default to 0 group
    if(group_id == -1) {
        group_id = 0;
    }

    f_p->set_basecalled_group_id(group_id);

    // Automatically detect the read type from the name
    // Set the read type based on the suffix and load the sequence
    assert(!read_name.empty());
    if(ends_with(read_name, "_template")) {
        read_type = SRT_TEMPLATE;
        read_sequence = f_p->basecalled_1D(read_type);
    } else if(ends_with(read_name, "_complement")) {
        read_type = SRT_COMPLEMENT;
        read_sequence = f_p->basecalled_1D(read_type);
    } else {
        read_type = SRT_2D;
        read_sequence = f_p->basecalled_2D();
    }

    // Load PoreModel for both strands
    for (size_t si = 0; si < 2; ++si) {

        // Do we want to load this strand?
        if(! (read_type == SRT_2D || read_type == si) ) {
            continue;
        }

        // Load the pore model for this strand
        pore_model[si] = PoreModel( f_p, si );

        // initialize transition parameters
        parameters[si].initialize(pore_model[si].name);

        // Load the events for this strand
        std::vector<fast5::Event_Entry> f5_events = f_p->get_events(si);

        // copy events
        events[si].resize(f5_events.size());
        for(size_t ei = 0; ei < f5_events.size(); ++ei) {
            const fast5::Event_Entry& f5_event = f5_events[ei];
            events[si][ei] = { static_cast<float>(f5_event.mean),
                               static_cast<float>(f5_event.stdv),
                               static_cast<float>(f5_event.start),
                               static_cast<float>(f5_event.length),
                               static_cast<float>(log(f5_event.stdv)) };
        }

        // build the map from k-mers to events if this is a 1D read
        if(read_type != SRT_2D) {
            build_event_map_1d(f_p, si, f5_events);
        }
    }

    // Both strands need to be loaded before the 2D event map is built
    if(read_type == SRT_2D) {
        build_event_map_2d(f_p);
    }

    delete f_p;
}

void SquiggleRead::build_event_map_1d(fast5::File* f_p, uint32_t strand, std::vector<fast5::Event_Entry>& f5_events)
{
    const uint32_t k = pore_model[T_IDX].k;
    assert(f5_events.size() == events[strand].size());

    // initialize - one entry per read kmer
    uint32_t n_read_kmers = read_sequence.size() - k + 1;
    base_to_event_map.resize(n_read_kmers);

    // The range for the first k-mer always starts at event 0
    assert(f5_events[0].move == 0);
    base_to_event_map[0].indices[strand].start = 0;

    size_t curr_k_idx = 0;
    for(size_t ei = 0; ei < f5_events.size(); ++ei) {
        const fast5::Event_Entry& f5_event = f5_events[ei];

        // Does this event correspond to a different k-mer than the previous one?
        if(f5_event.move > 0) {
            assert(ei != 0);

            // end the range for the current k-mer
            base_to_event_map[curr_k_idx].indices[strand].stop = ei - 1;
            curr_k_idx += f5_event.move;

            // start the range for the next kmer
            base_to_event_map[curr_k_idx].indices[strand].start = ei;
        }

        // ensure the traversal matches the read sequence
        assert(read_sequence.compare(curr_k_idx, k, f5_event.model_state) == 0);
    }
}

void SquiggleRead::build_event_map_2d(fast5::File* f_p)
{
    //
    // Build the map from read k-mers to events
    //

    std::vector<fast5::Event_Alignment_Entry> event_alignments = f_p->get_event_alignments();
    assert(!read_sequence.empty());

    const uint32_t k = pore_model[T_IDX].k;
    assert(pore_model[C_IDX].k == k);

    uint32_t n_read_kmers = read_sequence.size() - k + 1;
    base_to_event_map.resize(n_read_kmers);

    uint32_t read_kidx = 0;

    // The alignment format in the fast5 file is slightly bizarre in that it is
    // (template_idx, complement_idx, kmer) tuples. Some read kmers may not have a
    // tuple and some might have multiple tuples. We need to use the read kmer
    // sequences to work out which read base each entry is referring to
    uint32_t start_ea_idx = 0;
    uint32_t end_ea_idx = 0;

    while(start_ea_idx < event_alignments.size()) {

hack:
        uint32_t prev_kidx = read_kidx;

        // Advance the kmer index until we have found the read kmer
        // this tuple refers to
        while(read_kidx < n_read_kmers &&
              strncmp(event_alignments[start_ea_idx].kmer,
                     read_sequence.c_str() + read_kidx, k) != 0) {
            read_kidx += 1;
        }

        // In the most recent version of metrichor occasionally
        // a kmer will be present in the alignment table
        // that is not in the 2D read. This awful hack
        // will skip such k-mers. It is not a long-term
        // solution, only until metrichor is fixed.
        if(read_kidx - prev_kidx > 10) {
            start_ea_idx += 1;
            read_kidx = prev_kidx;
            goto hack;
        }

        // Advance the event alignment end index to the last tuple
        // with the same kmer as the start of this range
        end_ea_idx = start_ea_idx;
        while(end_ea_idx < event_alignments.size() &&
                strcmp(event_alignments[start_ea_idx].kmer,
                    event_alignments[end_ea_idx].kmer) == 0) {
            end_ea_idx += 1;
        }

        //printf("Base-to-event map kidx: %d %s event_tuple [%d %d]\n", read_kidx, read_sequence.substr(read_kidx, k).c_str(), start_ea_idx, end_ea_idx);
        EventRangeForBase& erfb =  base_to_event_map[read_kidx];
        for(uint32_t i = start_ea_idx; i < end_ea_idx; ++i) {

            fast5::Event_Alignment_Entry& eae = event_alignments[i];

            for(uint32_t si = 0; si <= 1; ++si) {
                int incoming_idx = si == 0 ? eae.template_index : eae.complement_index;

                // no event for this strand, nothing to update
                if(incoming_idx == -1) {
                    continue;
                }
                if(erfb.indices[si].start == -1) {
                    erfb.indices[si].start = incoming_idx;
                }
                erfb.indices[si].stop = incoming_idx;

                assert(erfb.indices[si].start < (int)events[si].size());
                assert(erfb.indices[si].stop < (int)events[si].size());
            }
        }
        //printf("\t[%d %d] [%d %d]\n", erfb.indices[0].start, erfb.indices[0].stop, erfb.indices[1].start, erfb.indices[1].stop);
        start_ea_idx = end_ea_idx;
    }
}

void SquiggleRead::replace_models(const ModelMap& map) {

    for(size_t strand_idx = 0; strand_idx < NUM_STRANDS; ++strand_idx) {

        // only replace this model if the strand was loaded
        if(! (read_type == SRT_2D || read_type == strand_idx) ) {
            continue;
        }

        std::string curr_model = this->pore_model[strand_idx].name;
        auto model_iter = map.find(curr_model);
        if(model_iter != map.end()) {
            this->pore_model[strand_idx].update_states( model_iter->second );
        } else {
            fprintf(stderr, "Error, alternative model %s not found\n", curr_model.c_str());
            exit(EXIT_FAILURE);
        }
    }
}
<|endoftext|>


<commit_before>#include <map>
#include <string>
#include <set>
#include <memory>
#include <utility>
#include <iostream>
#include <uv.h>

#include "../log.h"
#include "../message.h"
#include "../helper/common.h"
#include "polling_iterator.h"
#include "directory_record.h"

using std::string;
using std::set;
using std::endl;
using std::move;
using std::shared_ptr;

struct FSReq {
  uv_fs_t req;

  ~FSReq() {
    uv_fs_req_cleanup(&req);
  }
};

inline bool ts_less_than(const uv_timespec_t &left, const uv_timespec_t &right)
{
  return left.tv_sec < right.tv_sec ||
    (left.tv_sec == right.tv_sec && left.tv_nsec < right.tv_nsec);
}

inline EntryKind kind_from_stat(const uv_stat_t &st)
{
  if (st.st_flags & S_IFDIR) return KIND_DIRECTORY;
  if (st.st_flags & S_IFREG) return KIND_FILE;
  return KIND_UNKNOWN;
}

DirectoryRecord::DirectoryRecord(string &&name) :
  parent{nullptr},
  name{move(name)},
  populated{false}
{
  //
}

string DirectoryRecord::path() const
{
  return parent == nullptr ? name : path_join(parent->path(), name);
}

void DirectoryRecord::scan(BoundPollingIterator *it)
{
  FSReq scan_req;
  set<Entry> scanned_entries;

  string dir = path();
  int scan_err = uv_fs_scandir(nullptr, &scan_req.req, dir.c_str(), 0, nullptr);
  if (scan_err != 0) {
    LOGGER << "Unable to scan directory " << dir << ": " << uv_strerror(scan_err) << "." << endl;
    return;
  }

  uv_dirent_t dirent;
  int next_err = uv_fs_scandir_next(&scan_req.req, &dirent);
  while (next_err == 0) {
    string entry_name(dirent.name);

    EntryKind entry_kind = KIND_UNKNOWN;
    if (dirent.type == UV_DIRENT_FILE) entry_kind = KIND_FILE;
    if (dirent.type == UV_DIRENT_DIR) entry_kind = KIND_DIRECTORY;

    it->push_entry(string(entry_name), entry_kind);
    if (populated) scanned_entries.emplace(move(entry_name), entry_kind);

    next_err = uv_fs_scandir_next(&scan_req.req, &dirent);
  }

  if (next_err != UV_EOF) {
    LOGGER << "Unable to list entries in directory " << dir << ": " << uv_strerror(next_err) << "." << endl;
  } else {
    // Report entries that were present the last time we scanned this directory, but aren't included in this
    // scan.
    for (auto &previous : entries) {
      const string &previous_entry_name = previous.first;
      EntryKind previous_entry_kind = kind_from_stat(previous.second);
      Entry previous_entry(previous_entry_name, previous_entry_kind);

      if (scanned_entries.count(previous_entry) == 0) {
        entry_deleted(it, previous_entry_name, previous_entry_kind);
      }
    }
  }
}

void DirectoryRecord::entry(
  BoundPollingIterator *it,
  const string &entry_name,
  const string &entry_path,
  EntryKind scan_kind
) {
  FSReq lstat_req;
  EntryKind previous_kind = scan_kind;
  EntryKind current_kind = scan_kind;

  int lstat_err = uv_fs_lstat(nullptr, &lstat_req.req, entry_path.c_str(), nullptr);
  if (lstat_err != 0 && lstat_err != UV_ENOENT && lstat_err != UV_EACCES) {
    LOGGER << "Unable to stat " << entry_path << ": " << uv_strerror(lstat_err) << "." << endl;
  }

  auto previous = entries.find(entry_name);

  bool existed_before = previous != entries.end();
  bool exists_now = lstat_err == 0;

  if (existed_before) previous_kind = kind_from_stat(previous->second);
  if (exists_now) current_kind = kind_from_stat(lstat_req.req.statbuf);

  if (existed_before && exists_now) {
    // Modification or no change
    uv_stat_t &previous_stat = previous->second;
    uv_stat_t &current_stat = lstat_req.req.statbuf;

    // TODO consider modifications to mode or ownership bits?
    if (kinds_are_different(previous_kind, current_kind)) {
      entry_deleted(it, entry_path, previous_kind);
      entry_created(it, entry_path, current_kind);
    } else if (
      previous_stat.st_flags != current_stat.st_flags ||
      previous_stat.st_ino != current_stat.st_ino ||
      ts_less_than(previous_stat.st_mtim, current_stat.st_mtim) ||
      ts_less_than(previous_stat.st_ctim, current_stat.st_ctim)
    ) {
      entry_modified(it, entry_path, current_kind);
    }

  } else if (existed_before && !exists_now) {
    // Deletion

    entry_deleted(it, entry_path, previous_kind);

  } else if (!existed_before && exists_now) {
    // Creation

    if (kinds_are_different(scan_kind, current_kind)) {
      // Entry was created as a file, deleted, then recreated as a directory between scan() and entry()
      // (or vice versa)
      entry_created(it, entry_path, scan_kind);
      entry_deleted(it, entry_path, scan_kind);
    }
    entry_created(it, entry_path, current_kind);

  } else if (!existed_before && !exists_now) {
    // Entry was deleted between scan() and entry().
    // Emit a deletion and creation event pair. Note that the kinds will likely both be KIND_UNKNOWN.

    entry_created(it, entry_path, previous_kind);
    entry_deleted(it, entry_path, current_kind);

  }

  // Update entries with the latest stat information
  if (existed_before) entries.erase(previous);
  if (exists_now) entries.emplace(entry_name, lstat_req.req.statbuf);

  // Update subdirectories if this is or was a subdirectory
  auto dir = subdirectories.find(entry_name);
  if (current_kind != KIND_DIRECTORY && current_kind != KIND_UNKNOWN && dir != subdirectories.end()) {
    subdirectories.erase(dir);
  }
  if (current_kind == KIND_DIRECTORY) {
    if (dir == subdirectories.end()) {
      shared_ptr<DirectoryRecord> subdir(new DirectoryRecord(this, entry_name));
      subdirectories.emplace(entry_name, subdir);
      it->push_directory(subdir);
    } else {
      it->push_directory(dir->second);
    }
  }
}

void DirectoryRecord::entry_deleted(BoundPollingIterator *it, const string &entry_path, EntryKind kind)
{
  if (!populated) return;

  it->get_buffer().deleted(string(entry_path), kind);
}

void DirectoryRecord::entry_created(BoundPollingIterator *it, const string &entry_path, EntryKind kind)
{
  if (!populated) return;

  it->get_buffer().created(string(entry_path), kind);
}

void DirectoryRecord::entry_modified(BoundPollingIterator *it, const string &entry_path, EntryKind kind)
{
  if (!populated) return;

  it->get_buffer().modified(string(entry_path), kind);
}
<commit_msg>Implement private DirectoryRecord constructor<commit_after>#include <map>
#include <string>
#include <set>
#include <memory>
#include <utility>
#include <iostream>
#include <uv.h>

#include "../log.h"
#include "../message.h"
#include "../helper/common.h"
#include "polling_iterator.h"
#include "directory_record.h"

using std::string;
using std::set;
using std::endl;
using std::move;
using std::shared_ptr;

struct FSReq {
  uv_fs_t req;

  ~FSReq() {
    uv_fs_req_cleanup(&req);
  }
};

inline bool ts_less_than(const uv_timespec_t &left, const uv_timespec_t &right)
{
  return left.tv_sec < right.tv_sec ||
    (left.tv_sec == right.tv_sec && left.tv_nsec < right.tv_nsec);
}

inline EntryKind kind_from_stat(const uv_stat_t &st)
{
  if (st.st_flags & S_IFDIR) return KIND_DIRECTORY;
  if (st.st_flags & S_IFREG) return KIND_FILE;
  return KIND_UNKNOWN;
}

DirectoryRecord::DirectoryRecord(string &&name) :
  parent{nullptr},
  name{move(name)},
  populated{false}
{
  //
}

string DirectoryRecord::path() const
{
  return parent == nullptr ? name : path_join(parent->path(), name);
}

void DirectoryRecord::scan(BoundPollingIterator *it)
{
  FSReq scan_req;
  set<Entry> scanned_entries;

  string dir = path();
  int scan_err = uv_fs_scandir(nullptr, &scan_req.req, dir.c_str(), 0, nullptr);
  if (scan_err != 0) {
    LOGGER << "Unable to scan directory " << dir << ": " << uv_strerror(scan_err) << "." << endl;
    return;
  }

  uv_dirent_t dirent;
  int next_err = uv_fs_scandir_next(&scan_req.req, &dirent);
  while (next_err == 0) {
    string entry_name(dirent.name);

    EntryKind entry_kind = KIND_UNKNOWN;
    if (dirent.type == UV_DIRENT_FILE) entry_kind = KIND_FILE;
    if (dirent.type == UV_DIRENT_DIR) entry_kind = KIND_DIRECTORY;

    it->push_entry(string(entry_name), entry_kind);
    if (populated) scanned_entries.emplace(move(entry_name), entry_kind);

    next_err = uv_fs_scandir_next(&scan_req.req, &dirent);
  }

  if (next_err != UV_EOF) {
    LOGGER << "Unable to list entries in directory " << dir << ": " << uv_strerror(next_err) << "." << endl;
  } else {
    // Report entries that were present the last time we scanned this directory, but aren't included in this
    // scan.
    for (auto &previous : entries) {
      const string &previous_entry_name = previous.first;
      EntryKind previous_entry_kind = kind_from_stat(previous.second);
      Entry previous_entry(previous_entry_name, previous_entry_kind);

      if (scanned_entries.count(previous_entry) == 0) {
        entry_deleted(it, previous_entry_name, previous_entry_kind);
      }
    }
  }
}

void DirectoryRecord::entry(
  BoundPollingIterator *it,
  const string &entry_name,
  const string &entry_path,
  EntryKind scan_kind
) {
  FSReq lstat_req;
  EntryKind previous_kind = scan_kind;
  EntryKind current_kind = scan_kind;

  int lstat_err = uv_fs_lstat(nullptr, &lstat_req.req, entry_path.c_str(), nullptr);
  if (lstat_err != 0 && lstat_err != UV_ENOENT && lstat_err != UV_EACCES) {
    LOGGER << "Unable to stat " << entry_path << ": " << uv_strerror(lstat_err) << "." << endl;
  }

  auto previous = entries.find(entry_name);

  bool existed_before = previous != entries.end();
  bool exists_now = lstat_err == 0;

  if (existed_before) previous_kind = kind_from_stat(previous->second);
  if (exists_now) current_kind = kind_from_stat(lstat_req.req.statbuf);

  if (existed_before && exists_now) {
    // Modification or no change
    uv_stat_t &previous_stat = previous->second;
    uv_stat_t &current_stat = lstat_req.req.statbuf;

    // TODO consider modifications to mode or ownership bits?
    if (kinds_are_different(previous_kind, current_kind)) {
      entry_deleted(it, entry_path, previous_kind);
      entry_created(it, entry_path, current_kind);
    } else if (
      previous_stat.st_flags != current_stat.st_flags ||
      previous_stat.st_ino != current_stat.st_ino ||
      ts_less_than(previous_stat.st_mtim, current_stat.st_mtim) ||
      ts_less_than(previous_stat.st_ctim, current_stat.st_ctim)
    ) {
      entry_modified(it, entry_path, current_kind);
    }

  } else if (existed_before && !exists_now) {
    // Deletion

    entry_deleted(it, entry_path, previous_kind);

  } else if (!existed_before && exists_now) {
    // Creation

    if (kinds_are_different(scan_kind, current_kind)) {
      // Entry was created as a file, deleted, then recreated as a directory between scan() and entry()
      // (or vice versa)
      entry_created(it, entry_path, scan_kind);
      entry_deleted(it, entry_path, scan_kind);
    }
    entry_created(it, entry_path, current_kind);

  } else if (!existed_before && !exists_now) {
    // Entry was deleted between scan() and entry().
    // Emit a deletion and creation event pair. Note that the kinds will likely both be KIND_UNKNOWN.

    entry_created(it, entry_path, previous_kind);
    entry_deleted(it, entry_path, current_kind);

  }

  // Update entries with the latest stat information
  if (existed_before) entries.erase(previous);
  if (exists_now) entries.emplace(entry_name, lstat_req.req.statbuf);

  // Update subdirectories if this is or was a subdirectory
  auto dir = subdirectories.find(entry_name);
  if (current_kind != KIND_DIRECTORY && current_kind != KIND_UNKNOWN && dir != subdirectories.end()) {
    subdirectories.erase(dir);
  }
  if (current_kind == KIND_DIRECTORY) {
    if (dir == subdirectories.end()) {
      shared_ptr<DirectoryRecord> subdir(new DirectoryRecord(this, entry_name));
      subdirectories.emplace(entry_name, subdir);
      it->push_directory(subdir);
    } else {
      it->push_directory(dir->second);
    }
  }
}

DirectoryRecord::DirectoryRecord(DirectoryRecord *parent, const string &name) :
  parent{parent},
  name(move(name)),
  populated{false}
{
  //
}

void DirectoryRecord::entry_deleted(BoundPollingIterator *it, const string &entry_path, EntryKind kind)
{
  if (!populated) return;

  it->get_buffer().deleted(string(entry_path), kind);
}

void DirectoryRecord::entry_created(BoundPollingIterator *it, const string &entry_path, EntryKind kind)
{
  if (!populated) return;

  it->get_buffer().created(string(entry_path), kind);
}

void DirectoryRecord::entry_modified(BoundPollingIterator *it, const string &entry_path, EntryKind kind)
{
  if (!populated) return;

  it->get_buffer().modified(string(entry_path), kind);
}
<|endoftext|>


<commit_before>#include <vector>
#include <boost/test/unit_test.hpp>
#include <boost/foreach.hpp>

#include "script.h"
#include "key.h"

using namespace std;

// Helpers:
static std::vector<unsigned char>
Serialize(const CScript& s)
{
    std::vector<unsigned char> sSerialized(s);
    return sSerialized;
}

BOOST_AUTO_TEST_SUITE(sigopcount_tests)

BOOST_AUTO_TEST_CASE(GetSigOpCount)
{
    // Test CScript::GetSigOpCount()
    CScript s1;
    BOOST_CHECK_EQUAL(s1.GetSigOpCount(false), 0);
    BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 0);

    uint160 dummy;
    s1 << OP_1 << dummy << dummy << OP_2 << OP_CHECKMULTISIG;
    BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 2);
    s1 << OP_IF << OP_CHECKSIG << OP_ENDIF;
    BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 3);
    BOOST_CHECK_EQUAL(s1.GetSigOpCount(false), 21);

    CScript p2sh;
    p2sh.SetDestination(s1.GetID());
    CScript scriptSig;
    scriptSig << OP_0 << Serialize(s1);
    BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(scriptSig), 3);

    std::vector<CKey> keys;
    for (int i = 0; i < 3; i++)
    {
        CKey k;
        k.MakeNewKey(true);
        keys.push_back(k);
    }
    CScript s2;
    s2.SetMultisig(1, keys);
    BOOST_CHECK_EQUAL(s2.GetSigOpCount(true), 3);
    BOOST_CHECK_EQUAL(s2.GetSigOpCount(false), 20);

    p2sh.SetDestination(s2.GetID());
    BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(true), 0);
    BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(false), 0);
    CScript scriptSig2;
    scriptSig2 << OP_1 << dummy << dummy << Serialize(s2);
    BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(scriptSig2), 3);
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Delete sigopcount_tests.cpp<commit_after><|endoftext|>


<commit_before>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include <fnord-json/json.h>
#include "reports/TermInfoTableSink.h"

using namespace fnord;

namespace cm {

TermInfoTableSink::TermInfoTableSink(
    const String& output_file) :
    output_file_(output_file) {
  sstable_schema_.addColumn("related_terms", 1, sstable::SSTableColumnType::STRING);
}

void TermInfoTableSink::open() {
  if (FileUtil::exists(output_file_ + "~")) {
    fnord::logInfo(
        "cm.reportbuild",
        "Deleting orphaned temp file: $0",
        output_file_ + "~");

    FileUtil::rm(output_file_ + "~");
  }

  fnord::logInfo(
      "cm.reportbuild",
      "Opening output sstable: $0",
      output_file_);

  sstable_writer_ = sstable::SSTableWriter::create(
      output_file_ + "~",
      sstable::IndexProvider{},
      nullptr,
      0);
}

void TermInfoTableSink::addRow(
      const String& lang,
      const String& term,
      const HashMap<String, uint64_t>& related_terms) {
  auto key = lang + "~" + term;

  sstable::SSTableColumnWriter cols(&sstable_schema_);
  cols.addStringColumn(1, "fnord");
  sstable_writer_->appendRow(key, cols);
}

void TermInfoTableSink::close() {
  fnord::logInfo(
      "cm.reportbuild",
      "Finalizing output sstable: $0",
      output_file_);

  sstable_schema_.writeIndex(sstable_writer_.get());
  sstable_writer_->finalize();

  FileUtil::mv(output_file_ + "~", output_file_);
}

Set<String> TermInfoTableSink::outputFiles() {
  return Set<String> { output_file_ };
}

} // namespace cm

<commit_msg>write similar terms to output table<commit_after>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include <fnord-json/json.h>
#include "reports/TermInfoTableSink.h"

using namespace fnord;

namespace cm {

TermInfoTableSink::TermInfoTableSink(
    const String& output_file) :
    output_file_(output_file) {
  sstable_schema_.addColumn("related_terms", 1, sstable::SSTableColumnType::STRING);
}

void TermInfoTableSink::open() {
  if (FileUtil::exists(output_file_ + "~")) {
    fnord::logInfo(
        "cm.reportbuild",
        "Deleting orphaned temp file: $0",
        output_file_ + "~");

    FileUtil::rm(output_file_ + "~");
  }

  fnord::logInfo(
      "cm.reportbuild",
      "Opening output sstable: $0",
      output_file_);

  sstable_writer_ = sstable::SSTableWriter::create(
      output_file_ + "~",
      sstable::IndexProvider{},
      nullptr,
      0);
}

void TermInfoTableSink::addRow(
      const String& lang,
      const String& term,
      const HashMap<String, uint64_t>& related_terms) {
  auto key = lang + "~" + term;

  String terms_str;
  for (const auto t : related_terms) {
    terms_str += StringUtil::format("$0:$1,", t.first, t.second);
  }

  sstable::SSTableColumnWriter cols(&sstable_schema_);
  cols.addStringColumn(1, terms_str);
  sstable_writer_->appendRow(key, cols);
}

void TermInfoTableSink::close() {
  fnord::logInfo(
      "cm.reportbuild",
      "Finalizing output sstable: $0",
      output_file_);

  sstable_schema_.writeIndex(sstable_writer_.get());
  sstable_writer_->finalize();

  FileUtil::mv(output_file_ + "~", output_file_);
}

Set<String> TermInfoTableSink::outputFiles() {
  return Set<String> { output_file_ };
}

} // namespace cm

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2017 ARM Limited.
 *
 * SPDX-License-Identifier: MIT
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
#include "arm_compute/runtime/OMP/OMPScheduler.h"

#include "arm_compute/core/CPP/ICPPKernel.h"
#include "arm_compute/core/Error.h"
#include "arm_compute/core/Helpers.h"
#include "arm_compute/core/Utils.h"

#include <omp.h>

using namespace arm_compute;

OMPScheduler &OMPScheduler::get()
{
    static OMPScheduler scheduler;
    return scheduler;
}

OMPScheduler::OMPScheduler() // NOLINT
    : _num_threads(omp_get_max_threads())
{
}

unsigned int OMPScheduler::num_threads() const
{
    return _num_threads;
}

void OMPScheduler::set_num_threads(unsigned int num_threads)
{
    const unsigned int num_cores = omp_get_max_threads();
    _num_threads                 = (num_threads == 0) ? num_cores : num_threads;
}

void OMPScheduler::schedule(ICPPKernel *kernel, unsigned int split_dimension)
{
    ARM_COMPUTE_ERROR_ON_MSG(!kernel, "The child class didn't set the kernel");

    ThreadInfo info;
    info.cpu_info = _info;

    const Window      &max_window     = kernel->window();
    const unsigned int num_iterations = max_window.num_iterations(split_dimension);
    info.num_threads                  = std::min(num_iterations, _num_threads);

    if(!kernel->is_parallelisable() || info.num_threads == 1)
    {
        kernel->run(max_window, info);
    }
    else
    {
        #pragma omp parallel num_threads(info.num_threads)
        {
            #pragma omp for
            for(int t = 0; t < info.num_threads; ++t)
            {
                Window win     = max_window.split_window(split_dimension, t, info.num_threads);
                info.thread_id = t;
                kernel->run(win, info);
            }
        }
    }
}
<commit_msg>Fix race condition on info.thread_id in OpenMP scheduler (#399)<commit_after>/*
 * Copyright (c) 2017 ARM Limited.
 *
 * SPDX-License-Identifier: MIT
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
#include "arm_compute/runtime/OMP/OMPScheduler.h"

#include "arm_compute/core/CPP/ICPPKernel.h"
#include "arm_compute/core/Error.h"
#include "arm_compute/core/Helpers.h"
#include "arm_compute/core/Utils.h"

#include <omp.h>

using namespace arm_compute;

OMPScheduler &OMPScheduler::get()
{
    static OMPScheduler scheduler;
    return scheduler;
}

OMPScheduler::OMPScheduler() // NOLINT
    : _num_threads(omp_get_max_threads())
{
}

unsigned int OMPScheduler::num_threads() const
{
    return _num_threads;
}

void OMPScheduler::set_num_threads(unsigned int num_threads)
{
    const unsigned int num_cores = omp_get_max_threads();
    _num_threads                 = (num_threads == 0) ? num_cores : num_threads;
}

void OMPScheduler::schedule(ICPPKernel *kernel, unsigned int split_dimension)
{
    ARM_COMPUTE_ERROR_ON_MSG(!kernel, "The child class didn't set the kernel");

    ThreadInfo info;
    info.cpu_info = _info;

    const Window      &max_window     = kernel->window();
    const unsigned int num_iterations = max_window.num_iterations(split_dimension);
    info.num_threads                  = std::min(num_iterations, _num_threads);

    if(!kernel->is_parallelisable() || info.num_threads == 1)
    {
        kernel->run(max_window, info);
    }
    else
    {
        #pragma omp parallel private(info) num_threads(info.num_threads)
        {
            const int tid  = omp_get_thread_num();
            Window win     = max_window.split_window(split_dimension, tid, info.num_threads);
            info.thread_id = tid;
            kernel->run(win, info);
        }
    }
}
<|endoftext|>