text:
// Copyright 2014 Cloudera Inc.
//
// 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 "exec/data-source-scan-node.h"

#include <boost/foreach.hpp>
#include <vector>
#include <gutil/strings/substitute.h>

#include "exec/data-source-row-converter.h"
#include "exec/parquet-common.h"
#include "exec/read-write-util.h"
#include "exprs/expr.h"
#include "runtime/mem-pool.h"
#include "runtime/runtime-state.h"
#include "runtime/row-batch.h"
#include "runtime/string-value.h"
#include "runtime/tuple-row.h"
#include "util/jni-util.h"
#include "util/periodic-counter-updater.h"
#include "util/runtime-profile.h"

#include "common/names.h"

using namespace strings;
using namespace impala;
using namespace impala::extdatasource;

DEFINE_int32(data_source_batch_size, 1024, "Batch size for calls to GetNext() on "
    "external data sources.");

namespace impala {

DataSourceScanNode::DataSourceScanNode(ObjectPool* pool, const TPlanNode& tnode,
    const DescriptorTbl& descs)
    : ScanNode(pool, tnode, descs),
      data_src_node_(tnode.data_source_node),
      tuple_idx_(0) {
}

DataSourceScanNode::~DataSourceScanNode() {
}

Status DataSourceScanNode::Prepare(RuntimeState* state) {
  RETURN_IF_ERROR(ScanNode::Prepare(state));
  tuple_desc_ = state->desc_tbl().GetTupleDescriptor(data_src_node_.tuple_id);
  DCHECK(tuple_desc_ != NULL);

  data_source_executor_.reset(new ExternalDataSourceExecutor());
  RETURN_IF_ERROR(data_source_executor_->Init(data_src_node_.data_source.hdfs_location,
      data_src_node_.data_source.class_name, data_src_node_.data_source.api_version,
      data_src_node_.init_string));

  // Initialize materialized_slots_
  BOOST_FOREACH(SlotDescriptor* slot, tuple_desc_->slots()) {
    if (!slot->is_materialized()) continue;
    materialized_slots_.push_back(slot);
  }

  row_converter_.reset(
      new DataSourceRowConverter(tuple_desc_, NULL, materialized_slots_));
  return Status::OK();
}

Status DataSourceScanNode::Open(RuntimeState* state) {
  SCOPED_TIMER(runtime_profile_->total_time_counter());
  RETURN_IF_ERROR(ExecNode::Open(state));
  RETURN_IF_CANCELLED(state);

  // Prepare the schema for TOpenParams.row_schema
  vector<extdatasource::TColumnDesc> cols;
  BOOST_FOREACH(const SlotDescriptor* slot, materialized_slots_) {
    extdatasource::TColumnDesc col;
    int col_idx = slot->col_pos();
    col.__set_name(tuple_desc_->table_desc()->col_descs()[col_idx].name());
    col.__set_type(slot->type().ToThrift());
    cols.push_back(col);
  }
  extdatasource::TTableSchema row_schema;
  row_schema.__set_cols(cols);

  TOpenParams params;
  params.__set_query_id(state->query_id());
  params.__set_table_name(tuple_desc_->table_desc()->name());
  params.__set_init_string(data_src_node_.init_string);
  params.__set_authenticated_user_name(state->effective_user());
  params.__set_row_schema(row_schema);
  params.__set_batch_size(FLAGS_data_source_batch_size);
  params.__set_predicates(data_src_node_.accepted_predicates);
  TOpenResult result;
  RETURN_IF_ERROR(data_source_executor_->Open(params, &result));
  RETURN_IF_ERROR(Status(result.status));
  scan_handle_ = result.scan_handle;
  return GetNextInputBatch();
}

Status DataSourceScanNode::GetNextInputBatch() {
  input_batch_.reset(new TGetNextResult());
  TGetNextParams params;
  params.__set_scan_handle(scan_handle_);
  RETURN_IF_ERROR(data_source_executor_->GetNext(params, input_batch_.get()));
  RETURN_IF_ERROR(Status(input_batch_->status));

  if (input_batch_->__isset.rows) {
    RETURN_IF_ERROR(row_converter_->ResetRowBatch(&input_batch_->rows, true));
  }

  if (!InputBatchHasNext() && !input_batch_->eos) {
    // The data source should have set eos, but if it didn't we should just log a
    // warning and continue as if it had.
    VLOG_QUERY << "Data source " << data_src_node_.data_source.name << " returned no "
      << "rows but did not set 'eos'. No more rows will be fetched from the "
      << "data source.";
    input_batch_->eos = true;
  }
  return Status::OK();
}

Status DataSourceScanNode::GetNext(RuntimeState* state, RowBatch* row_batch, bool* eos) {
  RETURN_IF_ERROR(ExecDebugAction(TExecNodePhase::GETNEXT, state));
  RETURN_IF_CANCELLED(state);
  RETURN_IF_ERROR(QueryMaintenance(state));
  SCOPED_TIMER(runtime_profile_->total_time_counter());
  if (ReachedLimit()) {
    *eos = true;
    return Status::OK();
  }
  *eos = false;

  // create new tuple buffer for row_batch
  MemPool* tuple_pool = row_batch->tuple_data_pool();
  int tuple_buffer_size = row_batch->MaxTupleBufferSize();
  void* tuple_buffer = tuple_pool->Allocate(tuple_buffer_size);
  tuple_ = reinterpret_cast<Tuple*>(tuple_buffer);
  ExprContext** ctxs = &conjunct_ctxs_[0];
  int num_ctxs = conjunct_ctxs_.size();

  while (true) {
    {
      SCOPED_TIMER(materialize_tuple_timer());
      // copy rows until we hit the limit/capacity or until we exhaust input_batch_
      while (!ReachedLimit() && !row_batch->AtCapacity(tuple_pool) &&
          InputBatchHasNext()) {
        RETURN_IF_ERROR(row_converter_->MaterializeNextRow(tuple_, tuple_pool));
        int row_idx = row_batch->AddRow();
        TupleRow* tuple_row = row_batch->GetRow(row_idx);
        tuple_row->SetTuple(tuple_idx_, tuple_);

        if (ExecNode::EvalConjuncts(ctxs, num_ctxs, tuple_row)) {
          row_batch->CommitLastRow();
          char* new_tuple = reinterpret_cast<char*>(tuple_);
          new_tuple += tuple_desc_->byte_size();
          tuple_ = reinterpret_cast<Tuple*>(new_tuple);
          ++num_rows_returned_;
        }
      }
      COUNTER_SET(rows_returned_counter_, num_rows_returned_);

      if (ReachedLimit() || row_batch->AtCapacity() || input_batch_->eos) {
        *eos = ReachedLimit() || input_batch_->eos;
        return Status::OK();
      }
    }

    // Need more rows
    DCHECK(!InputBatchHasNext());
    RETURN_IF_ERROR(GetNextInputBatch());
  }
}

Status DataSourceScanNode::Reset(RuntimeState* state) {
  DCHECK(false) << "NYI";
  return Status("NYI");
}

void DataSourceScanNode::Close(RuntimeState* state) {
  if (is_closed()) return;
  SCOPED_TIMER(runtime_profile_->total_time_counter());
  PeriodicCounterUpdater::StopRateCounter(total_throughput_counter());
  PeriodicCounterUpdater::StopTimeSeriesCounter(bytes_read_timeseries_counter_);
  input_batch_.reset();
  TCloseParams params;
  params.__set_scan_handle(scan_handle_);
  TCloseResult result;
  Status status = data_source_executor_->Close(params, &result);
  if (!status.ok()) state->LogError(status.msg());
  ExecNode::Close(state);
}

void DataSourceScanNode::DebugString(int indentation_level, stringstream* out) const {
  string indent(indentation_level * 2, ' ');
  *out << indent << "DataSourceScanNode(tupleid=" << data_src_node_.tuple_id << ")";
}

}  // namespace impala

ext: cc

max_stars_repo_name: drankye/recordservice

max_issues_repo_name: drankye/recordservice

max_forks_repo_name: drankye/recordservice


text:
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 "kudu/tserver/mini_tablet_server.h"

#include <ostream>
#include <utility>
#include <vector>

#include <boost/optional/optional.hpp>
#include <gflags/gflags_declare.h>
#include <glog/logging.h>

#include "kudu/common/common.pb.h"
#include "kudu/common/partition.h"
#include "kudu/common/schema.h"
#include "kudu/common/wire_protocol.pb.h"
#include "kudu/consensus/metadata.pb.h"
#include "kudu/fs/fs_manager.h"
#include "kudu/gutil/ref_counted.h"
#include "kudu/gutil/strings/substitute.h"
#include "kudu/server/rpc_server.h"
#include "kudu/server/webserver_options.h"
#include "kudu/tablet/tablet-harness.h"
#include "kudu/tablet/tablet_replica.h"
#include "kudu/tserver/tablet_server.h"
#include "kudu/tserver/ts_tablet_manager.h"
#include "kudu/util/env.h"
#include "kudu/util/env_util.h"
#include "kudu/util/net/net_util.h"
#include "kudu/util/net/sockaddr.h"
#include "kudu/util/path_util.h"
#include "kudu/util/status.h"

DECLARE_bool(enable_minidumps);
DECLARE_bool(rpc_server_allow_ephemeral_ports);

using kudu::tablet::TabletReplica;
using kudu::consensus::RaftPeerPB;
using kudu::consensus::RaftConfigPB;
using std::pair;
using std::string;
using std::unique_ptr;
using std::vector;
using strings::Substitute;

namespace kudu {
namespace tserver {

MiniTabletServer::MiniTabletServer(string fs_root,
                                   const HostPort& rpc_bind_addr,
                                   int num_data_dirs)
    : fs_root_(std::move(fs_root)) {
  // Disable minidump handler (we allow only one per process).
  FLAGS_enable_minidumps = false;
  // Start RPC server on loopback.
  FLAGS_rpc_server_allow_ephemeral_ports = true;
  opts_.rpc_opts.rpc_bind_addresses = rpc_bind_addr.ToString();
  opts_.webserver_opts.bind_interface = rpc_bind_addr.host();
  opts_.webserver_opts.port = 0;
  if (num_data_dirs == 1) {
    opts_.fs_opts.wal_root = fs_root_;
    opts_.fs_opts.data_roots = { fs_root_ };
  } else {
    vector<string> fs_data_dirs;
    for (int dir = 0; dir < num_data_dirs; dir++) {
      fs_data_dirs.emplace_back(JoinPathSegments(fs_root_, Substitute("data-$0", dir)));
    }
    opts_.fs_opts.wal_root = JoinPathSegments(fs_root_, "wal");
    opts_.fs_opts.data_roots = fs_data_dirs;
  }
}

MiniTabletServer::~MiniTabletServer() {
  Shutdown();
}

Status MiniTabletServer::Start() {
  CHECK(!server_);
  // In case the wal dir and data dirs are subdirectories of the root directory,
  // ensure the root directory exists.
  RETURN_NOT_OK(env_util::CreateDirIfMissing(Env::Default(), fs_root_));
  unique_ptr<TabletServer> server(new TabletServer(opts_));
  RETURN_NOT_OK(server->Init());
  RETURN_NOT_OK(server->Start());
  server_.swap(server);

  return Status::OK();
}

Status MiniTabletServer::WaitStarted() {
  return server_->WaitInited();
}

void MiniTabletServer::Shutdown() {
  if (server_) {
    // Save the bound addrs back into the options structure so that, if we restart the
    // server, it will come back on the same address. This is necessary since we don't
    // currently support tablet servers re-registering on different ports (KUDU-418).
    opts_.rpc_opts.rpc_bind_addresses = bound_rpc_addr().ToString();
    opts_.webserver_opts.port = bound_http_addr().port();
    server_->Shutdown();
    server_.reset();
  }
}

Status MiniTabletServer::Restart() {
  return Start();
}

RaftConfigPB MiniTabletServer::CreateLocalConfig() const {
  CHECK(server_) << "must call Start() first";
  RaftConfigPB config;
  RaftPeerPB* peer = config.add_peers();
  peer->set_permanent_uuid(server_->instance_pb().permanent_uuid());
  peer->set_member_type(RaftPeerPB::VOTER);
  peer->mutable_last_known_addr()->set_host(bound_rpc_addr().host());
  peer->mutable_last_known_addr()->set_port(bound_rpc_addr().port());
  return config;
}

Status MiniTabletServer::AddTestTablet(const std::string& table_id,
                                       const std::string& tablet_id,
                                       const Schema& schema) {
  return AddTestTablet(table_id, tablet_id, schema, CreateLocalConfig());
}

Status MiniTabletServer::AddTestTablet(const std::string& table_id,
                                       const std::string& tablet_id,
                                       const Schema& schema,
                                       const RaftConfigPB& config) {
  Schema schema_with_ids = SchemaBuilder(schema).Build();
  pair<PartitionSchema, Partition> partition = tablet::CreateDefaultPartition(schema_with_ids);

  return server_->tablet_manager()->CreateNewTablet(
      table_id, tablet_id, partition.second, table_id,
      schema_with_ids, partition.first, config, boost::none, boost::none, boost::none, nullptr);
}

vector<string> MiniTabletServer::ListTablets() const {
  vector<string> tablet_ids;
  vector<scoped_refptr<TabletReplica>> replicas;
  server_->tablet_manager()->GetTabletReplicas(&replicas);
  for (const auto& replica : replicas) {
    tablet_ids.push_back(replica->tablet_id());
  }
  return tablet_ids;
}

void MiniTabletServer::FailHeartbeats() {
  server_->set_fail_heartbeats_for_tests(true);
}

const Sockaddr MiniTabletServer::bound_rpc_addr() const {
  return server_->first_rpc_address();
}

const Sockaddr MiniTabletServer::bound_http_addr() const {
  return server_->first_http_address();
}

const string& MiniTabletServer::uuid() const {
  return server_->fs_manager()->uuid();
}

} // namespace tserver
} // namespace kudu

max_stars_repo_name: attilabukor/kudu

max_issues_repo_name: attilabukor/kudu

max_forks_repo_name: attilabukor/kudu


text:
#include <iostream>
#include <boost/shared_ptr.hpp>

class Test
{
public:
	float floating;

	Test()
	{
		this->floating = 3.0f;
	}

	~Test()
	{
		std::cout << "Destructed in Test." << std::endl;
	}
};

class Test2
{
public:
	int integer;
	Test test;

	~Test2()
	{
		std::cout << "Destructed in Test" << integer << "." << std::endl;
	}
};

int main()
{
	//Test2 test2;
	//{
	//Test2 test5;

	//test5.integer = 5;

	//test2 = test5;
	//}

	Test2 test2;
	Test test;

	test2.test = test;

	std::cout << test2.integer << std::endl;

	return 0;
}

ext: cpp

max_stars_repo_name: taku-xhift/labo

max_issues_repo_name: taku-xhift/labo

max_forks_repo_name: taku-xhift/labo


text:
/*!
 * Copyright (c) 2021 Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See LICENSE file in the project root for license information.
 */
#include "ObjectResolutionVisitor.h"

#include <boost/cast.hpp>
#include <boost/foreach.hpp>
#include <boost/make_shared.hpp>
#include "CompoundType.h"
#include "FreeForm2Assert.h"
#include "MemberAccessExpression.h"
#include "Mutation.h"
#include "RefExpression.h"
#include <sstream>
#include "StateMachine.h"
#include "TypeManager.h"

FreeForm2::ObjectResolutionVisitor::ObjectResolutionVisitor()
{
}

bool FreeForm2::ObjectResolutionVisitor::AlternativeVisit(const StateMachineExpression &p_expr)
{
    FF2_ASSERT(p_expr.GetType().Primitive() == Type::StateMachine);
    const TypeImpl &copiedType = CopyType(p_expr.GetType());
    FF2_ASSERT(copiedType.IsSameAs(p_expr.GetType(), false));
    const StateMachineType &machineType = static_cast<const StateMachineType &>(copiedType);

    m_thisTypeStack.push(&machineType);
    const bool result = CopyingVisitor::AlternativeVisit(p_expr);
    FF2_ASSERT(m_thisTypeStack.top() == &machineType);
    m_thisTypeStack.pop();

    // Assert that we are correct in not calling the CopyingVisitor::Visit
    // method for this expression.
    FF2_ASSERT(result);
    return true;
}

void FreeForm2::ObjectResolutionVisitor::Visit(const ThisExpression &p_expr)
{
    if (m_thisTypeStack.empty())
    {
        std::ostringstream err;
        err << "Invalid this reference: not in object scope";
        throw ParseError(err.str(), p_expr.GetSourceLocation());
    }

    const CompoundType &currentThisType = *m_thisTypeStack.top();
    if (p_expr.GetType().Primitive() != Type::Unknown && !p_expr.GetType().IsSameAs(currentThisType, false))
    {
        std::ostringstream err;
        err << "Object types not compatible. Expected type: "
            << currentThisType << "; found type: "
            << p_expr.GetType();
        throw ParseError(err.str(), p_expr.GetSourceLocation());
    }

    AddExpression(boost::make_shared<ThisExpression>(p_expr.GetAnnotations(),
                                                     currentThisType));
}

void FreeForm2::ObjectResolutionVisitor::Visit(const UnresolvedAccessExpression &p_expr)
{
    const Expression &object = *m_stack.back();
    m_stack.pop_back();

    if (object.GetType().Primitive() != Type::StateMachine)
    {
        std::ostringstream err;
        err << "Unable to resolve member" << p_expr.GetMemberName()
            << " on type " << object.GetType();
        throw ParseError(err.str(), p_expr.GetSourceLocation());
    }

    const StateMachineType &type = static_cast<const StateMachineType &>(object.GetType());

    const std::string memberName = StateMachineExpression::GetAugmentedMemberName(type.GetName(), p_expr.GetMemberName());

    const CompoundType::Member *member = type.FindMember(memberName);
    if (member == NULL)
    {
        std::ostringstream err;
        err << "Unable to resolve member " << p_expr.GetMemberName()
            << " on type " << object.GetType();
        throw ParseError(err.str(), p_expr.GetSourceLocation());
    }

    if (!member->m_type->IsSameAs(p_expr.GetType(), false) && p_expr.GetType().Primitive() != Type::Unknown)
    {
        std::ostringstream err;
        err << "expected member " << p_expr.GetMemberName()
            << " to be type " << p_expr.GetType()
            << " but encountered type " << *member->m_type;
        throw ParseError(err.str(), p_expr.GetSourceLocation());
    }

    AddExpression(boost::make_shared<MemberAccessExpression>(p_expr.GetAnnotations(),
                                                             object,
                                                             *member,
                                                             0));
}

bool FreeForm2::ObjectResolutionVisitor::AlternativeVisit(const TypeInitializerExpression &p_expr)
{
    FF2_ASSERT(p_expr.GetType().Primitive() == Type::StateMachine);
    const TypeImpl &copiedType = CopyType(p_expr.GetType());
    FF2_ASSERT(copiedType.IsSameAs(p_expr.GetType(), false));
    const StateMachineType &machineType = static_cast<const StateMachineType &>(copiedType);

    m_thisTypeStack.push(&machineType);
    const bool result = CopyingVisitor::AlternativeVisit(p_expr);
    FF2_ASSERT(m_thisTypeStack.top() == &machineType);
    m_thisTypeStack.pop();

    // Assert that we are correct in not calling the CopyingVisitor::Visit
    // method for this expression.
    FF2_ASSERT(result);
    return true;
}

max_stars_repo_name: ltxtech/lightgbm-transform

max_issues_repo_name: ltxtech/lightgbm-transform

max_forks_repo_name: ltxtech/lightgbm-transform


text:
//
//  main.cpp
//  edgeRuntime
//
//  Created by Abdelrahaman Aly on 31/10/13.
//  Copyright (c) 2013 Abdelrahaman Aly. All rights reserved.
//

//Generic Headers
#include <iostream>

//#include <String>
#include <cstdlib>
#include <ctime>
#include <sys/time.h>
#include <pthread.h>

//#include <mach/mach.h>
//#include <mach/mach_time.h>

//Library Headers
#include <NTL/ZZ_pXFactoring.h>
#include <NTL/ZZ_pEX.h>
#include <NTL/ZZ_pX.h>
#include <NTL/ZZ_pE.h>
#include <NTL/ZZ.h>
#include <NTL/ZZ_p.h>

//Custom Headers
#include "StandardShare.h"
#include "Constants.h"
#include "StandardPlayer.h"
#include "ShamirSharesEngine.h"
#include "SocketPool.h"
#include "EngineBuffers.h"
#include "StandardBid.h"
#include "ReducedBid.h"
#include "AuctionResponse.h"
#include "LocationalAuction.h"
#include "PushRelabel.h"
#include "BellmanFord.h"
#include "List.h"
#include "Matrix.h"
#include "MathUtil.h"
#include "ShareUtil.h"
#include "LocationalAuctionUtil.h"
#include "PermutationMatrix.h"
#include "ShareUtil.h"

NTL_CLIENT
using namespace Applications::Auctions;
//using namespace std;

/**
 @mainpage Library code  "Edge Runtime".
 *Is a collection of libraries that implements a vast array of secure functionality. From comparison Methods and equality tests \cite Toft13 and \cite DKNT06 to the calculus of the inverse and xor gates.
 *
 *The framework relies on a synchronic communicational framework that parallelized communication services to implement Shamir secret sharing schemes, and GMW multiplications. Hoghly optimized for the 3 players case.
 *
 *Our security model protects data against non-adaptive honest-but-curious adversaries, and we assume secure transmission channels.
 * To start the main class contains an example on how it can be used.
 */

//Main Example
int main(int argc, const char ** argv)
{
    cout << "******************** Bellman Ford in C++ ********************"<<"\n";
    cout<<"#############################################################"<<endl;
	cout<<"#                    _                                      #"<<endl;
	cout<<"#                  -=\\`\\                                    #"<<endl;
	cout<<"#              |\\ ____\\_\\__                                 #"<<endl;
	cout<<"#            -=\\c`\"\"\"\"\"\"\" \"`)                               #"<<endl;
	cout<<"#               `~~~~~/ /~~`\                                #"<<endl;
	cout<<"#                 -==/ /                                    #"<<endl;
	cout<<"#                   '-'                                     #"<<endl;
	cout<<"#                  _  _                                     #"<<endl;
	cout<<"#                 ( `   )_                                  #"<<endl;
	cout<<"#                (    )    `)                               #"<<endl;
	cout<<"#              (_   (_ .  _) _)                             #"<<endl;
	cout<<"#                                             _             #"<<endl;
	cout<<"#                                            (  )           #"<<endl;
	cout<<"#             _ .                         ( `  ) . )        #"<<endl;
	cout<<"#           (  _ )_                      (_, _(  ,_)_)      #"<<endl;
	cout<<"#         (_  _(_ ,)                                        #"<<endl;
	cout<<"#############################################################"<<endl;
    cout << "brought you by: CORE -->{*.-}"<<"\n";
    cout << "Welcome to the GIT World Arithmetic Modulus!! Comp with 2 Local" <<"\n";

    Utils::List<Players::StandardPlayer> *list = new Utils::List<Players::StandardPlayer>(3);

    int player;
    int secret;
    if (argc==1) {

         player = atoi("3");
         secret = atoi("5");
    }else {

        player = atoi(argv[1]);
        secret = atoi(argv[2]);
    }
    int localHome[]= {127,0,0,1};
    int localAddress[]= {130,104,94,42};
    int externalAddress[]={130,104,98,0}; //{192,168,1,5};//{130,104,59,120};//{130,104,59,120};
    //int localAddress[]= {127,0,0,1};
    cout<< "The current player is: "<< player << " and his secret is: "<< secret<<"\n";

    Players::StandardPlayer * p1=new Players::StandardPlayer(1,3001,externalAddress);
    Players::StandardPlayer * p2=new Players::StandardPlayer(2,3003,externalAddress);

    Players::StandardPlayer * p3=new Players::StandardPlayer(3,3002,localAddress);

    list->add( p1);
    list->add( p2);
    list->add( p3);
    Pools::SocketPool::configureByDefault(list->get(player-1));
    cout<< "the exit port is:" << list->get(player-1)->getPort()<<"\n";
    //Experimentation with Multithreading TODO: Migrate operation counter
    //Applications::Permutations::PermutationMatrix::multiThreading(list, player);
    SmcEngines::ShamirSharesEngine *engine = new SmcEngines::ShamirSharesEngine(list->get(player-1),list,true);
    Utils::List<Shares::StandardShare> *shares;

    //getchar();
    //first value sharing
    shares=engine->shareValue(secret);

    //Algorithm variable declaration
    Shares::StandardShare * prod=NULL;

    //markets
   /* Utils::List<Shares::StandardShare> * markets = new  Utils::List<Shares::StandardShare>(4);
    markets->add(engine->buildShare(20));
    markets->add(engine->buildShare(22));
     markets->add(engine->buildShare(24));
     markets->add(engine->buildShare(26));

    //bids
    int totalBids=1949;
    Utils::List<Bids::ReducedBid> *rbids;
    Utils::List<Bids::StandardBid> * bids; //= new     Utils::List<Bids::StandardBid>();
    char* filename;
    asprintf(&filename, "%s%i%s", "bids-", player,".txt");
    bids =Applications::Auctions::Utilities::LocationalAuctionUtil::readBids(filename, player, totalBids);
    //bids->add(new Bids::StandardBid(engine->buildShare(0), markets->get(1)->clone(), engine->buildShare(50), engine->buildShare(10)));
    //bids->add(new Bids::StandardBid(engine->buildShare(1), markets->get(0)->clone(), engine->buildShare(30), engine->buildShare(10)));
    //bids->add(new Bids::StandardBid(engine->buildShare(2), markets->get(0)->clone(), engine->buildShare(20), engine->buildShare(15)));

    //max flow network
    int graphSize=6;
        asprintf(&filename, "%s%i%s", "network-", player,".txt");
    Utils::Matrix<Shares::StandardShare> * g; //= new  Utils::Matrix<Shares::StandardShare>(4,4);
    g=Applications::Auctions::Utilities::LocationalAuctionUtil::readNetwork(filename, player,graphSize);
    for (int i=0; i<graphSize; i++)
    {
        for (int j=0; j<graphSize; j++)
        {
            if (g->get(i, j)->getValue()==-1)
            {
                Shares::StandardShare *aux = g->get(i, j);
                g->set(i,j, NULL);
                delete aux;
            }

        }
    }

    //delete g->get(0,1);
    //g->set(0,1,NULL);
    //g->set(0,1,engine->buildShare(10));
    //g->set(1,0,engine->buildShare(0));

    //delete g->get(0,2);
    //g->set(0,2,NULL);
    //g->set(0,2,engine->buildShare(15));
    //g->set(2,0,engine->buildShare(0));

    //delete g->get(1,2);
    //g->set(1,2,NULL);
    //g->set(1,2,shares->get(2));
    //g->set(2,1,engine->buildShare(0));

    //delete g->get(1,3);
    //g->set(1,3,NULL);
    //g->set(1,3,shares->get(0));
    //g->set(3,1,engine->buildShare(0));

    //delete g->get(2,3);
    //g->set(2,3,NULL);
    //g->set(2,3,shares->get(1));
    //g->set(3,2,engine->buildShare(0));

    //Applications::MaxFlow::PushRelabel * pushRelabel = new Applications::MaxFlow::PushRelabel(g,4,engine);
   // LocationalAuction * auction = new LocationalAuction(bids, g, markets, engine);
   // Utils::List<Shares::StandardShare> * bits = new Utils::List<Shares::StandardShare>(32);
   // for (int i=0; i<32; i++)
   // {
   //     bits->add(engine->buildShare(0));
   // }
    */
    for (int j=0; j<10; j++)
    {
        //time measurement initialization

       // Shares::StandardShare * aux = engine->buildShare(0);
       // Shares::StandardShare * aux_m = engine->buildShare(0);
        //algorithm process

        //cout<<"Comparitions: \n"<<engine->totalCom<<"\n";
      //        double tInitial=  mach_absolute_time();

//        for (int i=4; i<=256; i=i*2)
        for (int i=1; i<=10; i++)
        {

            prod= engine->multiply(shares->get(0), shares->get(1));
            if(i<10)
            {
                delete prod;
            }
        /*
            delete prod;
            prod= engine->lessEqualThanCatrinaModShares(shares->get(1), shares->get(2));
            cout<<"result: "<< engine->presentShare(prod) <<"\n";
            Response::AuctionResponse * auctionResponse= auction->optimizeAuction();
            rbids = auctionResponse->getBids();
            prod = engine->buildShare(0);
            cout<<"Start Share Presentation: \n";
            for(int k=0; k< rbids->getLength();k++)
            {
                long used =engine->presentShare(rbids->get(k)->getQuantity());
                cout<<"op: "<< engine->presentShare(rbids->get(k)->getId()) <<" Usage: "<< used  <<" Price: "<< engine->presentShare(rbids->get(k)->getPrice()) <<"\n";
                if(used!=0)
                {
            //::Utilities::ShareUtil::destroyList(engine->obtainMostSignificativeBit(bits));
            //prod =engine->bitwiseLessThanEqualSecureScalar(bits,0);

            //prod= engine->lessEqualThanCatrinaModShares(aux, aux_m);
                   prod = engine->addTo(prod,engine->multiply(rbids->get(k)->getPrice(),used));
                }
            }
            //Utils::Matrix<Shares::StandardShare> *flow = pushRelabel->obtainMaxFlowStopCondition(0, 3);
            //prod = engine->add(flow->get(0, 1), flow->get(0,2));
          */

          //  double tInitial=  mach_absolute_time();
          /*  Utils::List<Utils::List<Shares::StandardShare> > * bellGraph = new Utils::List<Utils::List<Shares::StandardShare> > (i);
            for (int k=0 ; k<i; k++) {
                bellGraph->add(new Utils::List<Shares::StandardShare>(i));
                for (int z=0; z<i; z++) {
                    bellGraph->get(k)->set(z, engine->buildShare(0));
                }
            }

            Utils::List<Shares::StandardShare>* response    =       Applications::ShortestPath::BellmanFord::obtainSecureShortestPath(engine, bellGraph);
           */
            }
	//      double tFinal =mach_absolute_time();

	/* static double timeConvert = 0.0;
            if ( timeConvert == 0.0 )
            {
                mach_timebase_info_data_t timeBase;
                (void)mach_timebase_info( &timeBase );
                timeConvert = (double)timeBase.numer /
                (double)timeBase.denom /
                1000000000.0;
		}*/

	//cout <<(tFinal-tInitial)*timeConvert <<"\n";
	//  cout <<engine->getTime() * timeConvert <<"\n";

            //cout<<"Comparitions: \n"<<engine->totalCom<<"\n";
            cout <<Buffers::EngineBuffers::operationCounter_<<"\n";

           // ::Utilities::ShareUtil::destroyList(response);

           // for (int k=0 ; k<i; k++)
           //{
           //     ::Utilities::ShareUtil::destroyList(bellGraph->get(k));
           // }
           // delete bellGraph;
        }

        //time measurement process
        //gettimeofday(&tFinal, NULL);
        //int tmElp=(tFinal.tv_sec - tInitial.tv_sec) * 1000.0;
        //tmElp += (tFinal.tv_usec - tInitial.tv_usec) / 1000.0;
        //cout<<"total time elapsed: " <<tmElp <<"\n";

    //Process to Open Shares
    Utils::List<Shares::StandardShare> * localOpenShares= new  Utils::List<Shares::StandardShare>(1);
    Utils::List<Utils::List<Shares::StandardShare> >* openShares=NULL;
    vector<long> response;
    localOpenShares->add(prod);//*(totalRan)
    //cout<<"values: "<<greatThanToft->getValue()<<" "<<greatThanToft->getOperationId()<<" "<<greatThanToft->getPlayerId()<<"\n";
    for (int i=0; i<1; i++) {
        openShares=engine->syncGlobal(localOpenShares);
        response = engine->reconstructShares(localOpenShares);//*(ranBin)
        response = engine->reconstructShares(localOpenShares);
    }

    //printing information process
    //cout<< "total transmission operations performed: "<< Buffers::EngineBuffers::operationCounter_<<"\n";
    for (int i=0; i<openShares->get(0)->getLength(); i++)
    {
        cout<< "The Open Share from player: "<< i+1<<" is: "<<  openShares->get(0)->get(i)->getValue()  << "\n";

    };
    //single response line:
    cout<<"Response: on Multiplication: "<<engine->presentShare(prod)<<"\n";

    return 1;

};

max_stars_repo_name: abdelrahamanaly/mpcToolkit

max_issues_repo_name: abdelrahamanaly/mpcToolkit

max_forks_repo_name: abdelrahamanaly/mpcToolkit


text:
#include <boost/test/unit_test.hpp>
#include <bcio/chain/resource_limits.hpp>
#include <bcio/chain/config.hpp>
#include <bcio/testing/chainbase_fixture.hpp>

#include <algorithm>

using namespace bcio::chain::resource_limits;
using namespace bcio::testing;
using namespace bcio::chain;

class resource_limits_fixture: private chainbase_fixture<512*1024>, public resource_limits_manager
{
   public:
      resource_limits_fixture()
      :chainbase_fixture()
      ,resource_limits_manager(*chainbase_fixture::_db)
      {
         add_indices();
         initialize_database();
      }

      ~resource_limits_fixture() {}

      chainbase::database::session start_session() {
         return chainbase_fixture::_db->start_undo_session(true);
      }
};

constexpr uint64_t expected_elastic_iterations(uint64_t from, uint64_t to, uint64_t rate_num, uint64_t rate_den ) {
   uint64_t result = 0;
   uint64_t cur = from;

   while((from < to && cur < to) || (from > to && cur > to)) {
      cur = cur * rate_num / rate_den;
      result += 1;
   }

   return result;
}

constexpr uint64_t expected_exponential_average_iterations( uint64_t from, uint64_t to, uint64_t value, uint64_t window_size ) {
   uint64_t result = 0;
   uint64_t cur = from;

   while((from < to && cur < to) || (from > to && cur > to)) {
      cur = cur * (uint64_t)(window_size - 1) / (uint64_t)(window_size);
      cur += value / (uint64_t)(window_size);
      result += 1;
   }

   return result;
}

BOOST_AUTO_TEST_SUITE(resource_limits_test)

   /**
    * Test to make sure that the elastic limits for blocks relax and contract as expected
    */
   BOOST_FIXTURE_TEST_CASE(elastic_cpu_relax_contract, resource_limits_fixture) try {
      const uint64_t desired_virtual_limit = config::default_max_block_cpu_usage * 1000ULL;
      const uint64_t expected_relax_iterations = expected_elastic_iterations( config::default_max_block_cpu_usage, desired_virtual_limit, 1000, 999 );

      // this is enough iterations for the average to reach/exceed the target (triggering congestion handling) and then the iterations to contract down to the min
      // subtracting 1 for the iteration that pulls double duty as reaching/exceeding the target and starting congestion handling
      const uint64_t expected_contract_iterations =
              expected_exponential_average_iterations(0, BC_PERCENT(config::default_max_block_cpu_usage, config::default_target_block_cpu_usage_pct), config::default_max_block_cpu_usage, config::block_cpu_usage_average_window_ms / config::block_interval_ms ) +
              expected_elastic_iterations( desired_virtual_limit, config::default_max_block_cpu_usage, 99, 100 ) - 1;

      const account_name account(1);
      initialize_account(account);
      set_account_limits(account, -1, -1, -1);
      process_account_limit_updates();

      // relax from the starting state (congested) to the idle state as fast as possible
      uint32_t iterations = 0;
      while( get_virtual_block_cpu_limit() < desired_virtual_limit && iterations <= expected_relax_iterations ) {
         add_transaction_usage({account},0,0,iterations);
         process_block_usage(iterations++);
      }

      BOOST_REQUIRE_EQUAL(iterations, expected_relax_iterations);
      BOOST_REQUIRE_EQUAL(get_virtual_block_cpu_limit(), desired_virtual_limit);

      // push maximum resources to go from idle back to congested as fast as possible
      while( get_virtual_block_cpu_limit() > config::default_max_block_cpu_usage
              && iterations <= expected_relax_iterations + expected_contract_iterations ) {
         add_transaction_usage({account}, config::default_max_block_cpu_usage, 0, iterations);
         process_block_usage(iterations++);
      }

      BOOST_REQUIRE_EQUAL(iterations, expected_relax_iterations + expected_contract_iterations);
      BOOST_REQUIRE_EQUAL(get_virtual_block_cpu_limit(), config::default_max_block_cpu_usage);
   } FC_LOG_AND_RETHROW();

   /**
    * Test to make sure that the elastic limits for blocks relax and contract as expected
    */
   BOOST_FIXTURE_TEST_CASE(elastic_net_relax_contract, resource_limits_fixture) try {
      const uint64_t desired_virtual_limit = config::default_max_block_net_usage * 1000ULL;
      const uint64_t expected_relax_iterations = expected_elastic_iterations( config::default_max_block_net_usage, desired_virtual_limit, 1000, 999 );

      // this is enough iterations for the average to reach/exceed the target (triggering congestion handling) and then the iterations to contract down to the min
      // subtracting 1 for the iteration that pulls double duty as reaching/exceeding the target and starting congestion handling
      const uint64_t expected_contract_iterations =
              expected_exponential_average_iterations(0, BC_PERCENT(config::default_max_block_net_usage, config::default_target_block_net_usage_pct), config::default_max_block_net_usage, config::block_size_average_window_ms / config::block_interval_ms ) +
              expected_elastic_iterations( desired_virtual_limit, config::default_max_block_net_usage, 99, 100 ) - 1;

      const account_name account(1);
      initialize_account(account);
      set_account_limits(account, -1, -1, -1);
      process_account_limit_updates();

      // relax from the starting state (congested) to the idle state as fast as possible
      uint32_t iterations = 0;
      while( get_virtual_block_net_limit() < desired_virtual_limit && iterations <= expected_relax_iterations ) {
         add_transaction_usage({account},0,0,iterations);
         process_block_usage(iterations++);
      }

      BOOST_REQUIRE_EQUAL(iterations, expected_relax_iterations);
      BOOST_REQUIRE_EQUAL(get_virtual_block_net_limit(), desired_virtual_limit);

      // push maximum resources to go from idle back to congested as fast as possible
      while( get_virtual_block_net_limit() > config::default_max_block_net_usage
              && iterations <= expected_relax_iterations + expected_contract_iterations ) {
         add_transaction_usage({account},0, config::default_max_block_net_usage, iterations);
         process_block_usage(iterations++);
      }

      BOOST_REQUIRE_EQUAL(iterations, expected_relax_iterations + expected_contract_iterations);
      BOOST_REQUIRE_EQUAL(get_virtual_block_net_limit(), config::default_max_block_net_usage);
   } FC_LOG_AND_RETHROW();

   /**
    * create 5 accounts with different weights, verify that the capacities are as expected and that usage properly enforces them
    */

// TODO: restore weighted capacity cpu tests
#if 0
   BOOST_FIXTURE_TEST_CASE(weighted_capacity_cpu, resource_limits_fixture) try {
      const vector<int64_t> weights = { 234, 511, 672, 800, 1213 };
      const int64_t total = std::accumulate(std::begin(weights), std::end(weights), 0LL);
      vector<int64_t> expected_limits;
      std::transform(std::begin(weights), std::end(weights), std::back_inserter(expected_limits), [total](const auto& v){ return v * config::default_max_block_cpu_usage / total; });

      for (int64_t idx = 0; idx < weights.size(); idx++) {
         const account_name account(idx + 100);
         initialize_account(account);
         set_account_limits(account, -1, -1, weights.at(idx));
      }

      process_account_limit_updates();

      for (int64_t idx = 0; idx < weights.size(); idx++) {
         const account_name account(idx + 100);
         BOOST_CHECK_EQUAL(get_account_cpu_limit(account), expected_limits.at(idx));

         {  // use the expected limit, should succeed ... roll it back
            auto s = start_session();
            add_transaction_usage({account}, expected_limits.at(idx), 0, 0);
            s.undo();
         }

         // use too much, and expect failure;
         BOOST_REQUIRE_THROW(add_transaction_usage({account}, expected_limits.at(idx) + 1, 0, 0), tx_cpu_usage_exceeded);
      }
   } FC_LOG_AND_RETHROW();

   /**
    * create 5 accounts with different weights, verify that the capacities are as expected and that usage properly enforces them
    */
   BOOST_FIXTURE_TEST_CASE(weighted_capacity_net, resource_limits_fixture) try {
      const vector<int64_t> weights = { 234, 511, 672, 800, 1213 };
      const int64_t total = std::accumulate(std::begin(weights), std::end(weights), 0LL);
      vector<int64_t> expected_limits;
      std::transform(std::begin(weights), std::end(weights), std::back_inserter(expected_limits), [total](const auto& v){ return v * config::default_max_block_net_usage / total; });

      for (int64_t idx = 0; idx < weights.size(); idx++) {
         const account_name account(idx + 100);
         initialize_account(account);
         set_account_limits(account, -1, weights.at(idx), -1 );
      }

      process_account_limit_updates();

      for (int64_t idx = 0; idx < weights.size(); idx++) {
         const account_name account(idx + 100);
         BOOST_CHECK_EQUAL(get_account_net_limit(account), expected_limits.at(idx));

         {  // use the expected limit, should succeed ... roll it back
            auto s = start_session();
            add_transaction_usage({account}, 0, expected_limits.at(idx), 0);
            s.undo();
         }

         // use too much, and expect failure;
         BOOST_REQUIRE_THROW(add_transaction_usage({account}, 0, expected_limits.at(idx) + 1, 0), tx_net_usage_exceeded);
      }
   } FC_LOG_AND_RETHROW();
#endif

   BOOST_FIXTURE_TEST_CASE(enforce_block_limits_cpu, resource_limits_fixture) try {
      const account_name account(1);
      initialize_account(account);
      set_account_limits(account, -1, -1, -1 );
      process_account_limit_updates();

      const uint64_t increment = 1000;
      const uint64_t expected_iterations = config::default_max_block_cpu_usage / increment;

      for (int idx = 0; idx < expected_iterations; idx++) {
         add_transaction_usage({account}, increment, 0, 0);
      }

      BOOST_REQUIRE_THROW(add_transaction_usage({account}, increment, 0, 0), block_resource_exhausted);

   } FC_LOG_AND_RETHROW();

   BOOST_FIXTURE_TEST_CASE(enforce_block_limits_net, resource_limits_fixture) try {
      const account_name account(1);
      initialize_account(account);
      set_account_limits(account, -1, -1, -1 );
      process_account_limit_updates();

      const uint64_t increment = 1000;
      const uint64_t expected_iterations = config::default_max_block_net_usage / increment;

      for (int idx = 0; idx < expected_iterations; idx++) {
         add_transaction_usage({account}, 0, increment, 0);
      }

      BOOST_REQUIRE_THROW(add_transaction_usage({account}, 0, increment, 0), block_resource_exhausted);

   } FC_LOG_AND_RETHROW();

   BOOST_FIXTURE_TEST_CASE(enforce_account_ram_limit, resource_limits_fixture) try {
      const uint64_t limit = 1000;
      const uint64_t increment = 77;
      const uint64_t expected_iterations = (limit + increment - 1 ) / increment;

      const account_name account(1);
      initialize_account(account);
      set_account_limits(account, limit, -1, -1 );
      process_account_limit_updates();

      for (int idx = 0; idx < expected_iterations - 1; idx++) {
         add_pending_ram_usage(account, increment);
         verify_account_ram_usage(account);
      }

      add_pending_ram_usage(account, increment);
      BOOST_REQUIRE_THROW(verify_account_ram_usage(account), ram_usage_exceeded);
   } FC_LOG_AND_RETHROW();

   BOOST_FIXTURE_TEST_CASE(enforce_account_ram_limit_underflow, resource_limits_fixture) try {
      const account_name account(1);
      initialize_account(account);
      set_account_limits(account, 100, -1, -1 );
      verify_account_ram_usage(account);
      process_account_limit_updates();
      BOOST_REQUIRE_THROW(add_pending_ram_usage(account, -101), transaction_exception);

   } FC_LOG_AND_RETHROW();

   BOOST_FIXTURE_TEST_CASE(enforce_account_ram_limit_overflow, resource_limits_fixture) try {
      const account_name account(1);
      initialize_account(account);
      set_account_limits(account, UINT64_MAX, -1, -1 );
      verify_account_ram_usage(account);
      process_account_limit_updates();
      add_pending_ram_usage(account, UINT64_MAX/2);
      verify_account_ram_usage(account);
      add_pending_ram_usage(account, UINT64_MAX/2);
      verify_account_ram_usage(account);
      BOOST_REQUIRE_THROW(add_pending_ram_usage(account, 2), transaction_exception);

   } FC_LOG_AND_RETHROW();

   BOOST_FIXTURE_TEST_CASE(enforce_account_ram_commitment, resource_limits_fixture) try {
      const int64_t limit = 1000;
      const int64_t commit = 600;
      const int64_t increment = 77;
      const int64_t expected_iterations = (limit - commit + increment - 1 ) / increment;

      const account_name account(1);
      initialize_account(account);
      set_account_limits(account, limit, -1, -1 );
      process_account_limit_updates();
      add_pending_ram_usage(account, commit);
      verify_account_ram_usage(account);

      for (int idx = 0; idx < expected_iterations - 1; idx++) {
         set_account_limits(account, limit - increment * idx, -1, -1);
         verify_account_ram_usage(account);
         process_account_limit_updates();
      }

      set_account_limits(account, limit - increment * expected_iterations, -1, -1);
      BOOST_REQUIRE_THROW(verify_account_ram_usage(account), ram_usage_exceeded);
   } FC_LOG_AND_RETHROW();

   BOOST_FIXTURE_TEST_CASE(sanity_check, resource_limits_fixture) try {
      double total_staked_tokens = 1'000'000'000'0000.;
      double user_stake = 1'0000.;
      double max_block_cpu = 100000.; // us;
      double blocks_per_day = 2*60*60*23;
      double total_cpu_per_period = max_block_cpu * blocks_per_day * 3;

      double congested_cpu_time_per_period = total_cpu_per_period * user_stake / total_staked_tokens;
      wdump((congested_cpu_time_per_period));
      double uncongested_cpu_time_per_period = (1000*total_cpu_per_period) * user_stake / total_staked_tokens;
      wdump((uncongested_cpu_time_per_period));

      initialize_account( N(dan) );
      initialize_account( N(everyone) );
      set_account_limits( N(dan), 0, 0, 10000 );
      set_account_limits( N(everyone), 0, 0, 10000000000000ll );
      process_account_limit_updates();

      add_transaction_usage( {N(dan)}, 10, 0, 1 ); /// dan should be able to do 10 us per 3 days

   } FC_LOG_AND_RETHROW()

BOOST_AUTO_TEST_SUITE_END()


text:
// Copyright 2016-2019 Doug Moen
// Licensed under the Apache License, version 2.0
// See accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0

#include <cctype>
#include <iostream>
#include <typeinfo>
#include <boost/core/demangle.hpp>
#include <libcurv/context.h>
#include <libcurv/die.h>
#include <libcurv/dtostr.h>
#include <libcurv/exception.h>
#include <libcurv/function.h>
#include <libcurv/sc_compiler.h>
#include <libcurv/sc_context.h>
#include <libcurv/math.h>
#include <libcurv/meaning.h>
#include <libcurv/optimizer.h>
#include <libcurv/picker.h>
#include <libcurv/reactive.h>
#include <libcurv/system.h>

namespace curv {

struct SC_Data_Ref : public Operation
{
    SC_Value val_;
    SC_Data_Ref(Shared<const Phrase> src, SC_Value v)
    : Operation(std::move(src)), val_(v)
    {}
    SC_Value sc_eval(SC_Frame&) const override { return val_; }
    void exec(Frame&, Executor&) const override { }
};

// This is the main entry point into the Shape Compiler.
void
SC_Compiler::define_function(
    const char* name, SC_Type param_type, SC_Type result_type,
    Shared<const Function> func, const Context& cx)
{
    begin_function();
    SC_Value param = newvalue(param_type);
    if (target_ == SC_Target::cpp) {
        out_
            << "extern \"C\" void " << name
            << "(const " << param_type << "* param, "
            << result_type << "* result)\n"
            "{\n"
            "  " << param_type << " " << param << " = *param;\n";
    } else {
        out_ <<
        result_type << " " << name << "(" << param_type << " " << param << ")\n"
        "{\n";
    }
    auto f = SC_Frame::make(0, *this, &cx, nullptr, nullptr);
    auto param_ref = make<SC_Data_Ref>(nullptr, param);
    auto result = func->sc_call_expr(*param_ref, nullptr, *f);
    if (result.type != result_type) {
        throw Exception(cx, stringify(name," function returns ",result.type));
    }
    end_function();
    if (target_ == SC_Target::cpp) {
        out_ << "  *result = " << result << ";\n";
    } else {
        out_ << "  return " << result << ";\n";
    }
    out_ << "}\n";
}

void
SC_Compiler::begin_function()
{
    valcount_ = 0;
    valcache_.clear();
    opcaches_.clear();
    opcaches_.emplace_back(Op_Cache{});
    constants_.str("");
    body_.str("");
}

void
SC_Compiler::end_function()
{
    out_ << "  /* constants */\n";
    out_ << constants_.str();
    out_ << "  /* body */\n";
    out_ << body_.str();
}

SC_Value sc_call_unary_numeric(SC_Frame& f, const char* name)
{
    auto arg = f[0];
    if (!arg.type.is_numeric())
        throw Exception(At_SC_Arg(0, f),
            stringify(name,": argument is not numeric"));
    auto result = f.sc_.newvalue(arg.type);
    f.sc_.out()<<"  "<<arg.type<<" "<<result<<" = "<<name<<"("<<arg<<");\n";
    return result;
}

struct Set_Purity
{
    SC_Compiler& sc_;
    bool previous_purity_;
    Set_Purity(SC_Compiler& sc, bool purity)
    :
        sc_(sc),
        previous_purity_(sc.in_constants_)
    {
        sc_.in_constants_ = purity;
    }
    ~Set_Purity()
    {
        sc_.in_constants_ = previous_purity_;
    }
};

// Wrapper for Operation::sc_eval(f), does common subexpression elimination.
SC_Value sc_eval_op(SC_Frame& f, const Operation& op)
{
#if OPTIMIZE
    if (!op.pure_) {
      #if 0
        bool previous = f.sc_.in_constants_;
        f.sc_.in_constants_ = false;
        auto k = f.sc_.valcount_;
        f.sc_.out()
            <<"/*in "<<k<<" IMPR "
            <<boost::core::demangle(typeid(op).name())<<"*/\n";
        SC_Value val;
        try {
            val = op.sc_eval(f);
        } catch (...) {
            f.sc_.out()
                <<"/*except "<<k<<"/"<<f.sc_.valcount_<<" IMPR "
                <<boost::core::demangle(typeid(op).name())<<"*/\n";
            f.sc_.in_constants_ = previous;
            throw;
        }
        f.sc_.out()
            <<"/*out "<<k<<"/"<<f.sc_.valcount_<<" IMPR "
            <<boost::core::demangle(typeid(op).name())<<"*/\n";
        f.sc_.in_constants_ = previous;
        return val;
      #else
        Set_Purity pu(f.sc_, false);
        return op.sc_eval(f);
      #endif
    }
    // 'op' is a uniform expression, consisting of pure operations at interior
    // nodes and Constants at leaf nodes. There can be no variable references
    // (eg, no Data_Ref ops), other than uniform variables in reactive values.
    // What follows is a limited form of common subexpression elimination
    // which reduces code size when reactive values are used.
    for (Op_Cache& opcache : f.sc_.opcaches_) {
        auto cached = opcache.find(share(op));
        if (cached != opcache.end())
            return cached->second;
    }
  #if 0
    bool previous = f.sc_.in_constants_;
    f.sc_.in_constants_ = true;
    auto k = f.sc_.valcount_;
    f.sc_.out()
        <<"/*in "<<k<<" PURE "
        <<boost::core::demangle(typeid(op).name())<<"*/\n";
    SC_Value val;
    try {
        val = op.sc_eval(f);
    } catch (...) {
        f.sc_.out()
            <<"/*except "<<k<<"/"<<f.sc_.valcount_<<" PURE "
            <<boost::core::demangle(typeid(op).name())<<"*/\n";
        f.sc_.in_constants_ = previous;
        throw;
    }
    f.sc_.out()
        <<"/*out "<<k<<"/"<<f.sc_.valcount_<<" PURE "
        <<boost::core::demangle(typeid(op).name())<<"*/\n";
    f.sc_.in_constants_ = previous;
    f.sc_.opcache_[share(op)] = val;
    return val;
  #else
    Set_Purity pu(f.sc_, true);
    auto val = op.sc_eval(f);
    f.sc_.opcaches_.back()[share(op)] = val;
    return val;
  #endif
#else
    return op.sc_eval(f);
#endif
}

SC_Value sc_eval_expr(SC_Frame& f, const Operation& op, SC_Type type)
{
    SC_Value arg = sc_eval_op(f, op);
    if (arg.type != type) {
        throw Exception(At_SC_Phrase(op.syntax_, f),
            stringify("wrong argument type: expected ",type,", got ",arg.type));
    }
    return arg;
}

#if 0
bool
get_mat(List& list, int i, int j, double& elem)
{
    if (auto row = list[i].dycast<List>()) {
        if (row->size() == list.size()) {
            Value e = row->at(j);
            if (e.is_num()) {
                elem = e.get_num_unsafe();
                return true;
            }
        }
    }
    return false;
}
#endif

void
sc_put_num(Value val, const Context& cx, std::ostream& out)
{
    out << dfmt(val.to_num(cx), dfmt::EXPR);
}

void
sc_put_vec(unsigned size, Value val, const Context& cx, std::ostream& out)
{
    auto list = val.to<List>(cx);
    list->assert_size(size, cx);
    out << SC_Type::Vec(size) << "(";
    bool first = true;
    for (unsigned i = 0; i < size; ++i) {
        if (!first) out << ",";
        first = false;
        sc_put_num(list->at(i), cx, out);
    }
    out << ")";
}

SC_Value sc_eval_const(SC_Frame& f, Value val, const Phrase& syntax)
{
#if OPTIMIZE
    auto cached = f.sc_.valcache_.find(val);
    if (cached != f.sc_.valcache_.end())
        return cached->second;
#endif

    Set_Purity pu(f.sc_, true);
    At_SC_Phrase cx(share(syntax), f);
    if (val.is_num()) {
        SC_Value result = f.sc_.newvalue(SC_Type::Num());
        double num = val.get_num_unsafe();
        f.sc_.out() << "  const float " << result << " = "
            << dfmt(num, dfmt::EXPR) << ";\n";
        f.sc_.valcache_[val] = result;
        return result;
    }
    if (val.is_bool()) {
        SC_Value result = f.sc_.newvalue(SC_Type::Bool());
        bool b = val.get_bool_unsafe();
        f.sc_.out() << "  const bool " << result << " = "
            << (b ? "true" : "false") << ";\n";
        f.sc_.valcache_[val] = result;
        return result;
    }
    if (auto list = val.dycast<List>()) {
        if (list->size() == 0 || list->size() > SC_Type::MAX_LIST) {
            throw Exception(cx, stringify(
                "list of size ",list->size(), " is not supported"));
        }
        if (isnum(list->front())) {
            // It is a list of numbers. Size 2..4 is a vector.
            if (list->size() >= 2 && list->size() <= 4) {
                // vector
                SC_Value values[4];
                for (unsigned i = 0; i < list->size(); ++i) {
                    values[i] = sc_eval_const(f, list->at(i), syntax);
                    if (values[i].type != SC_Type::Num())
                        goto error;
                }
                static SC_Type types[5] = {
                    {}, {}, SC_Type::Vec(2), SC_Type::Vec(3), SC_Type::Vec(4)
                };
                SC_Value result = f.sc_.newvalue(types[list->size()]);
                f.sc_.out() << "  " << result.type << " " << result
                    << " = " << result.type << "(";
                bool first = true;
                for (unsigned i = 0; i < list->size(); ++i) {
                    if (!first) f.sc_.out() << ",";
                    first = false;
                    f.sc_.out() << values[i];
                }
                f.sc_.out() << ");\n";
                f.sc_.valcache_[val] = result;
                return result;
            }
            // It is a float array.
            SC_Value result = f.sc_.newvalue(SC_Type::Num(list->size()));
            if (f.sc_.target_ == SC_Target::cpp) {
                f.sc_.out() << "  static const float "<<result<<"[] = {";
            } else {
                f.sc_.out() << "  const " << result.type << " " << result
                    << " = " << result.type << "(";
            }
            bool first = true;
            for (unsigned i = 0; i < list->size(); ++i) {
                if (!first) f.sc_.out() << ",";
                first = false;
                f.sc_.out() << dfmt(list->at(i).to_num(cx), dfmt::EXPR);
            }
            if (f.sc_.target_ == SC_Target::cpp) {
                f.sc_.out() << "};\n";
            } else {
                f.sc_.out() << ");\n";
            }
            f.sc_.valcache_[val] = result;
            return result;
          #if 0
            else {
                // matrix
                static SC_Type types[5] = {
                    {}, {}, SC_Type::Mat(2), SC_Type::Mat(3), SC_Type::Mat(4)
                };
                SC_Value result = f.sc_.newvalue(types[list->size()]);
                f.sc_.out() << "  " << result.type << " " << result
                    << " = " << result.type << "(";
                bool first = true;
                for (size_t i = 0; i < list->size(); ++i) {
                    for (size_t j = 0; j < list->size(); ++j) {
                        double elem;
                        if (get_mat(*list, j, i, elem)) {
                            if (!first) f.sc_.out() << ",";
                            first = false;
                            f.sc_.out() << dfmt(elem, dfmt::EXPR);
                        } else
                            goto error;
                    }
                }
                f.sc_.out() << ");\n";
                return result;
            }
          #endif
        }
        if (auto list2 = list->front().dycast<List>()) {
            if (list2->size() == 0 || list2->size() > SC_Type::MAX_LIST) {
                throw Exception(cx, stringify(
                    "list of size ",list2->size()," is not supported"));
            }
            if (isnum(list2->front())) {
                // A list of lists of numbers...
                if (list2->size() >= 2 && list2->size() <= 4) {
                    // list of vectors
                    SC_Value result =
                        f.sc_.newvalue(
                            SC_Type::Vec(list2->size(), list->size()));
                    if (f.sc_.target_ == SC_Target::cpp) {
                        f.sc_.out()
                            << "  static const " << SC_Type::Vec(list2->size())
                            << " "<<result<<"[] = {";
                    } else {
                        f.sc_.out() << "  const " << result.type << " " << result
                            << " = " << result.type << "(";
                    }
                    bool first = true;
                    for (unsigned i = 0; i < list->size(); ++i) {
                        if (!first) f.sc_.out() << ",";
                        first = false;
                        sc_put_vec(list2->size(), list->at(i), cx, f.sc_.out());
                    }
                    if (f.sc_.target_ == SC_Target::cpp) {
                        f.sc_.out() << "};\n";
                    } else {
                        f.sc_.out() << ");\n";
                    }
                    f.sc_.valcache_[val] = result;
                    return result;
                }
                // 2D array of numbers
                SC_Value result =
                    f.sc_.newvalue(SC_Type::Num(list->size(), list2->size()));
                if (f.sc_.target_ == SC_Target::cpp) {
                    f.sc_.out() << "  static const float " <<result<<"[] = {";
                } else {
                    f.sc_.out() << "  const " << result.type << " " << result
                        << " = " << result.type << "(";
                }
                bool first = true;
                for (unsigned i = 0; i < list->size(); ++i) {
                    auto l2 = list->at(i).to<List>(cx);
                    if (l2->size() != list2->size())
                        goto error;
                    for (unsigned j = 0; j < l2->size(); ++j) {
                        if (!first) f.sc_.out() << ",";
                        first = false;
                        sc_put_num(l2->at(j), cx, f.sc_.out());
                    }
                }
                if (f.sc_.target_ == SC_Target::cpp) {
                    f.sc_.out() << "};\n";
                } else {
                    f.sc_.out() << ");\n";
                }
                f.sc_.valcache_[val] = result;
                return result;
            }
            if (auto list3 = list2->front().dycast<List>()) {
                // A list of lists of lists: interpret as 2D array of vectors
                if (list3->size() < 2 || list3->size() > 4) goto error;
                SC_Value result =
                    f.sc_.newvalue(SC_Type::Vec(list3->size(),
                        list->size(), list2->size()));
                if (f.sc_.target_ == SC_Target::cpp) {
                    f.sc_.out() << "  static const "
                        << SC_Type::Vec(list3->size())
                        << " " <<result<<"[] = {";
                } else {
                    f.sc_.out() << "  const " << result.type << " " << result
                        << " = " << result.type << "(";
                }
                bool first = true;
                for (unsigned i = 0; i < list->size(); ++i) {
                    auto l2 = list->at(i).to<List>(cx);
                    if (l2->size() != list2->size())
                        goto error;
                    for (unsigned j = 0; j < l2->size(); ++j) {
                        if (!first) f.sc_.out() << ",";
                        first = false;
                        sc_put_vec(list3->size(), l2->at(j), cx, f.sc_.out());
                    }
                }
                if (f.sc_.target_ == SC_Target::cpp) {
                    f.sc_.out() << "};\n";
                } else {
                    f.sc_.out() << ");\n";
                }
                f.sc_.valcache_[val] = result;
                return result;
            }
        }
        goto error;
    }
    if (auto re = val.dycast<Reactive_Expression>()) {
        auto f2 = SC_Frame::make(0, f.sc_, nullptr, &f, &syntax);
        auto result = sc_eval_op(*f2, *re->expr_);
        f.sc_.valcache_[val] = result;
        return result;
    }
    if (auto uv = val.dycast<Uniform_Variable>()) {
        SC_Value result = f.sc_.newvalue(uv->sctype_);
        f.sc_.out() << "  " << uv->sctype_
            << " " << result << " = " << uv->identifier_ << ";\n";
        f.sc_.valcache_[val] = result;
        return result;
    }
error:
    throw Exception(At_SC_Phrase(share(syntax), f),
        stringify("value ",val," is not supported "));
}

SC_Value Operation::sc_eval(SC_Frame& f) const
{
    throw Exception(At_SC_Phrase(syntax_, f), stringify(
        "this expression is not supported: ",
        boost::core::demangle(typeid(*this).name())));
}

void Operation::sc_exec(SC_Frame& f) const
{
    throw Exception(At_SC_Phrase(syntax_, f), stringify(
        "this action is not supported: ",
        boost::core::demangle(typeid(*this).name())));
}

SC_Value Constant::sc_eval(SC_Frame& f) const
{
    return sc_eval_const(f, value_, *syntax_);
}

SC_Value Negative_Expr::sc_eval(SC_Frame& f) const
{
    auto x = sc_eval_op(f, *arg_);
    if (!x.type.is_numeric())
        throw Exception(At_SC_Phrase(arg_->syntax_, f),
            "argument not numeric");
    SC_Value result = f.sc_.newvalue(x.type);
    f.sc_.out()<<"  "<<x.type<<" "<<result<<" = -"<<x<< ";\n";
    return result;
}

void sc_put_as(SC_Frame& f, SC_Value val, const Context& cx, SC_Type type)
{
    if (val.type == type) {
        f.sc_.out() << val;
        return;
    }
    if (val.type == SC_Type::Num()) {
        if (sc_type_count(type) > 1) {
            f.sc_.out() << type << "(";
            bool first = true;
            for (unsigned i = 0; i < sc_type_count(type); ++i) {
                if (!first) f.sc_.out() << ",";
                f.sc_.out() << val;
                first = false;
            }
            f.sc_.out() << ")";
            return;
        }
    }
    throw Exception(cx, stringify("can't convert ",val.type," to ",type));
}

SC_Value
sc_arith_expr(SC_Frame& f, const Phrase& syntax,
    const Operation& xexpr, const char* op, const Operation& yexpr)
{
    auto x = sc_eval_op(f, xexpr);
    auto y = sc_eval_op(f, yexpr);

    SC_Type rtype = SC_Type::Bool();
    if (x.type == y.type)
        rtype = x.type;
    else if (x.type == SC_Type::Num())
        rtype = y.type;
    else if (y.type == SC_Type::Num())
        rtype = x.type;
    if (rtype == SC_Type::Bool())
        throw Exception(At_SC_Phrase(share(syntax), f),
            stringify("domain error: ",x.type,op,y.type));

    SC_Value result = f.sc_.newvalue(rtype);
    f.sc_.out() <<"  "<<rtype<<" "<<result<<" = ";
    if (isalpha(*op)) {
        f.sc_.out() << op << "(";
        sc_put_as(f, x, At_SC_Phrase(xexpr.syntax_, f), rtype);
        f.sc_.out() << ",";
        sc_put_as(f, y, At_SC_Phrase(yexpr.syntax_, f), rtype);
        f.sc_.out() << ")";
    } else {
        sc_put_as(f, x, At_SC_Phrase(xexpr.syntax_, f), rtype);
        f.sc_.out() << op;
        sc_put_as(f, y, At_SC_Phrase(yexpr.syntax_, f), rtype);
    }
    f.sc_.out() << ";\n";
    return result;
}

SC_Value Add_Expr::sc_eval(SC_Frame& f) const
{
    return sc_arith_expr(f, *syntax_, *arg1_, "+", *arg2_);
}

SC_Value Subtract_Expr::sc_eval(SC_Frame& f) const
{
    return sc_arith_expr(f, *syntax_, *arg1_, "-", *arg2_);
}

SC_Value Multiply_Expr::sc_eval(SC_Frame& f) const
{
    return sc_arith_expr(f, *syntax_, *arg1_, "*", *arg2_);
}

SC_Value Divide_Expr::sc_eval(SC_Frame& f) const
{
    return sc_arith_expr(f, *syntax_, *arg1_, "/", *arg2_);
}

SC_Value Power_Expr::sc_eval(SC_Frame& f) const
{
    return sc_arith_expr(f, *syntax_, *arg1_, "pow", *arg2_);
}

// Evaluate an expression to a constant at SC compile time,
// or abort if it isn't a constant.
Value sc_constify(Operation& op, SC_Frame& f)
{
    if (auto c = dynamic_cast<Constant*>(&op))
        return c->value_;
    else if (auto dot = dynamic_cast<Dot_Expr*>(&op)) {
        Value base = sc_constify(*dot->base_, f);
        if (dot->selector_.id_ != nullptr)
            return base.at(dot->selector_.id_->symbol_,
                At_SC_Phrase(op.syntax_, f));
        else
            throw Exception(At_SC_Phrase(dot->selector_.string_->syntax_, f),
                "not an identifier");
    }
    else if (auto ref = dynamic_cast<Nonlocal_Data_Ref*>(&op))
        return f.nonlocals_->at(ref->slot_);
    else if (auto ref = dynamic_cast<Symbolic_Ref*>(&op)) {
        auto b = f.nonlocals_->dictionary_->find(ref->name_);
        assert(b != f.nonlocals_->dictionary_->end());
        return f.nonlocals_->get(b->second);
    }
    else if (auto list = dynamic_cast<List_Expr*>(&op)) {
        Shared<List> listval = List::make(list->size());
        for (size_t i = 0; i < list->size(); ++i) {
            (*listval)[i] = sc_constify(*(*list)[i], f);
        }
        return {listval};
    } else if (auto neg = dynamic_cast<Negative_Expr*>(&op)) {
        Value arg = sc_constify(*neg->arg_, f);
        if (arg.is_num())
            return Value(-arg.get_num_unsafe());
    }
    throw Exception(At_SC_Phrase(op.syntax_, f),
        "not a constant");
}

bool sc_try_constify(Operation& op, SC_Frame& f, Value& val)
{
    try {
        val = sc_constify(op, f);
        return true;
    } catch (Exception&) {
        return false;
    }
}

bool sc_try_eval(Operation& op, SC_Frame& f, SC_Value& val)
{
    try {
        val = sc_eval_op(f, op);
        return true;
    } catch (Exception&) {
        return false;
    }
}

SC_Value Block_Op::sc_eval(SC_Frame& f) const
{
    statements_.sc_exec(f);
    return sc_eval_op(f, *body_);
}
void Block_Op::sc_exec(SC_Frame& f) const
{
    statements_.sc_exec(f);
    body_->sc_exec(f);
}

SC_Value Preaction_Op::sc_eval(SC_Frame& f) const
{
    actions_->sc_exec(f);
    return sc_eval_op(f, *body_);
}
void Preaction_Op::sc_exec(SC_Frame& f) const
{
    actions_->sc_exec(f);
    body_->sc_exec(f);
}

void Compound_Op_Base::sc_exec(SC_Frame& f) const
{
    for (auto s : *this)
        s->sc_exec(f);
}

void Scope_Executable::sc_exec(SC_Frame& f) const
{
    for (auto action : actions_)
        action->sc_exec(f);
}
void Null_Action::sc_exec(SC_Frame&) const
{
}

void
Assignment_Action::sc_exec(SC_Frame& f) const
{
    SC_Value val = sc_eval_op(f, *expr_);
    f.sc_.out() << "  "<<f[slot_]<<"="<<val<<";\n";
}
void
Data_Setter::sc_exec(SC_Frame& f) const
{
    assert(module_slot_ == (slot_t)(-1));
    pattern_->sc_exec(*definiens_, f, f);
}

char gl_index_letter(Value k, unsigned vecsize, const Context& cx)
{
    auto num = k.get_num_or_nan();
    if (num == 0.0)
        return 'x';
    if (num == 1.0)
        return 'y';
    if (num == 2.0 && vecsize > 2)
        return 'z';
    if (num == 3.0 && vecsize > 3)
        return 'w';
    throw Exception(cx,
        stringify("got ",k,", expected 0..",vecsize-1));
}

// compile array[i] expression
SC_Value sc_eval_index_expr(SC_Value array, Operation& index, SC_Frame& f)
{
    Value k;
    if (array.type.is_vec() && sc_try_constify(index, f, k)) {
        // A vector with a constant index. Swizzling is supported.
        if (auto list = k.dycast<List>()) {
            if (list->size() < 2 || list->size() > 4) {
                throw Exception(At_SC_Phrase(index.syntax_, f),
                    "list index vector must have between 2 and 4 elements");
            }
            char swizzle[5];
            memset(swizzle, 0, 5);
            for (size_t i = 0; i <list->size(); ++i) {
                swizzle[i] = gl_index_letter((*list)[i],
                    array.type.count(),
                    At_Index(i, At_SC_Phrase(index.syntax_, f)));
            }
            SC_Value result = f.sc_.newvalue(SC_Type::Vec(list->size()));
            f.sc_.out() << "  " << result.type << " "<< result<<" = ";
            if (f.sc_.target_ == SC_Target::glsl) {
                // use GLSL swizzle syntax: v.xyz
                f.sc_.out() <<array<<"."<<swizzle;
            } else {
                // fall back to a vector constructor: vec3(v.x,v.y,v.z)
                f.sc_.out() << result.type << "(";
                bool first = true;
                for (size_t i = 0; i < list->size(); ++i) {
                    if (!first)
                        f.sc_.out() << ",";
                    first = false;
                    f.sc_.out() << array << "." << swizzle[i];
                }
                f.sc_.out() << ")";
            }
            f.sc_.out() <<";\n";
            return result;
        }
        const char* arg2 = nullptr;
        auto num = k.get_num_or_nan();
        if (num == 0.0)
            arg2 = ".x";
        else if (num == 1.0)
            arg2 = ".y";
        else if (num == 2.0 && array.type.count() > 2)
            arg2 = ".z";
        else if (num == 3.0 && array.type.count() > 3)
            arg2 = ".w";
        if (arg2 == nullptr)
            throw Exception(At_SC_Phrase(index.syntax_, f),
                stringify("got ",k,", expected 0..",
                    array.type.count()-1));

        SC_Value result = f.sc_.newvalue(SC_Type::Num());
        f.sc_.out() << "  float "<<result<<" = "<<array<<arg2<<";\n";
        return result;
    }
    // An array of numbers, indexed with a number.
    if (array.type.rank_ > 1) {
        throw Exception(At_SC_Phrase(index.syntax_,f), stringify(
            "can't index a ", array.type.rank_, "D array of ",
            SC_Type(array.type.base_type_), " with a single index"));
    }
    auto ix = sc_eval_expr(f, index, SC_Type::Num());
    SC_Value result = f.sc_.newvalue(array.type.abase());
    f.sc_.out() << "  " << result.type << " " << result << " = "
             << array << "[int(" << ix << ")];\n";
    return result;
}

// compile array[i,j] expression
SC_Value sc_eval_index2_expr(
    SC_Value array, Operation& op_ix1, Operation& op_ix2, SC_Frame& f,
    const Context& acx)
{
    auto ix1 = sc_eval_expr(f, op_ix1, SC_Type::Num());
    auto ix2 = sc_eval_expr(f, op_ix2, SC_Type::Num());
    if (array.type.rank_ == 2) {
        // 2D array of number or vector. Not supported by GLSL 1.5,
        // so we emulate this type using a 1D array.
        // Index value must be [i,j], can't use a single index.
        SC_Value result = f.sc_.newvalue({array.type.base_type_});
        f.sc_.out() << "  " << result.type << " " << result << " = " << array
                 << "[int(" << ix1 << ")*" << array.type.dim2_
                 << "+" << "int(" << ix2 << ")];\n";
        return result;
    }
    if (array.type.rank_ == 1 && array.type.base_info().rank == 1) {
        // 1D array of vector.
        SC_Value result = f.sc_.newvalue(SC_Type::Num());
        f.sc_.out() << "  " << result.type << " " << result << " = " << array
                 << "[int(" << ix1 << ")]"
                 << "[int(" << ix2 << ")];\n";
        return result;
    }
    throw Exception(acx, "2 indexes (a[i,j]) not supported for this array");
}

// compile array[i,j,k] expression
SC_Value sc_eval_index3_expr(
    SC_Value array, Operation& op_ix1, Operation& op_ix2, Operation& op_ix3,
    SC_Frame& f, const Context& acx)
{
    if (array.type.rank_ == 2 && array.type.base_info().rank == 1) {
        // 2D array of vector.
        auto ix1 = sc_eval_expr(f, op_ix1, SC_Type::Num());
        auto ix2 = sc_eval_expr(f, op_ix2, SC_Type::Num());
        auto ix3 = sc_eval_expr(f, op_ix3, SC_Type::Num());
        SC_Value result = f.sc_.newvalue(SC_Type::Num());
        f.sc_.out() << "  " << result.type << " " << result << " = " << array
                 << "[int(" << ix1 << ")*" << array.type.dim2_
                 << "+" << "int(" << ix2 << ")][int(" << ix3 << ")];\n";
        return result;
    }
    throw Exception(acx, "3 indexes (a[i,j,k]) not supported for this array");
}

SC_Value Call_Expr::sc_eval(SC_Frame& f) const
{
    SC_Value scval;
    if (sc_try_eval(*fun_, f, scval)) {
        if (!scval.type.is_list())
            throw Exception(At_SC_Phrase(fun_->syntax_, f),
                stringify("type ", scval.type, ": not an array or function"));
        auto list = cast<List_Expr>(arg_);
        if (list == nullptr)
            throw Exception(At_SC_Phrase(arg_->syntax_, f),
                "expected '[index]' expression");
        if (list->size() == 1)
            return sc_eval_index_expr(scval, *list->at(0), f);
        if (list->size() == 2)
            return sc_eval_index2_expr(scval, *list->at(0), *list->at(1), f,
                At_SC_Phrase(arg_->syntax_, f));
        if (list->size() == 3)
            return sc_eval_index3_expr(scval,
                *list->at(0), *list->at(1), *list->at(2),
                f, At_SC_Phrase(arg_->syntax_, f));
    }
    Value val = sc_constify(*fun_, f);
    Value v = val;
    for (;;) {
        if (auto fun = v.dycast<Function>()) {
            return fun->sc_call_expr(*arg_, syntax_, f);
        }
        if (auto r = v.dycast<Record>()) {
            static Symbol call_key = "call";
            if (r->hasfield(call_key)) {
                v = r->getfield(call_key,At_SC_Phrase(fun_->syntax_,f));
                continue;
            }
        }
        break;
    }
    throw Exception(At_SC_Phrase(fun_->syntax_, f),
        stringify("",val," is not an array or function"));
}

SC_Value Data_Ref::sc_eval(SC_Frame& f) const
{
    return f[slot_];
}

SC_Value Nonlocal_Data_Ref::sc_eval(SC_Frame& f) const
{
    return sc_eval_const(f, f.nonlocals_->at(slot_), *syntax_);
}
SC_Value Symbolic_Ref::sc_eval(SC_Frame& f) const
{
    auto b = f.nonlocals_->dictionary_->find(name_);
    assert(b != f.nonlocals_->dictionary_->end());
    Value val = f.nonlocals_->get(b->second);
    return sc_eval_const(f, val, *syntax_);
}

SC_Value List_Expr_Base::sc_eval(SC_Frame& f) const
{
    if (this->size() == 2) {
        auto e1 = sc_eval_expr(f, *(*this)[0], SC_Type::Num());
        auto e2 = sc_eval_expr(f, *(*this)[1], SC_Type::Num());
        SC_Value result = f.sc_.newvalue(SC_Type::Vec(2));
        f.sc_.out() << "  vec2 "<<result<<" = vec2("<<e1<<","<<e2<<");\n";
        return result;
    }
    if (this->size() == 3) {
        auto e1 = sc_eval_expr(f, *(*this)[0], SC_Type::Num());
        auto e2 = sc_eval_expr(f, *(*this)[1], SC_Type::Num());
        auto e3 = sc_eval_expr(f, *(*this)[2], SC_Type::Num());
        SC_Value result = f.sc_.newvalue(SC_Type::Vec(3));
        f.sc_.out() << "  vec3 "<<result<<" = vec3("
            <<e1<<","<<e2<<","<<e3<<");\n";
        return result;
    }
    if (this->size() == 4) {
        auto e1 = sc_eval_expr(f, *(*this)[0], SC_Type::Num());
        auto e2 = sc_eval_expr(f, *(*this)[1], SC_Type::Num());
        auto e3 = sc_eval_expr(f, *(*this)[2], SC_Type::Num());
        auto e4 = sc_eval_expr(f, *(*this)[3], SC_Type::Num());
        SC_Value result = f.sc_.newvalue(SC_Type::Vec(4));
        f.sc_.out() << "  vec4 "<<result<<" = vec4("
            <<e1<<","<<e2<<","<<e3<<","<<e4<<");\n";
        return result;
    }
    throw Exception(At_SC_Phrase(syntax_, f),
        "this list constructor is not supported");
}

SC_Value Not_Expr::sc_eval(SC_Frame& f) const
{
    auto arg = sc_eval_expr(f, *arg_, SC_Type::Bool());
    SC_Value result = f.sc_.newvalue(SC_Type::Bool());
    f.sc_.out() <<"  bool "<<result<<" = !"<<arg<<";\n";
    return result;
}
SC_Value Or_Expr::sc_eval(SC_Frame& f) const
{
    // TODO: change Or to use lazy evaluation.
    auto arg1 = sc_eval_expr(f, *arg1_, SC_Type::Bool());
    auto arg2 = sc_eval_expr(f, *arg2_, SC_Type::Bool());
    SC_Value result = f.sc_.newvalue(SC_Type::Bool());
    f.sc_.out() <<"  bool "<<result<<" =("<<arg1<<" || "<<arg2<<");\n";
    return result;
}
SC_Value And_Expr::sc_eval(SC_Frame& f) const
{
    // TODO: change And to use lazy evaluation.
    auto arg1 = sc_eval_expr(f, *arg1_, SC_Type::Bool());
    auto arg2 = sc_eval_expr(f, *arg2_, SC_Type::Bool());
    SC_Value result = f.sc_.newvalue(SC_Type::Bool());
    f.sc_.out() <<"  bool "<<result<<" =("<<arg1<<" && "<<arg2<<");\n";
    return result;
}
SC_Value If_Else_Op::sc_eval(SC_Frame& f) const
{
    // TODO: change If to use lazy evaluation.
    auto arg1 = sc_eval_expr(f, *arg1_, SC_Type::Bool());
    auto arg2 = sc_eval_op(f, *arg2_);
    auto arg3 = sc_eval_op(f, *arg3_);
    if (arg2.type != arg3.type) {
        throw Exception(At_SC_Phrase(syntax_, f), stringify(
            "if: type mismatch in 'then' and 'else' arms (",
            arg2.type, ",", arg3.type, ")"));
    }
    SC_Value result = f.sc_.newvalue(arg2.type);
    f.sc_.out() <<"  "<<arg2.type<<" "<<result
             <<" =("<<arg1<<" ? "<<arg2<<" : "<<arg3<<");\n";
    return result;
}
void If_Else_Op::sc_exec(SC_Frame& f) const
{
    auto arg1 = sc_eval_expr(f, *arg1_, SC_Type::Bool());
    f.sc_.out() << "  if ("<<arg1<<") {\n";
    arg2_->sc_exec(f);
    f.sc_.out() << "  } else {\n";
    arg3_->sc_exec(f);
    f.sc_.out() << "  }\n";
}
void If_Op::sc_exec(SC_Frame& f) const
{
    auto arg1 = sc_eval_expr(f, *arg1_, SC_Type::Bool());
    f.sc_.out() << "  if ("<<arg1<<") {\n";
    arg2_->sc_exec(f);
    f.sc_.out() << "  }\n";
}
void While_Op::sc_exec(SC_Frame& f) const
{
    f.sc_.opcaches_.emplace_back(Op_Cache{});
    f.sc_.out() << "  while (true) {\n";
    auto cond = sc_eval_expr(f, *cond_, SC_Type::Bool());
    f.sc_.out() << "  if (!"<<cond<<") break;\n";
    body_->sc_exec(f);
    f.sc_.out() << "  }\n";
    f.sc_.opcaches_.pop_back();
}
void For_Op::sc_exec(SC_Frame& f) const
{
  #define RANGE_EXPRESSIONS 1
    auto range = cast<const Range_Expr>(list_);
    if (range == nullptr)
        throw Exception(At_SC_Phrase(list_->syntax_, f),
            "not a range");
  #if RANGE_EXPRESSIONS
    // range arguments are general expressions
    auto first = sc_eval_expr(f, *range->arg1_, SC_Type::Num());
    auto last = sc_eval_expr(f, *range->arg2_, SC_Type::Num());
    auto step = range->arg3_ != nullptr
        ? sc_eval_expr(f, *range->arg3_, SC_Type::Num())
        : sc_eval_const(f, Value{1.0}, *syntax_);
  #else
    // range arguments are constants
    double first = sc_constify(*range->arg1_, f)
        .to_num(At_SC_Phrase(range->arg1_->syntax_, f));
    double last = sc_constify(*range->arg2_, f)
        .to_num(At_SC_Phrase(range->arg2_->syntax_, f));
    double step = range->arg3_ != nullptr
        ? sc_constify(*range->arg3_, f)
          .to_num(At_SC_Phrase(range->arg3_->syntax_, f))
        : 1.0;
  #endif
    auto i = f.sc_.newvalue(SC_Type::Num());
    f.sc_.opcaches_.emplace_back(Op_Cache{});
  #if RANGE_EXPRESSIONS
    f.sc_.out() << "  for (float " << i << "=" << first << ";"
             << i << (range->half_open_ ? "<" : "<=") << last << ";"
             << i << "+=" << step << ") {\n";
  #else
    f.sc_.out() << "  for (float " << i << "=" << dfmt(first, dfmt::EXPR) << ";"
             << i << (range->half_open_ ? "<" : "<=") << dfmt(last, dfmt::EXPR) << ";"
             << i << "+=" << dfmt(step, dfmt::EXPR) << ") {\n";
  #endif
    pattern_->sc_exec(i, At_SC_Phrase(list_->syntax_, f), f);
    body_->sc_exec(f);
    f.sc_.out() << "  }\n";
    f.sc_.opcaches_.pop_back();
}
SC_Value Equal_Expr::sc_eval(SC_Frame& f) const
{
    auto a = sc_eval_op(f, *arg1_);
    auto b = sc_eval_op(f, *arg2_);
    if (a.type != b.type || a.type.rank_ > 0) {
        throw Exception(At_SC_Phrase(syntax_, f),
            stringify("domain error: ",a.type," == ",b.type));
    }
    SC_Value result = f.sc_.newvalue(SC_Type::Bool());
    f.sc_.out() <<"  bool "<<result<<" =("<<a<<" == "<<b<<");\n";
    return result;
}
SC_Value Not_Equal_Expr::sc_eval(SC_Frame& f) const
{
    auto a = sc_eval_op(f, *arg1_);
    auto b = sc_eval_op(f, *arg2_);
    if (a.type != b.type || a.type.rank_ > 0) {
        throw Exception(At_SC_Phrase(syntax_, f),
            stringify("domain error: ",a.type," != ",b.type));
    }
    SC_Value result = f.sc_.newvalue(SC_Type::Bool());
    f.sc_.out() <<"  bool "<<result<<" =("<<a<<" != "<<b<<");\n";
    return result;
}
SC_Value Less_Expr::sc_eval(SC_Frame& f) const
{
    auto arg1 = sc_eval_expr(f, *arg1_, SC_Type::Num());
    auto arg2 = sc_eval_expr(f, *arg2_, SC_Type::Num());
    SC_Value result = f.sc_.newvalue(SC_Type::Bool());
    f.sc_.out() <<"  bool "<<result<<" =("<<arg1<<" < "<<arg2<<");\n";
    return result;
}
SC_Value Greater_Expr::sc_eval(SC_Frame& f) const
{
    auto arg1 = sc_eval_expr(f, *arg1_, SC_Type::Num());
    auto arg2 = sc_eval_expr(f, *arg2_, SC_Type::Num());
    SC_Value result = f.sc_.newvalue(SC_Type::Bool());
    f.sc_.out() <<"  bool "<<result<<" =("<<arg1<<" > "<<arg2<<");\n";
    return result;
}
SC_Value Less_Or_Equal_Expr::sc_eval(SC_Frame& f) const
{
    auto arg1 = sc_eval_expr(f, *arg1_, SC_Type::Num());
    auto arg2 = sc_eval_expr(f, *arg2_, SC_Type::Num());
    SC_Value result = f.sc_.newvalue(SC_Type::Bool());
    f.sc_.out() <<"  bool "<<result<<" =("<<arg1<<" <= "<<arg2<<");\n";
    return result;
}
SC_Value Greater_Or_Equal_Expr::sc_eval(SC_Frame& f) const
{
    auto arg1 = sc_eval_expr(f, *arg1_, SC_Type::Num());
    auto arg2 = sc_eval_expr(f, *arg2_, SC_Type::Num());
    SC_Value result = f.sc_.newvalue(SC_Type::Bool());
    f.sc_.out() <<"  bool "<<result<<" =("<<arg1<<" >= "<<arg2<<");\n";
    return result;
}

SC_Value sc_vec_element(SC_Frame& f, SC_Value vec, int i)
{
    SC_Value r = f.sc_.newvalue(SC_Type::Num());
    f.sc_.out() << "  float " << r << " = " << vec << "[" << i << "];\n";
    return r;
}

} // namespace curv

max_stars_repo_name: p-e-w/curv

max_issues_repo_name: p-e-w/curv

max_forks_repo_name: p-e-w/curv


text:
/*
 * Copyright (c) 2010-2011 frankee zhou (frankee.zhou at gmail dot com)
 *
 * Distributed under 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 <boost/thread.hpp>
#include <boost/date_time.hpp>

#include "cetty/channel/DefaultChannelFuture.h"

#include "cetty/logging/InternalLogger.h"
#include "cetty/logging/InternalLoggerFactory.h"

#include "cetty/util/TimeUnit.h"
#include "cetty/util/Exception.h"

namespace cetty { namespace channel {

using namespace cetty::util;
using namespace cetty::logging;

InternalLogger *DefaultChannelFuture::logger =
                    InternalLoggerFactory::getInstance("DefaultChannelFuture");

bool DefaultChannelFuture::useDeadLockChecker = true;
bool DefaultChannelFuture::disabledDeadLockCheckerOnce = false;

Exception DefaultChannelFuture::CANCELLED("Future cancelled");

DefaultChannelFuture::DefaultChannelFuture(Channel& channel, bool cancellable)
                      : cancellable(cancellable),
                        done(false),
                        channel(&channel),
                        functionListener(0),
                        firstListener(NULL),
                        otherListeners(NULL),
                        progressListeners(NULL),
                        cause(NULL),
                        cond(NULL),
                        waiters(0){
}

DefaultChannelFuture::~DefaultChannelFuture() {
    if (otherListeners) {
        delete otherListeners;
    }

    if (progressListeners) {
        delete progressListeners;
    }

    if (cause && cause != &CANCELLED) {
        delete cause;
    }

    if (cond) {
        delete cond;
    }
}

void DefaultChannelFuture::setUseDeadLockChecker(bool useDeadLockChecker) {
    if (!useDeadLockChecker && !disabledDeadLockCheckerOnce) {
        disabledDeadLockCheckerOnce = true;
        logger->debug("The dead lock checker in ChannelFuture \
                      has been disabled as requested at your own risk.");
    }
    DefaultChannelFuture::useDeadLockChecker = useDeadLockChecker;
}

bool DefaultChannelFuture::isDone() const {
    boost::lock_guard<boost::mutex> guard(mutex);
    return done;
}

bool DefaultChannelFuture::isSuccess() const {
    boost::lock_guard<boost::mutex> guard(mutex);
    return done && cause == NULL;
}

const Exception* DefaultChannelFuture::getCause() const {
    boost::lock_guard<boost::mutex> guard(mutex);

    if (cause != &CANCELLED) {
        return cause;
    } else {
        return NULL;
    }
}

bool DefaultChannelFuture::isCancelled() const {
    boost::lock_guard<boost::mutex> guard(mutex);
    return cause == &CANCELLED;
}

void DefaultChannelFuture::setListener(const ListenerFunction& listener) {
    if (listener.empty()) {
        return;
    }
    bool notifyNow = false;

    {
        boost::lock_guard<boost::mutex> guard(mutex);

        if (done) {
            notifyNow = true;
        }
        else {
            functionListener = listener;
        }
    }

    if (notifyNow) {
        notifyListener(listener);
    }
}

void DefaultChannelFuture::addListener(ChannelFutureListener* listener) {
    if (listener == NULL) {
        return;
    }

    bool notifyNow = false;
    {
        boost::lock_guard<boost::mutex> guard(mutex);

        if (done) {
            notifyNow = true;
        }
        else {
            if (firstListener == NULL) {
                firstListener = listener;
            }
            else {
                if (otherListeners == NULL) {
                    otherListeners = new std::list<ChannelFutureListener*>();
                }
                otherListeners->push_back(listener);
            }

            ChannelFutureProgressListener* progressListener =
                dynamic_cast<ChannelFutureProgressListener*>(listener);
            if (progressListener) {
                if (progressListeners == NULL) {
                    progressListeners = new std::list<ChannelFutureProgressListener*>();
                }
                progressListeners->push_back(progressListener);
            }
        }
    }

    if (notifyNow) {
        notifyListener(listener);
    }
}

void DefaultChannelFuture::removeListener(const ChannelFutureListener* listener) {
    if (listener == NULL) {
        return;
    }

    boost::lock_guard<boost::mutex> guard(mutex);
    if (!done) {
        if (listener == firstListener) {
            if (otherListeners != NULL && !otherListeners->empty()) {
                firstListener = otherListeners->front();
                otherListeners->pop_front();
            }
            else {
                firstListener = NULL;
            }
        }
        else if (otherListeners != NULL) {
            otherListeners->remove((ChannelFutureListener* const)listener);
        }

        const ChannelFutureProgressListener* progressListener =
            dynamic_cast<const ChannelFutureProgressListener*>(listener);
        if (progressListener && progressListeners) {
            progressListeners->remove(
                (ChannelFutureProgressListener* const)progressListener);
        }
    }
}

ChannelFuture& DefaultChannelFuture::await() {
    if (boost::this_thread::interruption_requested()) {
        throw InterruptedException();
    }

    {
        boost::unique_lock<boost::mutex> lock(mutex);
        while (!done) {
            checkDeadLock();
            waiters++;
            try {
                condition().wait(lock);
            }
            catch(...) {
                waiters--;
            }
        }
    }
    return *this;
}

bool DefaultChannelFuture::await(boost::int64_t timeout, const TimeUnit& unit) {
    return await0(unit.toMillis(timeout), true);
}

bool DefaultChannelFuture::await(boost::int64_t timeoutMillis) {
    return await0(timeoutMillis, true);
}

ChannelFuture& DefaultChannelFuture::awaitUninterruptibly() {
    bool interrupted = false;
    {
        boost::unique_lock<boost::mutex> lock(mutex);
        while (!done) {
            checkDeadLock();
            waiters++;
            try {
                condition().wait(lock);
            }
            catch (const boost::thread_interrupted& e) {
                interrupted = true;
                waiters--;

                logger->warn("thread interrupted while awaiting");
            }
        }
    }

    if (interrupted) {
        //TODO must get
        //Thread.currentThread().interrupt();
    }
    return *this;
}

bool DefaultChannelFuture::awaitUninterruptibly(boost::int64_t timeout, const TimeUnit& unit) {
    try {
        return await0(unit.toMillis(timeout), false);
    }
    catch (const boost::thread_interrupted& e) {
        throw RuntimeException("thread interrupted.");
    }
}

bool DefaultChannelFuture::awaitUninterruptibly(boost::int64_t timeoutMillis) {
    try {
        return await0(timeoutMillis, false);
    }
    catch (const boost::thread_interrupted& e) {
        throw RuntimeException("thread interrupted.");
    }
}

bool DefaultChannelFuture::setSuccess() {
    {
        boost::lock_guard<boost::mutex> guard(mutex);

        // Allow only once.
        if (done) {
            return false;
        }

        done = true;
        if (waiters > 0) {
            cond->notify_all();
        }
    }

    notifyListeners();
    return true;
}

bool DefaultChannelFuture::setFailure(const Exception& cause) {
    {
        boost::lock_guard<boost::mutex> guard(mutex);

        // Allow only once.
        if (done) {
            return false;
        }

        if (this->cause && this->cause != &CANCELLED) {
            delete this->cause;
            this->cause = NULL;
        }
        this->cause = new Exception(cause);

        done = true;
        if (waiters > 0) {
            cond->notify_all();
        }
    }

    notifyListeners();
    return true;
}

bool DefaultChannelFuture::cancel() {
    if (!cancellable) {
        return false;
    }

    {
        boost::lock_guard<boost::mutex> guard(mutex);

        // Allow only once.
        if (done) {
            return false;
        }

        cause = &CANCELLED;
        done = true;
        if (waiters > 0) {
            cond->notify_all();
        }
    }

    notifyListeners();
    return true;
}

bool DefaultChannelFuture::setProgress(int amount, int current, int total) {
    std::list<ChannelFutureProgressListener*> tmplist;

    {
        boost::lock_guard<boost::mutex> guard(mutex);

        // Do not generate progress event after completion.
        if (done) {
            return false;
        }

        if (progressListeners == NULL || progressListeners->empty()) {
            // Nothing to notify - no need to create an empty array.
            return true;
        }

        tmplist = *progressListeners;
    }

    std::list<ChannelFutureProgressListener*>::iterator itr;
    for (itr = tmplist.begin(); itr != tmplist.end(); ++itr) {
        notifyProgressListener(*itr, amount, current, total);
    }

    return true;
}

bool DefaultChannelFuture::await0(boost::int64_t timeoutMillis, bool interruptable) {
    if (interruptable && boost::this_thread::interruption_requested()) {
        throw InterruptedException("");
    }

    boost::posix_time::time_duration duration =
        boost::posix_time::milliseconds(timeoutMillis);

    boost::posix_time::ptime expiredTime(
        timeoutMillis <= 0 ? boost::get_system_time()
                           : boost::get_system_time() + duration);

    bool interrupted = false;

    try {
        boost::unique_lock<boost::mutex> lock(mutex);
        if (done) {
            return done;
        }
        else if (timeoutMillis <= 0) {
            return done;
        }

        checkDeadLock();
        waiters++;
        try {
            for (;;) {
                try {
                    condition().timed_wait(lock, expiredTime);
                }
                catch (const boost::thread_interrupted& e) {
                    if (interruptable) {
                        throw InterruptedException("");
                    }
                    else {
                        interrupted = true;
                    }
                }

                if (done) {
                    return true;
                }
                else {
                    if (boost::get_system_time() >= expiredTime) {
                        return done;
                    }
                }
            }
        }
        catch (...) {
            waiters--;
        }
    }
    catch (...) {
        if (interrupted) {
            //Thread.currentThread().interrupt();
        }
    }
    return false;
}

void DefaultChannelFuture::checkDeadLock() {
//     if (isUseDeadLockChecker() && IoWorkerRunnable.IN_IO_THREAD.get()) {
//         throw IllegalStateException(
//                 "await*() in I/O thread causes a dead lock or "
//                 "sudden performance drop. Use addListener() instead or "
//                 "call await*() from a different thread.");
//     }
}

void DefaultChannelFuture::notifyListeners() {
    // This method doesn't need synchronization because:
    // 1) This method is always called after synchronized (this) block.
    //    Hence any listener list modification happens-before this method.
    // 2) This method is called only when 'done' is true.  Once 'done'
    //    becomes true, the listener list is never modified - see add/removeListener()
    if (firstListener != NULL) {
        notifyListener(firstListener);
        firstListener = NULL;

        if (otherListeners && !otherListeners->empty()) {
            std::list<ChannelFutureListener*>::iterator itr;
            for (itr = otherListeners->begin(); itr != otherListeners->end(); ++itr) {
                notifyListener(*itr);
            }
            otherListeners->empty();
        }
    }

    if (functionListener) {
        notifyListener(functionListener);
        functionListener = 0;
    }
}

void DefaultChannelFuture::notifyListener(ChannelFutureListener* l) {
    try {
        l->operationComplete(shared_from_this());
    }
    catch (const Exception& e) {
        logger->warn(
            "An exception was thrown by ChannelFutureListener .", e);
    }
}

void DefaultChannelFuture::notifyListener(const ListenerFunction& l) {
    try {
        l(shared_from_this());
    }
    catch (const Exception& e) {
        logger->warn(
            "An exception was thrown by ChannelFutureListener .", e);
    }
}

void DefaultChannelFuture::notifyProgressListener(ChannelFutureProgressListener* l, int amount, int current, int total) {
    if (NULL == l) return;

    try {
        l->operationProgressed(shared_from_this(), amount, current, total);
    }
    catch (const Exception& e) {
        logger->warn(
            std::string("An exception was thrown by ").append(l->toString()),
            e);
    }
}

boost::condition_variable& DefaultChannelFuture::condition() {
    if (!cond) {
        cond = new boost::condition_variable();
    }
    return *cond;
}

}}

max_stars_repo_name: frankee/Cetty

max_issues_repo_name: frankee/Cetty

max_forks_repo_name: frankee/Cetty


text:
#pragma once

#include <Eigen/Dense>
#include <cmath>
#include <iomanip>
#include <random>
#include <vector>

namespace Robotics {
    template <int N>
    using ColumnVector = Eigen::Matrix<double, N, 1>;

    template <int N>
    using SquareMatrix = Eigen::Matrix<double, N, N>;

    template <int N, int M>
    using Matrix = Eigen::Matrix<double, N, M>;

    inline double deg2rad(double deg)
    {
        return deg * 3.14 / 180.0;  // TODO: replace 3.14 with M_PI (cross-platform)
    }

    /**
     * @brief return evenly spaced numbers over a specified N interval.
     * @param start The starting value of the sequence
     * @param stop The end value of the sequence
     * @param N number of sample to generate.
     */
    template <typename T>
    inline constexpr std::vector<T> linspace(T start, T stop, std::size_t N)
    {
        assert(N > 1);
        std::vector<T> vec(N, 0);

        T val{start};
        T increment{(stop - start) / static_cast<T>(N - 1)};
        for (auto it = vec.begin(); it != vec.end(); ++it) {
            *it = val;
            val += increment;
        }
        return vec;
    }

    class NormalDistributionRandomGenerator {
      public:
        template <int Size>
        ColumnVector<Size> GetColumnVector()
        {
            ColumnVector<Size> rand_vector;

            for (auto i = 0; i < rand_vector.size(); i++) rand_vector(i) = distribution(generator);

            return rand_vector;
        }

      private:
        std::default_random_engine generator;
        std::normal_distribution<double> distribution{0.0, 1.0};
    };

}  // namespace Robotics

ext: hpp