<commit_before>// fdp.hpp :  include file containing templated C++ interfaces to fused dot product
//
// Copyright (C) 2017-2019 Stillwater Supercomputing, Inc.
//
// This file is part of the universal numbers project, which is released under an MIT Open Source license.

#include <vector>

namespace sw {
	namespace unum {

// dot product: the operator vector::x[index] is limited to uint32_t, so the arguments are limited to uint32_t as well
// since we do not support arbitrary posit configuration conversions, the element type of the vectors x and y are declared to be the same.
// TODO: investigate if the vector<> index is always a 32bit entity?
template<typename Ty>
Ty dot(size_t n, const std::vector<Ty>& x, size_t incx, const std::vector<Ty>& y, size_t incy) {
	Ty sum_of_products = 0;
	size_t cnt, ix, iy;
	for (cnt = 0, ix = 0, iy = 0; cnt < n && ix < x.size() && iy < y.size(); ++cnt, ix += incx, iy += incy) {
		Ty product = x[ix] * y[iy];
		sum_of_products += product;
	}
	return sum_of_products;
}

/// //////////////////////////////////////////////////////////////////
/// fused dot product operators
/// fdp_qc         fused dot product with quire continuation
/// fdp_stride     fused dot product with non-negative stride
/// fdp            fused dot product of two vectors

// Fused dot product with quire continuation
template<typename Qy, typename Vector>
void fdp_qc(Qy& sum_of_products, size_t n, const Vector& x, size_t incx, const Vector& y, size_t incy) {
	size_t ix, iy;
	for (ix = 0, iy = 0; ix < n && iy < n; ix = ix + incx, iy = iy + incy) {
		sum_of_products += sw::unum::quire_mul(x[ix], y[iy]);
	}
}

// Resolved fused dot product, with the option to control capacity bits in the quire
template<typename Vector, size_t capacity = 10>
typename Vector::value_type fdp_stride(size_t n, const Vector& x, size_t incx, const Vector& y, size_t incy) {
	constexpr size_t nbits = Vector::value_type::nbits;
	constexpr size_t es = Vector::value_type::es;
	quire<nbits, es, capacity> q = 0;
	size_t ix, iy;
	for (ix = 0, iy = 0; ix < n && iy < n; ix = ix + incx, iy = iy + incy) {
		q += sw::unum::quire_mul(x[ix], y[iy]);
		if (sw::unum::_trace_quire_add) std::cout << q << '\n';
	}
	typename Vector::value_type sum;
	convert(q.to_value(), sum);     // one and only rounding step of the fused-dot product
	return sum;
}

// Specialized resolved fused dot product that assumes unit stride and a standard vector,
// with the option to control capacity bits in the quire
template<typename Vector, size_t capacity = 10>
typename Vector::value_type fdp(const Vector& x, const Vector& y) {
	constexpr size_t nbits = Vector::value_type::nbits;
	constexpr size_t es = Vector::value_type::es;
	quire<nbits, es, capacity> q = 0;
	size_t ix, iy, n = x.size();
	for (ix = 0, iy = 0; ix < n && iy < n; ++ix, ++iy) {
		q += sw::unum::quire_mul(x[ix], y[iy]);
	}
	typename Vector::value_type sum;
	convert(q.to_value(), sum);     // one and only rounding step of the fused-dot product
	return sum;
}

#ifdef BLAS_L2
// LEVEL 2 BLAS operators
template<typename Ty>
void matvec(const std::vector<Ty>& A, const std::vector<Ty>& x, std::vector<Ty>& b) {
	// preconditions
	size_t d = x.size();
	assert(A.size() == d*d);
	assert(b.size() == d);
	for (size_t i = 0; i < d; ++i) {
		b[i] = 0;
		for (size_t j = 0; j < d; ++j) {
			//std::cout << "b[" << i << "] = " << b[i] << std::endl;
			//std::cout << "A[" << i << "][" << j << "] = " << A[i*d + j] << std::endl;
			//std::cout << "x[" << j << "] = " << x[j] << std::endl;
			b[i] = b[i] + A[i*d + j] * x[j];
		}
		//std::cout << "b[" << i << "] = " << b[i] << std::endl;
	}
}

// leverage template parameter inference to specialize matvec to use the quire when the inputs are posit vectors
template<size_t nbits, size_t es, size_t capacity = 10>
void matvec(const std::vector< posit<nbits, es> >& A, const std::vector< posit<nbits, es> >& x, std::vector< posit<nbits, es> >& b) {
	// preconditions
	size_t d = x.size();
	assert(A.size() == d*d);
	assert(b.size() == d);
	for (size_t i = 0; i < d; ++i) {
		b[i] = 0;
		quire<nbits, es, capacity> q;   // initialized to 0 by constructor
		for (size_t j = 0; j < d; ++j) {
			q += quire_mul(A[i*d + j], x[j]);
			if (sw::unum::_trace_quire_add) std::cout << q << '\n';
		}
		convert(q.to_value(), b[i]);  // one and only rounding step of the fused-dot product
		//std::cout << "b[" << i << "] = " << b[i] << std::endl;
	}
}
#endif  // BLAS_L2

#ifdef BLAS_L3
// LEVEL 3 BLAS operators

// matrix-matrix multiplication
template<typename Ty>
void matmul(const std::vector<Ty>& A, const std::vector<Ty>& B, std::vector<Ty>& C) {
	// preconditions
	size_t d = size_t(std::sqrt(A.size()));
	assert(A.size() == d*d);
	assert(B.size() == d*d);
	assert(C.size() == d*d);
	for (size_t i = 0; i < d; ++i) {
		for (size_t j = 0; j < d; ++j) {
			C[i*d + j] = Ty(0);
			for (size_t k = 0; k < d; ++k) {
				C[i*d + j] = C[i*d + j] + A[i*d + k] * B[k*d + j];
			}
		}
	}
}

// leverage template parameter inference to specialize matmul to use the quire when the inputs are posit vectors
template<size_t nbits, size_t es, size_t capacity = 10>
void matmul(const std::vector<posit<nbits,es> >& A, const std::vector< posit<nbits, es> >& B, std::vector< posit<nbits, es> >& C) {
	// preconditions
	size_t d = size_t(std::sqrt(A.size()));
	assert(A.size() == d*d);
	assert(B.size() == d*d);
	assert(C.size() == d*d);
	for (size_t i = 0; i < d; ++i) {
		for (size_t j = 0; j < d; ++j) {
			C[i*d + j] = 0;
			quire<nbits, es, capacity> q;   // initialized to 0 by constructor
			for (size_t k = 0; k < d; ++k) {
				// C[i*d + j] = C[i*d + j] + A[i*d + k] * B[k*d + j];
				q += quire_mul(A[i*d + k], B[k*d + j]);
				if (sw::unum::_trace_quire_add) std::cout << q << '\n';
			}
			convert(q.to_value(), C[i*d + j]);  // one and only rounding step of the fused-dot product
		}
	}
}

#endif  // BLAS_L3

} // namespace unum
} // namespace sw

<commit_msg>removing BLAS L2 and L3 operators from fdp<commit_after>// fdp.hpp :  include file containing templated C++ interfaces to fused dot product
//
// Copyright (C) 2017-2019 Stillwater Supercomputing, Inc.
//
// This file is part of the universal numbers project, which is released under an MIT Open Source license.

#include <vector>

namespace sw {
	namespace unum {

// dot product: the operator vector::x[index] is limited to uint32_t, so the arguments are limited to uint32_t as well
// since we do not support arbitrary posit configuration conversions, the element type of the vectors x and y are declared to be the same.
// TODO: investigate if the vector<> index is always a 32bit entity?
template<typename Ty>
Ty dot(size_t n, const std::vector<Ty>& x, size_t incx, const std::vector<Ty>& y, size_t incy) {
	Ty sum_of_products = 0;
	size_t cnt, ix, iy;
	for (cnt = 0, ix = 0, iy = 0; cnt < n && ix < x.size() && iy < y.size(); ++cnt, ix += incx, iy += incy) {
		Ty product = x[ix] * y[iy];
		sum_of_products += product;
	}
	return sum_of_products;
}

/// //////////////////////////////////////////////////////////////////
/// fused dot product operators
/// fdp_qc         fused dot product with quire continuation
/// fdp_stride     fused dot product with non-negative stride
/// fdp            fused dot product of two vectors

// Fused dot product with quire continuation
template<typename Qy, typename Vector>
void fdp_qc(Qy& sum_of_products, size_t n, const Vector& x, size_t incx, const Vector& y, size_t incy) {
	size_t ix, iy;
	for (ix = 0, iy = 0; ix < n && iy < n; ix = ix + incx, iy = iy + incy) {
		sum_of_products += sw::unum::quire_mul(x[ix], y[iy]);
	}
}

// Resolved fused dot product, with the option to control capacity bits in the quire
template<typename Vector, size_t capacity = 10>
typename Vector::value_type fdp_stride(size_t n, const Vector& x, size_t incx, const Vector& y, size_t incy) {
	constexpr size_t nbits = Vector::value_type::nbits;
	constexpr size_t es = Vector::value_type::es;
	quire<nbits, es, capacity> q = 0;
	size_t ix, iy;
	for (ix = 0, iy = 0; ix < n && iy < n; ix = ix + incx, iy = iy + incy) {
		q += sw::unum::quire_mul(x[ix], y[iy]);
		if (sw::unum::_trace_quire_add) std::cout << q << '\n';
	}
	typename Vector::value_type sum;
	convert(q.to_value(), sum);     // one and only rounding step of the fused-dot product
	return sum;
}

// Specialized resolved fused dot product that assumes unit stride and a standard vector,
// with the option to control capacity bits in the quire
template<typename Vector, size_t capacity = 10>
typename Vector::value_type fdp(const Vector& x, const Vector& y) {
	constexpr size_t nbits = Vector::value_type::nbits;
	constexpr size_t es = Vector::value_type::es;
	quire<nbits, es, capacity> q = 0;
	size_t ix, iy, n = x.size();
	for (ix = 0, iy = 0; ix < n && iy < n; ++ix, ++iy) {
		q += sw::unum::quire_mul(x[ix], y[iy]);
	}
	typename Vector::value_type sum;
	convert(q.to_value(), sum);     // one and only rounding step of the fused-dot product
	return sum;
}

} // namespace unum
} // namespace sw

<|endoftext|>


<commit_before>// UndefCapturedBlockVarChecker.cpp - Uninitialized captured vars -*- C++ -*-=//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This checker detects blocks that capture uninitialized values.
//
//===----------------------------------------------------------------------===//

#include "ClangSACheckers.h"
#include "clang/AST/Attr.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;
using namespace ento;

namespace {
class UndefCapturedBlockVarChecker
  : public Checker< check::PostStmt<BlockExpr> > {
 mutable OwningPtr<BugType> BT;

public:
  void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
};
} // end anonymous namespace

static const DeclRefExpr *FindBlockDeclRefExpr(const Stmt *S,
                                               const VarDecl *VD) {
  if (const DeclRefExpr *BR = dyn_cast<DeclRefExpr>(S))
    if (BR->getDecl() == VD)
      return BR;

  for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
       I!=E; ++I)
    if (const Stmt *child = *I) {
      const DeclRefExpr *BR = FindBlockDeclRefExpr(child, VD);
      if (BR)
        return BR;
    }

  return NULL;
}

void
UndefCapturedBlockVarChecker::checkPostStmt(const BlockExpr *BE,
                                            CheckerContext &C) const {
  if (!BE->getBlockDecl()->hasCaptures())
    return;

  ProgramStateRef state = C.getState();
  const BlockDataRegion *R =
    cast<BlockDataRegion>(state->getSVal(BE,
                                         C.getLocationContext()).getAsRegion());

  BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
                                            E = R->referenced_vars_end();

  for (; I != E; ++I) {
    // This VarRegion is the region associated with the block; we need
    // the one associated with the encompassing context.
    const VarRegion *VR = *I;
    const VarDecl *VD = VR->getDecl();

    if (VD->getAttr<BlocksAttr>() || !VD->hasLocalStorage())
      continue;

    // Get the VarRegion associated with VD in the local stack frame.
    const LocationContext *LC = C.getLocationContext();
    VR = C.getSValBuilder().getRegionManager().getVarRegion(VD, LC);
    SVal VRVal = state->getSVal(VR);

    if (VRVal.isUndef())
      if (ExplodedNode *N = C.generateSink()) {
        if (!BT)
          BT.reset(new BuiltinBug("uninitialized variable captured by block"));

        // Generate a bug report.
        SmallString<128> buf;
        llvm::raw_svector_ostream os(buf);

        os << "Variable '" << VD->getName()
           << "' is uninitialized when captured by block";

        BugReport *R = new BugReport(*BT, os.str(), N);
        if (const Expr *Ex = FindBlockDeclRefExpr(BE->getBody(), VD))
          R->addRange(Ex->getSourceRange());
        R->addVisitor(new FindLastStoreBRVisitor(VRVal, VR));
        R->disablePathPruning();
        // need location of block
        C.emitReport(R);
      }
  }
}

void ento::registerUndefCapturedBlockVarChecker(CheckerManager &mgr) {
  mgr.registerChecker<UndefCapturedBlockVarChecker>();
}
<commit_msg>Use 'getOriginalRegion()' rather than going through the logic to recreate it.<commit_after>// UndefCapturedBlockVarChecker.cpp - Uninitialized captured vars -*- C++ -*-=//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This checker detects blocks that capture uninitialized values.
//
//===----------------------------------------------------------------------===//

#include "ClangSACheckers.h"
#include "clang/AST/Attr.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;
using namespace ento;

namespace {
class UndefCapturedBlockVarChecker
  : public Checker< check::PostStmt<BlockExpr> > {
 mutable OwningPtr<BugType> BT;

public:
  void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
};
} // end anonymous namespace

static const DeclRefExpr *FindBlockDeclRefExpr(const Stmt *S,
                                               const VarDecl *VD) {
  if (const DeclRefExpr *BR = dyn_cast<DeclRefExpr>(S))
    if (BR->getDecl() == VD)
      return BR;

  for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
       I!=E; ++I)
    if (const Stmt *child = *I) {
      const DeclRefExpr *BR = FindBlockDeclRefExpr(child, VD);
      if (BR)
        return BR;
    }

  return NULL;
}

void
UndefCapturedBlockVarChecker::checkPostStmt(const BlockExpr *BE,
                                            CheckerContext &C) const {
  if (!BE->getBlockDecl()->hasCaptures())
    return;

  ProgramStateRef state = C.getState();
  const BlockDataRegion *R =
    cast<BlockDataRegion>(state->getSVal(BE,
                                         C.getLocationContext()).getAsRegion());

  BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
                                            E = R->referenced_vars_end();

  for (; I != E; ++I) {
    // This VarRegion is the region associated with the block; we need
    // the one associated with the encompassing context.
    const VarRegion *VR = *I;
    const VarDecl *VD = VR->getDecl();

    if (VD->getAttr<BlocksAttr>() || !VD->hasLocalStorage())
      continue;

    // Get the VarRegion associated with VD in the local stack frame.
    SVal VRVal = state->getSVal(I.getOriginalRegion());

    if (VRVal.isUndef())
      if (ExplodedNode *N = C.generateSink()) {
        if (!BT)
          BT.reset(new BuiltinBug("uninitialized variable captured by block"));

        // Generate a bug report.
        SmallString<128> buf;
        llvm::raw_svector_ostream os(buf);

        os << "Variable '" << VD->getName()
           << "' is uninitialized when captured by block";

        BugReport *R = new BugReport(*BT, os.str(), N);
        if (const Expr *Ex = FindBlockDeclRefExpr(BE->getBody(), VD))
          R->addRange(Ex->getSourceRange());
        R->addVisitor(new FindLastStoreBRVisitor(VRVal, VR));
        R->disablePathPruning();
        // need location of block
        C.emitReport(R);
      }
  }
}

void ento::registerUndefCapturedBlockVarChecker(CheckerManager &mgr) {
  mgr.registerChecker<UndefCapturedBlockVarChecker>();
}
<|endoftext|>


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

#include "ir.h"
#include "ir_hierarchical_visitor.h"

ir_hierarchical_visitor::ir_hierarchical_visitor()
{
   this->callback = NULL;
   this->data = NULL;
}

ir_visitor_status
ir_hierarchical_visitor::visit(ir_variable *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit(ir_constant *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit(ir_loop_jump *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit(ir_dereference_variable *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_loop *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_loop *ir)
{
   (void) ir;
   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_function_signature *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_function_signature *ir)
{
   (void) ir;
   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_function *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_function *ir)
{
   (void) ir;
   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_expression *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_expression *ir)
{
   (void) ir;
   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_texture *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_texture *ir)
{
   (void) ir;
   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_swizzle *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_swizzle *ir)
{
   (void) ir;
   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_dereference_array *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_dereference_array *ir)
{
   (void) ir;
   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_dereference_record *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_dereference_record *ir)
{
   (void) ir;
   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_assignment *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_assignment *ir)
{
   (void) ir;
   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_call *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_call *ir)
{
   (void) ir;
   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_return *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_return *ir)
{
   (void) ir;
   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_discard *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_discard *ir)
{
   (void) ir;
   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_if *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_if *ir)
{
   (void) ir;
   return visit_continue;
}

void
ir_hierarchical_visitor::run(exec_list *instructions)
{
   visit_list_elements(this, instructions);
}

void
visit_tree(ir_instruction *ir,
	   void (*callback)(class ir_instruction *ir, void *data),
	   void *data)
{
   ir_hierarchical_visitor v;

   v.callback = callback;
   v.data = data;

   ir->accept(&v);
}
<commit_msg>glsl: Fix uninitialized member in ir_hierarchical_vistor constructor.<commit_after>/*
 * Copyright © 2010 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include "ir.h"
#include "ir_hierarchical_visitor.h"

ir_hierarchical_visitor::ir_hierarchical_visitor()
{
   this->base_ir = NULL;
   this->callback = NULL;
   this->data = NULL;
}

ir_visitor_status
ir_hierarchical_visitor::visit(ir_variable *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit(ir_constant *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit(ir_loop_jump *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit(ir_dereference_variable *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_loop *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_loop *ir)
{
   (void) ir;
   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_function_signature *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_function_signature *ir)
{
   (void) ir;
   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_function *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_function *ir)
{
   (void) ir;
   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_expression *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_expression *ir)
{
   (void) ir;
   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_texture *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_texture *ir)
{
   (void) ir;
   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_swizzle *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_swizzle *ir)
{
   (void) ir;
   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_dereference_array *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_dereference_array *ir)
{
   (void) ir;
   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_dereference_record *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_dereference_record *ir)
{
   (void) ir;
   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_assignment *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_assignment *ir)
{
   (void) ir;
   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_call *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_call *ir)
{
   (void) ir;
   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_return *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_return *ir)
{
   (void) ir;
   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_discard *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_discard *ir)
{
   (void) ir;
   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_enter(ir_if *ir)
{
   if (this->callback != NULL)
      this->callback(ir, this->data);

   return visit_continue;
}

ir_visitor_status
ir_hierarchical_visitor::visit_leave(ir_if *ir)
{
   (void) ir;
   return visit_continue;
}

void
ir_hierarchical_visitor::run(exec_list *instructions)
{
   visit_list_elements(this, instructions);
}

void
visit_tree(ir_instruction *ir,
	   void (*callback)(class ir_instruction *ir, void *data),
	   void *data)
{
   ir_hierarchical_visitor v;

   v.callback = callback;
   v.data = data;

   ir->accept(&v);
}
<|endoftext|>


<commit_before>/*
	proxyImage.cpp
	Arsh Chauhan
	05/02/2016

	Source for class Proxyimage
*/

#include "proxyImage.hpp"

/*
	2 parameter constructor
	Pre: None
	Post: Creates new Proxyimage with filename fileName
*/
Proxyimage::Proxyimage(string fileName): fileName_(fileName)
{
	cout << "Proxy image created for file " << fileName << endl;
}

/*
	display
	Pre: None
	Post: Creates a bew RealImage with filename
	         fileName_ and sets realImage_ to that object
		  Calls RealImage's display function with realImage_
*/
void Proxyimage::display()
{
	realImage_ = Realimage(fileName_);
	realImage_.display();
}<commit_msg>Implemented method getFIles to return all files<commit_after>/*
	proxyImage.cpp
	Arsh Chauhan
	05/02/2016

	Source for class Proxyimage
*/

#include "proxyImage.hpp"

vector<string> Proxyimage::files_;

/*
	2 parameter constructor
	Pre: None
	Post: Creates new Proxyimage with filename fileName
*/
Proxyimage::Proxyimage(string fileName): fileName_(fileName)
{
	cout << "Proxy image created for file " << fileName_ << endl;
	files_.push_back(fileName_);
}

/*
	display
	Pre: None
	Post: Creates a bew RealImage with filename
	         fileName_ and sets realImage_ to that object
		  Calls RealImage's display function with realImage_
*/
void Proxyimage::display()
{
	realImage_ = Realimage(fileName_);
	realImage_.display();
}

vector<string> Proxyimage::getFiles()
{
	return files_;
}<|endoftext|>


<commit_before>#include <algorithm>
#include <set>
#include <list>
#include <iterator>

#include "otc/otcli.h"
#include "otc/tree_operations.h"
#include "otc/tree_iter.h"
using namespace otc;
using std::vector;
using std::unique_ptr;
using std::set;
using std::list;
using std::map;
using std::string;
using namespace otc;

typedef TreeMappedWithSplits Tree_t;

template <typename T>
std::ostream& operator<<(std::ostream& o, const std::set<T>& s)
{
  auto it = s.begin();
  o<<*it++;
  for(; it != s.end(); it++)
    o<<" "<<*it;
  return o;
}

template <typename T>
std::ostream& operator<<(std::ostream& o, const std::list<T>& s)
{
  auto it = s.begin();
  o<<*it++;
  for(; it != s.end(); it++)
    o<<" "<<*it;
  return o;
}

struct RSplit
{
  set<long> in;
  set<long> out;
  set<long> all;
  RSplit() = default;
  RSplit(const set<long>& i, const set<long>& a)
    :in(i),all(a)
  {
    out = set_difference_as_set(all,in);
    assert(in.size() + out.size() == all.size());
  }
};

std::ostream& operator<<(std::ostream& o, const RSplit& s)
{
  o<<s.in<<" | "<<s.out;
  return o;
}

/// Merge components c1 and c2 and return the component name that survived
long merge_components(long c1, long c2, map<long,long>& component, map<long,list<long>>& elements)
{
  if (elements[c2].size() > elements[c1].size())
    std::swap(c1,c2);

  for(long i:elements[c2])
    component[i] = c1;

  elements[c1].splice(elements[c1].begin(), elements[c2]);

  return c1;
}

bool empty_intersection(const set<long>& x, const set<long>& y)
{
  std::set<long>::const_iterator i = x.begin();
  std::set<long>::const_iterator j = y.begin();
  while (i != x.end() && j != y.end())
  {
    if (*i == *j)
      return false;
    else if (*i < *j)
      ++i;
    else
      ++j;
  }
  return true;
}

/// Construct a tree with all the splits mentioned, and return a null pointer if this is not possible
unique_ptr<Tree_t> BUILD(const std::set<long>& tips, const vector<RSplit>& splits)
{
  std::unique_ptr<Tree_t> tree(new Tree_t());
  tree->createRoot();

  // 1. First handle trees of size 1 and 2
  if (tips.size() == 1)
  {
    tree->getRoot()->setOttId(*tips.begin());
    return tree;
  }
  else if (tips.size() == 2)
  {
    auto Node1a = tree->createChild(tree->getRoot());
    auto Node1b = tree->createChild(tree->getRoot());
    auto it = tips.begin();
    Node1a->setOttId(*it++);
    Node1b->setOttId(*it++);
    return tree;
  }

  // 2. Initialize the mapping from elements to components
  map<long,long> component;      // element   -> component
  map<long,list<long>> elements; // component -> elements
  for(long i: tips)
  {
    component[i] = i;
    elements[i].push_back(i);
  }

  // 3. For each split, all the leaves in the include group must be in the same component
  for(const auto& split: splits)
  {
    long c1 = -1;
    for(long i: split.in)
    {
      long c2 = component[i];
      if (c1 != -1 and c1 != c2)
	merge_components(c1,c2,component,elements);
      c1 = component[i];
    }
  }

  // 4. If we can't subdivide the leaves in any way, then the splits are not consistent, so return failure
  long first = *tips.begin();
  if (elements[component[first]].size() == tips.size())
    return {};

  // 5. Create the set of tips in each connected component
  map<long,set<long>> subtips;
  for(long c: tips)
  {
    if (c != component[c]) continue;

    set<long>& s = subtips[c];
    for(long l: elements[c])
      s.insert(l);
  }

  // 6. Determine the splits that are not satisfied yet and go into each component
  map<long,vector<RSplit>> subsplits;
  for(const auto& split: splits)
  {
    long first = *split.in.begin();
    long c = component[first];

    // if none of the exclude group are in the component, then the split is satisfied by the top-level partition.
    if (empty_intersection(split.out, subtips[c])) continue;

    subsplits[c].push_back(split);
  }

  // 7. Recursively solve the sub-problems of the partition components
  for(const auto& x: subtips)
  {
    auto subtree = BUILD(x.second, subsplits[x.first]);
    if (not subtree) return {};

    tree->addSubtree(tree->getRoot(), *subtree);
  }

  return tree;
}

/// Run the BUILD algorithm on the first n splits
unique_ptr<Tree_t> BUILD(const std::set<long>& tips, const vector<RSplit>& splits, int n)
{
  vector<RSplit> splits2;
  for(int i=0;i<n;i++)
    splits2.push_back(splits[i]);
  return BUILD(tips,splits2);
}

/// Copy node names from taxonomy to tree based on ott ids, and copy the root name also
void add_names(unique_ptr<Tree_t>& tree, const unique_ptr<Tree_t>& taxonomy)
{
  map<long,string> names;

  // 1. Determine the names for each ottid
  for(auto nd: iter_post(*taxonomy))
    if (nd->isTip())
      names[nd->getOttId()] = nd->getName();

  // 2. Set the names of nodes based on their ottid
  for(auto nd: iter_post(*tree))
    if (nd->hasOttId())
      nd->setName( names[nd->getOttId()] );

  // 3. Name the root node too
  string rootname = taxonomy->getRoot()->getName();
  tree->getRoot()->setName(rootname);
}

/// Get the list of splits, and add them one at a time if they are consistent with previous splits
unique_ptr<Tree_t> combine(const vector<unique_ptr<Tree_t>>& trees)
{
  // Standardize names to 0..n-1 for this subproblem
  const auto& taxonomy = trees.back();
  auto all_leaves = taxonomy->getRoot()->getData().desIds;

  // 1. Find splits in order of input trees
  vector<RSplit> splits;
  for(const auto& tree: trees)
  {
    auto root = tree->getRoot();
    const auto leafTaxa = root->getData().desIds;

    for(const auto& leaf: set_difference_as_set(leafTaxa, all_leaves))
      throw OTCError()<<"OTT Id "<<leaf<<" not in taxonomy!";

    for(auto nd: iter_post_const(*tree))
    {
      const auto& descendants = nd->getData().desIds;
      RSplit split{descendants, leafTaxa};
      if (split.in.size()>1 and split.out.size())
      	splits.push_back(split);
    }
  }

  // 2. Add splits sequentially if they are consistent with previous splits.
  vector<RSplit> consistent;
  for(const auto& split: splits)
  {
    consistent.push_back(split);
    auto result = BUILD(all_leaves, consistent);
    if (not result)
    {
      consistent.pop_back();
      LOG(DEBUG)<<"Reject: "<<split<<"\n";
    }
    else
      LOG(DEBUG)<<"Keep:   "<<split<<"\n";
  }

  // 3. Construct final tree and add names
  auto tree = BUILD(all_leaves, consistent);
  add_names(tree, taxonomy);
  return tree;
}

bool handleRequireOttIds(OTCLI & otCLI, const std::string & arg)
{
  if (arg == "true" or arg == "yes" or arg == "True" or arg == "Yes")
    otCLI.getParsingRules().requireOttIds = true;
  else if (arg == "false" or arg == "no" or arg == "False" or arg == "no")
    otCLI.getParsingRules().requireOttIds = false;
  else
    return false;

  return true;
}

bool handlePruneUnrecognizedTips(OTCLI & otCLI, const std::string & arg)
{
  if (arg == "true" or arg == "yes" or arg == "True" or arg == "Yes")
    otCLI.getParsingRules().pruneUnrecognizedInputTips = true;
  else if (arg == "false" or arg == "no" or arg == "False" or arg == "no")
    otCLI.getParsingRules().pruneUnrecognizedInputTips = false;
  else
    return false;

  return true;
}

bool synthesize_taxonomy = false;

bool handleSynthesizeTaxonomy(OTCLI &, const std::string & arg)
{
  if (arg == "true" or "yes" or "True" or "Yes")
    synthesize_taxonomy = true;
  else if (arg == "false" or "no" or "False" or "no")
    synthesize_taxonomy = false;
  else
    return false;

  return true;
}

int main(int argc, char *argv[]) {
    OTCLI otCLI("otc-solve-subproblem",
                "takes at series of tree files. Each is treated as a subproblem.\n",
		"subproblem.tre");

    otCLI.addFlag('o',
		  "Require OTT ids.  Defaults to true",
		  handleRequireOttIds,
		  true);
    otCLI.addFlag('p',
		  "Prune unrecognized tips.  Defaults to false",
		  handlePruneUnrecognizedTips,
		  true);
    otCLI.addFlag('t',
		  "Synthesize unresolved taxonomy from all mentioned taxa.  Defaults to false",
		  handleSynthesizeTaxonomy,
		  true);

    vector<unique_ptr<Tree_t>> trees;
    auto get = [&trees](OTCLI &, unique_ptr<Tree_t> nt) {trees.push_back(std::move(nt)); return true;};

    if (argc < 2)
	throw OTCError("No subproblem provided!");

    // I think multiple subproblem files are essentially concatenated.
    // Is it possible to read a single subproblem from cin?
    if (treeProcessingMain<Tree_t>(otCLI, argc, argv, get, nullptr, 1))
      std::exit(1);

    // Add fake Ott Ids to tips and compute desIds
    if (not otCLI.getParsingRules().requireOttIds)
    {
      auto& taxonomy = trees.back();

      // 1. Compute mapping from name -> id
      long id = 1;
      map<string,long> name_to_id;
      for(auto nd: iter_pre(*taxonomy))
	if (nd->isTip())
	{
	  string name = nd->getName();
	  if (not name.size())
	    throw OTCError()<<"Taxonomy tip has no label or OTT id!";
	  auto it = name_to_id.find(name);
	  if (it != name_to_id.end())
	    throw OTCError()<<"Tip label '"<<name<<"' occurs twice in taxonomy!";
	  name_to_id[name] = id++;
	}

      // 2. Set ids
      for(auto& tree: trees)
	for(auto nd: iter_post(*tree))
	  if (nd->isTip())
	  {
	    string name = nd->getName();
	    if (not name.size())
	      throw OTCError()<<"Tip has no label or OTT id!";
	    auto it = name_to_id.find(name);
	    if (it == name_to_id.end())
	      throw OTCError()<<"Can't find label '"<<name<<"' in taxonomy!";
	    auto id = it->second;
	    nd->setOttId(id);
	  }

      // 3. Compute DesIds.
      for(auto& tree: trees)
	clearAndfillDesIdSets(*tree);
    }

    auto tree = combine(trees);

    writeTreeAsNewick(std::cout, *tree);
    std::cout<<"\n";
}
<commit_msg>Allow generating a taxonomy if one is not supplied.<commit_after>#include <algorithm>
#include <set>
#include <list>
#include <iterator>

#include "otc/otcli.h"
#include "otc/tree_operations.h"
#include "otc/tree_iter.h"
using namespace otc;
using std::vector;
using std::unique_ptr;
using std::set;
using std::list;
using std::map;
using std::string;
using namespace otc;

typedef TreeMappedWithSplits Tree_t;

template <typename T>
std::ostream& operator<<(std::ostream& o, const std::set<T>& s)
{
  auto it = s.begin();
  o<<*it++;
  for(; it != s.end(); it++)
    o<<" "<<*it;
  return o;
}

template <typename T>
std::ostream& operator<<(std::ostream& o, const std::list<T>& s)
{
  auto it = s.begin();
  o<<*it++;
  for(; it != s.end(); it++)
    o<<" "<<*it;
  return o;
}

struct RSplit
{
  set<long> in;
  set<long> out;
  set<long> all;
  RSplit() = default;
  RSplit(const set<long>& i, const set<long>& a)
    :in(i),all(a)
  {
    out = set_difference_as_set(all,in);
    assert(in.size() + out.size() == all.size());
  }
};

std::ostream& operator<<(std::ostream& o, const RSplit& s)
{
  o<<s.in<<" | "<<s.out;
  return o;
}

/// Merge components c1 and c2 and return the component name that survived
long merge_components(long c1, long c2, map<long,long>& component, map<long,list<long>>& elements)
{
  if (elements[c2].size() > elements[c1].size())
    std::swap(c1,c2);

  for(long i:elements[c2])
    component[i] = c1;

  elements[c1].splice(elements[c1].begin(), elements[c2]);

  return c1;
}

bool empty_intersection(const set<long>& x, const set<long>& y)
{
  std::set<long>::const_iterator i = x.begin();
  std::set<long>::const_iterator j = y.begin();
  while (i != x.end() && j != y.end())
  {
    if (*i == *j)
      return false;
    else if (*i < *j)
      ++i;
    else
      ++j;
  }
  return true;
}

/// Construct a tree with all the splits mentioned, and return a null pointer if this is not possible
unique_ptr<Tree_t> BUILD(const std::set<long>& tips, const vector<RSplit>& splits)
{
  std::unique_ptr<Tree_t> tree(new Tree_t());
  tree->createRoot();

  // 1. First handle trees of size 1 and 2
  if (tips.size() == 1)
  {
    tree->getRoot()->setOttId(*tips.begin());
    return tree;
  }
  else if (tips.size() == 2)
  {
    auto Node1a = tree->createChild(tree->getRoot());
    auto Node1b = tree->createChild(tree->getRoot());
    auto it = tips.begin();
    Node1a->setOttId(*it++);
    Node1b->setOttId(*it++);
    return tree;
  }

  // 2. Initialize the mapping from elements to components
  map<long,long> component;      // element   -> component
  map<long,list<long>> elements; // component -> elements
  for(long i: tips)
  {
    component[i] = i;
    elements[i].push_back(i);
  }

  // 3. For each split, all the leaves in the include group must be in the same component
  for(const auto& split: splits)
  {
    long c1 = -1;
    for(long i: split.in)
    {
      long c2 = component[i];
      if (c1 != -1 and c1 != c2)
	merge_components(c1,c2,component,elements);
      c1 = component[i];
    }
  }

  // 4. If we can't subdivide the leaves in any way, then the splits are not consistent, so return failure
  long first = *tips.begin();
  if (elements[component[first]].size() == tips.size())
    return {};

  // 5. Create the set of tips in each connected component
  map<long,set<long>> subtips;
  for(long c: tips)
  {
    if (c != component[c]) continue;

    set<long>& s = subtips[c];
    for(long l: elements[c])
      s.insert(l);
  }

  // 6. Determine the splits that are not satisfied yet and go into each component
  map<long,vector<RSplit>> subsplits;
  for(const auto& split: splits)
  {
    long first = *split.in.begin();
    long c = component[first];

    // if none of the exclude group are in the component, then the split is satisfied by the top-level partition.
    if (empty_intersection(split.out, subtips[c])) continue;

    subsplits[c].push_back(split);
  }

  // 7. Recursively solve the sub-problems of the partition components
  for(const auto& x: subtips)
  {
    auto subtree = BUILD(x.second, subsplits[x.first]);
    if (not subtree) return {};

    tree->addSubtree(tree->getRoot(), *subtree);
  }

  return tree;
}

/// Run the BUILD algorithm on the first n splits
unique_ptr<Tree_t> BUILD(const std::set<long>& tips, const vector<RSplit>& splits, int n)
{
  vector<RSplit> splits2;
  for(int i=0;i<n;i++)
    splits2.push_back(splits[i]);
  return BUILD(tips,splits2);
}

/// Copy node names from taxonomy to tree based on ott ids, and copy the root name also
void add_names(unique_ptr<Tree_t>& tree, const unique_ptr<Tree_t>& taxonomy)
{
  map<long,string> names;

  // 1. Determine the names for each ottid
  for(auto nd: iter_post(*taxonomy))
    if (nd->isTip())
      names[nd->getOttId()] = nd->getName();

  // 2. Set the names of nodes based on their ottid
  for(auto nd: iter_post(*tree))
    if (nd->hasOttId())
      nd->setName( names[nd->getOttId()] );

  // 3. Name the root node too
  string rootname = taxonomy->getRoot()->getName();
  tree->getRoot()->setName(rootname);
}

/// Get the list of splits, and add them one at a time if they are consistent with previous splits
unique_ptr<Tree_t> combine(const vector<unique_ptr<Tree_t>>& trees)
{
  // Standardize names to 0..n-1 for this subproblem
  const auto& taxonomy = trees.back();
  auto all_leaves = taxonomy->getRoot()->getData().desIds;

  // 1. Find splits in order of input trees
  vector<RSplit> splits;
  for(const auto& tree: trees)
  {
    auto root = tree->getRoot();
    const auto leafTaxa = root->getData().desIds;

    for(const auto& leaf: set_difference_as_set(leafTaxa, all_leaves))
      throw OTCError()<<"OTT Id "<<leaf<<" not in taxonomy!";

    for(auto nd: iter_post_const(*tree))
    {
      const auto& descendants = nd->getData().desIds;
      RSplit split{descendants, leafTaxa};
      if (split.in.size()>1 and split.out.size())
      	splits.push_back(split);
    }
  }

  // 2. Add splits sequentially if they are consistent with previous splits.
  vector<RSplit> consistent;
  for(const auto& split: splits)
  {
    consistent.push_back(split);
    auto result = BUILD(all_leaves, consistent);
    if (not result)
    {
      consistent.pop_back();
      LOG(DEBUG)<<"Reject: "<<split<<"\n";
    }
    else
      LOG(DEBUG)<<"Keep:   "<<split<<"\n";
  }

  // 3. Construct final tree and add names
  auto tree = BUILD(all_leaves, consistent);
  add_names(tree, taxonomy);
  return tree;
}

bool handleRequireOttIds(OTCLI & otCLI, const std::string & arg)
{
  if (arg == "true" or arg == "yes" or arg == "True" or arg == "Yes")
    otCLI.getParsingRules().requireOttIds = true;
  else if (arg == "false" or arg == "no" or arg == "False" or arg == "no")
    otCLI.getParsingRules().requireOttIds = false;
  else
    return false;

  return true;
}

bool handlePruneUnrecognizedTips(OTCLI & otCLI, const std::string & arg)
{
  if (arg == "true" or arg == "yes" or arg == "True" or arg == "Yes")
    otCLI.getParsingRules().pruneUnrecognizedInputTips = true;
  else if (arg == "false" or arg == "no" or arg == "False" or arg == "no")
    otCLI.getParsingRules().pruneUnrecognizedInputTips = false;
  else
    return false;

  return true;
}

bool synthesize_taxonomy = false;

bool handleSynthesizeTaxonomy(OTCLI &, const std::string & arg)
{
  if (arg == "true" or "yes" or "True" or "Yes")
    synthesize_taxonomy = true;
  else if (arg == "false" or "no" or "False" or "no")
    synthesize_taxonomy = false;
  else
    return false;

  return true;
}

unique_ptr<Tree_t> make_unresolved_tree(const vector<unique_ptr<Tree_t>>& trees, bool use_ids)
{
  std::unique_ptr<Tree_t> tree(new Tree_t());
  tree->createRoot();

  if (use_ids)
  {
    map<long,string> names;
    for(const auto& tree: trees)
      for(auto nd: iter_pre_const(*tree))
	if (nd->isTip())
	{
	  long id = nd->getOttId();
	  auto it = names.find(id);
	  if (it == names.end())
	    names[id] = nd->getName();
	}

    for(const auto& n: names)
    {
      auto node = tree->createChild(tree->getRoot());
      node->setOttId(n.first);
      node->setName(n.second);
    }
    clearAndfillDesIdSets(*tree);
  }
  else
  {
    set<string> names;
    for(const auto& tree: trees)
      for(auto nd: iter_pre_const(*tree))
	if (nd->isTip())
	  names.insert(nd->getName());

    for(const auto& n: names)
    {
      auto node = tree->createChild(tree->getRoot());
      node->setName(n);
    }
  }

  return tree;
}

string newick(const Tree_t &t)
{
  std::ostringstream s;
  writeTreeAsNewick(s, t);
  return s.str();
}

int main(int argc, char *argv[]) {
    OTCLI otCLI("otc-solve-subproblem",
                "takes at series of tree files. Each is treated as a subproblem.\n",
		"subproblem.tre");

    otCLI.addFlag('o',
		  "Require OTT ids.  Defaults to true",
		  handleRequireOttIds,
		  true);
    otCLI.addFlag('p',
		  "Prune unrecognized tips.  Defaults to false",
		  handlePruneUnrecognizedTips,
		  true);
    otCLI.addFlag('T',
		  "Synthesize unresolved taxonomy from all mentioned taxa.  Defaults to false",
		  handleSynthesizeTaxonomy,
		  false);

    vector<unique_ptr<Tree_t>> trees;
    auto get = [&trees](OTCLI &, unique_ptr<Tree_t> nt) {trees.push_back(std::move(nt)); return true;};

    if (argc < 2)
	throw OTCError("No subproblem provided!");

    // I think multiple subproblem files are essentially concatenated.
    // Is it possible to read a single subproblem from cin?
    if (treeProcessingMain<Tree_t>(otCLI, argc, argv, get, nullptr, 1))
      std::exit(1);

    bool requireOttIds = otCLI.getParsingRules().requireOttIds;
    if (synthesize_taxonomy)
    {
      trees.push_back(make_unresolved_tree(trees,requireOttIds));
      LOG(DEBUG)<<"taxonomy = "<<newick(*trees.back())<<"\n";
    }

    // Add fake Ott Ids to tips and compute desIds
    if (not requireOttIds)
    {
      auto& taxonomy = trees.back();

      // 1. Compute mapping from name -> id
      long id = 1;
      map<string,long> name_to_id;
      for(auto nd: iter_pre(*taxonomy))
	if (nd->isTip())
	{
	  string name = nd->getName();
	  if (not name.size())
	    throw OTCError()<<"Taxonomy tip has no label or OTT id!";
	  auto it = name_to_id.find(name);
	  if (it != name_to_id.end())
	    throw OTCError()<<"Tip label '"<<name<<"' occurs twice in taxonomy!";
	  name_to_id[name] = id++;
	}

      // 2. Set ids
      for(auto& tree: trees)
	for(auto nd: iter_post(*tree))
	  if (nd->isTip())
	  {
	    string name = nd->getName();
	    if (not name.size())
	      throw OTCError()<<"Tip has no label or OTT id!";
	    auto it = name_to_id.find(name);
	    if (it == name_to_id.end())
	      throw OTCError()<<"Can't find label '"<<name<<"' in taxonomy!";
	    auto id = it->second;
	    nd->setOttId(id);
	  }

      // 3. Compute DesIds.
      for(auto& tree: trees)
	clearAndfillDesIdSets(*tree);
    }

    auto tree = combine(trees);

    writeTreeAsNewick(std::cout, *tree);
    std::cout<<"\n";
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/hwpf/fapi2/include/ffdc.H $                        */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2011,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
/**
 *  @file ffdc.H
 *  @brief Defines the FirstFailureData class
 */

#ifndef FAPI2_FFDC_H_
#define FAPI2_FFDC_H_

#include <memory>
#include <hwp_return_codes.H>
#include <return_code_defs.H>
#include <plat_trace.H>
#include <error_info.H>
#include <target.H>

using fapi2::TARGET_TYPE_ALL;

namespace fapi2
{
///
/// @brief Check the type of a variable
///
/// This function can be called to check that a variable type is as expected
/// @note This mechanism will allow for cast ctor's which other static type
/// checking might not.
///
template<typename T>
inline
void checkType(const T&) {}

class ReturnCode;

///
/// @class FirstFailureData
///
/// This class provides storage and methods for creating and manipulating
/// FFDC.
/// It is not needed on all platforms - platforms which need this class have
/// specified this by forcing their fapi2::ReturnCode to be a subclass of
/// this class.
///
template< class R = fapi2::ReturnCode >
class FirstFailureData
{
    public:

        ///
        /// @brief Default constructor.
        /// @note We don't create our error info by default. It will be created
        /// when its needed in the setHwpError() method. Note that dereferencing
        /// the error info without first calling setHwpError() will create a
        //  problem.
        ///
        FirstFailureData(void):
            iv_info( nullptr ), iv_platDataPtr(nullptr)
        {}

        ///
        /// @brief Copy Constructor
        ///
        /// @param[in] i_right Reference to FirstFailureData to copy
        /// @note Generates default copy constructor - no deep pointer
        /// copies necessary.
        ///
        FirstFailureData(const FirstFailureData& i_right) = default;

        ///
        /// @brief Destructor
        ///
        ~FirstFailureData(void) = default;

        ///
        /// @brief Assignment Operator.
        ///
        /// @param[in] i_right Reference to FirstFailureData to assign from.
        /// @return Reference to 'this' FirstFailureData
        ///
        FirstFailureData& operator=(const FirstFailureData& i_right) = default;

        ///
        /// @brief Sets a HWP error. Sets the rcValue to the supplied value (from
        ///      the HwpFirstFailureData enumeration) and deletes any
        /// associated data.
        ///
        /// HWP code must call the FAPI_SET_HWP_ERROR macro rather than this
        /// function
        /// directly to generate an error so that any error information is
        /// automatically added to the FirstFailureData
        ///
        /// @param[in] i_rcValue Error value to set
        ///
        inline void _setHwpError(const fapi2::HwpReturnCode i_rcValue)
        {
            FAPI_ERR("_setHwpError: Creating HWP error 0x%x", i_rcValue);
            static_cast<R*>(this)->operator=(i_rcValue);

            // Forget about any associated data (this is a new error)
            iv_info.reset(new ErrorInfo());
        }

        ///
        /// @return void *. Pointer to error info data. If NULL then no data
        ///
        void* getData(void) const;

        ///
        /// @brief Get a pointer to any error info and release ownership from
        ///      FirstFailureData. The caller is responsible for deletion.
        ///
        /// This is called by PLAT. The expected use-case is to retrieve a
        /// platform error log.
        ///
        /// @return void*. Pointer to any Error data. If NULL then no data
        ///
        inline void* releaseData(void)
        {
            void* l_pData = iv_info;
            iv_info = NULL;
            return l_pData;
        }

        ///
        /// @brief Add ErrorInfo
        ///
        /// This is called by the FAPI_SET_HWP_ERROR and macro to add ErrorInfo
        /// to the FirstFailureData when a HWP generates an error. The function
        /// is designed to add all the ErrorInfo at once rather than the
        /// FAPI_SET_HWP_ERROR macro making multiple function calls to add each
        /// piece of ErrorInfo individually in order to minimize code size
        ///
        /// @param[in] i_pObjects Pointer to array of const pointers to const
        ///     objects that are referred to by ErrorInfoEntry objects
        /// @param[in] i_pEntries Pointer to array of ErrorInfoEntry objects
        ///     defining the ErrorInfo that needs to be added
        /// @param[in] i_count    Number of ErrorInfoEntry entries
        ///
        void addErrorInfo(const void* const* i_pObjects,
                          const ErrorInfoEntry* i_pEntries,
                          const uint8_t i_count);

        ///
        /// @brief Get a pointer to any ErrorInfo
        ///
        /// This is called by PLAT to find information about an error
        ///
        /// @return ErrorInfo *. Pointer to any ErrorInfo. If NULL then no info
        ///
        inline const fapi2::ErrorInfo* getErrorInfo(void) const
        {
            return iv_info.get();
        }

        ///
        /// @brief Forgets about any associated data (PlatData and ErrorInfo)
        ///
        /// If this is the only FirstFailureData pointing to the data then the
        /// data is deleted
        ///
        inline void forgetData(void)
        {
            iv_info = nullptr;
        }

        ///
        /// @brief Returns the platform data pointer value to the caller.
        ///
        inline void* getPlatDataPtr()
        {
            return iv_platDataPtr;
        };

        ///
        /// @brief Sets objects platform data pointer to the passed in value.
        ///
        ///
        inline void  setPlatDataPtr( void* i_ptr )
        {
            static_cast<R*>(this)->operator=(FAPI2_RC_PLAT_ERR_SEE_DATA);
            iv_platDataPtr = i_ptr;
        };

    private:

        // Pointer to the error info
        std::shared_ptr<ErrorInfo> iv_info;

        // free format data, to be used by the platform
        void*    iv_platDataPtr;
};

}
#endif // FAPI2_FFDC_H_
<commit_msg>Add new addErrorInfo method to enable collectFfdc and collectRegFfdc<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/hwpf/fapi2/include/ffdc.H $                        */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2011,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
/**
 *  @file ffdc.H
 *  @brief Defines the FirstFailureData class
 */

#ifndef FAPI2_FFDC_H_
#define FAPI2_FFDC_H_

#include <memory>
#include <hwp_return_codes.H>
#include <return_code_defs.H>
#include <plat_trace.H>
#include <error_info.H>
#include <target.H>

using fapi2::TARGET_TYPE_ALL;

namespace fapi2
{
///
/// @brief Check the type of a variable
///
/// This function can be called to check that a variable type is as expected
/// @note This mechanism will allow for cast ctor's which other static type
/// checking might not.
///
template<typename T>
inline
void checkType(const T&) {}

class ReturnCode;

///
/// @class FirstFailureData
///
/// This class provides storage and methods for creating and manipulating
/// FFDC.
/// It is not needed on all platforms - platforms which need this class have
/// specified this by forcing their fapi2::ReturnCode to be a subclass of
/// this class.
///
template< class R = fapi2::ReturnCode >
class FirstFailureData
{
    public:

        ///
        /// @brief Default constructor.
        /// @note We don't create our error info by default. It will be created
        /// when its needed in the setHwpError() method. Note that dereferencing
        /// the error info without first calling setHwpError() will create a
        //  problem.
        ///
        FirstFailureData(void):
            iv_info( nullptr ), iv_platDataPtr(nullptr)
        {}

        ///
        /// @brief Copy Constructor
        ///
        /// @param[in] i_right Reference to FirstFailureData to copy
        /// @note Generates default copy constructor - no deep pointer
        /// copies necessary.
        ///
        FirstFailureData(const FirstFailureData& i_right) = default;

        ///
        /// @brief Destructor
        ///
        ~FirstFailureData(void) = default;

        ///
        /// @brief Assignment Operator.
        ///
        /// @param[in] i_right Reference to FirstFailureData to assign from.
        /// @return Reference to 'this' FirstFailureData
        ///
        FirstFailureData& operator=(const FirstFailureData& i_right) = default;

        ///
        /// @brief Sets a HWP error. Sets the rcValue to the supplied value (from
        ///      the HwpFirstFailureData enumeration) and deletes any
        /// associated data.
        ///
        /// HWP code must call the FAPI_SET_HWP_ERROR macro rather than this
        /// function
        /// directly to generate an error so that any error information is
        /// automatically added to the FirstFailureData
        ///
        /// @param[in] i_rcValue Error value to set
        ///
        inline void _setHwpError(const fapi2::HwpReturnCode i_rcValue)
        {
            FAPI_ERR("_setHwpError: Creating HWP error 0x%x", i_rcValue);
            static_cast<R*>(this)->operator=(i_rcValue);

            // Forget about any associated data (this is a new error)
            iv_info.reset(new ErrorInfo());
        }

        ///
        /// @return void *. Pointer to error info data. If NULL then no data
        ///
        void* getData(void) const;

        ///
        /// @brief Get a pointer to any error info and release ownership from
        ///      FirstFailureData. The caller is responsible for deletion.
        ///
        /// This is called by PLAT. The expected use-case is to retrieve a
        /// platform error log.
        ///
        /// @return void*. Pointer to any Error data. If NULL then no data
        ///
        inline void* releaseData(void)
        {
            void* l_pData = iv_info;
            iv_info = NULL;
            return l_pData;
        }

        ///
        /// @brief Add ErrorInfo
        ///
        /// This is called by the FAPI_SET_HWP_ERROR and macro to add ErrorInfo
        /// to the FirstFailureData when a HWP generates an error. The function
        /// is designed to add all the ErrorInfo at once rather than the
        /// FAPI_SET_HWP_ERROR macro making multiple function calls to add each
        /// piece of ErrorInfo individually in order to minimize code size
        ///
        /// @param[in] i_pObjects Pointer to array of const pointers to const
        ///     objects that are referred to by ErrorInfoEntry objects
        /// @param[in] i_pEntries Pointer to array of ErrorInfoEntry objects
        ///     defining the ErrorInfo that needs to be added
        /// @param[in] i_count    Number of ErrorInfoEntry entries
        ///
        void addErrorInfo(const void* const* i_pObjects,
                          const ErrorInfoEntry* i_pEntries,
                          const uint8_t i_count);

        ///
        /// @brief Add ErrorInfo
        ///
        /// This is called by the collectFfdc and collectRegFfdc functions
        /// following the call to actually collect the ffdc data, the ffdc
        /// collection functions return a vector of shared pointers to the
        /// ErrorInfoFfdc objects
        ///
        /// @param[in] i_errorInfo - vector of shared pointers to
        ///                          errorInfoFfdc objects
        ///
        inline void addErrorInfo(std::vector<std::shared_ptr<ErrorInfoFfdc>>& i_errorInfo)
        {
            for( auto p : i_errorInfo )
            {
                iv_info->iv_ffdcs.push_back(p);
            }
        };

        ///

        ///
        /// @brief Get a pointer to any ErrorInfo
        ///
        /// This is called by PLAT to find information about an error
        ///
        /// @return ErrorInfo *. Pointer to any ErrorInfo. If NULL then no info
        ///
        inline const fapi2::ErrorInfo* getErrorInfo(void) const
        {
            return iv_info.get();
        }

        ///
        /// @brief Forgets about any associated data (PlatData and ErrorInfo)
        ///
        /// If this is the only FirstFailureData pointing to the data then the
        /// data is deleted
        ///
        inline void forgetData(void)
        {
            iv_info = nullptr;
        }

        ///
        /// @brief Returns the platform data pointer value to the caller.
        ///
        inline void* getPlatDataPtr()
        {
            return iv_platDataPtr;
        };

        ///
        /// @brief Sets objects platform data pointer to the passed in value.
        ///
        ///
        inline void  setPlatDataPtr( void* i_ptr )
        {
            static_cast<R*>(this)->operator=(FAPI2_RC_PLAT_ERR_SEE_DATA);
            iv_platDataPtr = i_ptr;
        };

    private:

        // Pointer to the error info
        std::shared_ptr<ErrorInfo> iv_info;

        // free format data, to be used by the platform
        void*    iv_platDataPtr;
};

}
#endif // FAPI2_FFDC_H_
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/hwpf/fapi2/include/ffdc.H $                        */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2011,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
/**
 *  @file ffdc.H
 *  @brief Defines the FirstFailureData class
 */

#ifndef FAPI2_FFDC_H_
#define FAPI2_FFDC_H_

#include <memory>
#include <hwp_return_codes.H>
#include <plat_trace.H>
#include <error_info.H>
#include <target.H>

using fapi2::TARGET_TYPE_ALL;

namespace fapi2
{
///
/// @brief Check the type of a variable
///
/// This function can be called to check that a variable type is as expected
/// @note This mechanism will allow for cast ctor's which other static type
/// checking might not.
///
template<typename T>
inline
void checkType(const T&) {}

class ReturnCode;

///
/// @class FirstFailureData
///
/// This class provides storage and methods for creating and manipulating
/// FFDC.
/// It is not needed on all platforms - platforms which need this class have
/// specified this by forcing their fapi2::ReturnCode to be a subclass of
/// this class.
///
template< class R = fapi2::ReturnCode >
class FirstFailureData
{
    public:

        ///
        /// @brief Default constructor.
        /// @note We don't create our error info by default. It will be created
        /// when its needed in the setHwpError() method. Note that dereferencing
        /// the error info without first calling setHwpError() will create a
        //  problem.
        ///
        FirstFailureData(void):
            iv_info( nullptr ), iv_platDataPtr(nullptr)
        {}

        ///
        /// @brief Copy Constructor
        ///
        /// @param[in] i_right Reference to FirstFailureData to copy
        /// @note Generates default copy constructor - no deep pointer
        /// copies necessary.
        ///
        FirstFailureData(const FirstFailureData& i_right) = default;

        ///
        /// @brief Destructor
        ///
        ~FirstFailureData(void) = default;

        ///
        /// @brief Assignment Operator.
        ///
        /// @param[in] i_right Reference to FirstFailureData to assign from.
        /// @return Reference to 'this' FirstFailureData
        ///
        FirstFailureData& operator=(const FirstFailureData& i_right) = default;

        ///
        /// @brief Sets a HWP error. Sets the rcValue to the supplied value (from
        ///      the HwpFirstFailureData enumeration) and deletes any
        /// associated data.
        ///
        /// HWP code must call the FAPI_SET_HWP_ERROR macro rather than this
        /// function
        /// directly to generate an error so that any error information is
        /// automatically added to the FirstFailureData
        ///
        /// @param[in] i_rcValue Error value to set
        ///
        inline void _setHwpError(const fapi2::HwpReturnCode i_rcValue)
        {
            FAPI_ERR("_setHwpError: Creating HWP error 0x%x", i_rcValue);
            static_cast<R*>(this)->operator=(i_rcValue);

            // Forget about any associated data (this is a new error)
            iv_info.reset(new ErrorInfo());
        }

        ///
        /// @return void *. Pointer to error info data. If NULL then no data
        ///
        void* getData(void) const;

        ///
        /// @brief Get a pointer to any error info and release ownership from
        ///      FirstFailureData. The caller is responsible for deletion.
        ///
        /// This is called by PLAT. The expected use-case is to retrieve a
        /// platform error log.
        ///
        /// @return void*. Pointer to any Error data. If NULL then no data
        ///
        inline void* releaseData(void)
        {
            void* l_pData = iv_info;
            iv_info = NULL;
            return l_pData;
        }

        ///
        /// @brief Add ErrorInfo
        ///
        /// This is called by the FAPI_SET_HWP_ERROR and macro to add ErrorInfo
        /// to the FirstFailureData when a HWP generates an error. The function
        /// is designed to add all the ErrorInfo at once rather than the
        /// FAPI_SET_HWP_ERROR macro making multiple function calls to add each
        /// piece of ErrorInfo individually in order to minimize code size
        ///
        /// @param[in] i_pObjects Pointer to array of const pointers to const
        ///     objects that are referred to by ErrorInfoEntry objects
        /// @param[in] i_pEntries Pointer to array of ErrorInfoEntry objects
        ///     defining the ErrorInfo that needs to be added
        /// @param[in] i_count    Number of ErrorInfoEntry entries
        ///
        void addErrorInfo(const void* const* i_pObjects,
                          const ErrorInfoEntry* i_pEntries,
                          const uint8_t i_count);

        ///
        /// @brief Get a pointer to any ErrorInfo
        ///
        /// This is called by PLAT to find information about an error
        ///
        /// @return ErrorInfo *. Pointer to any ErrorInfo. If NULL then no info
        ///
        inline const fapi2::ErrorInfo* getErrorInfo(void) const
        {
            return iv_info.get();
        }

        ///
        /// @brief Forgets about any associated data (PlatData and ErrorInfo)
        ///
        /// If this is the only FirstFailureData pointing to the data then the
        /// data is deleted
        ///
        inline void forgetData(void)
        {
            iv_info = nullptr;
        }

        ///
        /// @brief Returns the platform data pointer value to the caller.
        ///
        inline void* getPlatDataPtr()
        {
            return iv_platDataPtr;
        };

        ///
        /// @brief Sets objects platform data pointer to the passed in value.
        ///
        ///
        inline void  setPlatDataPtr( void* i_ptr )
        {
            iv_platDataPtr = i_ptr;
        };

    private:

        // Pointer to the error info
        std::shared_ptr<ErrorInfo> iv_info;

        // free format data, to be used by the platform
        void*    iv_platDataPtr;
};

}
#endif // FAPI2_FFDC_H_
<commit_msg>Add mcbist L2 function<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/hwpf/fapi2/include/ffdc.H $                        */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2011,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
/**
 *  @file ffdc.H
 *  @brief Defines the FirstFailureData class
 */

#ifndef FAPI2_FFDC_H_
#define FAPI2_FFDC_H_

#include <memory>
#include <hwp_return_codes.H>
#include <plat_trace.H>
#include <error_info.H>
#include <target.H>

using fapi2::TARGET_TYPE_ALL;

namespace fapi2
{
///
/// @brief Check the type of a variable
///
/// This function can be called to check that a variable type is as expected
/// @note This mechanism will allow for cast ctor's which other static type
/// checking might not.
///
template<typename T>
inline
void checkType(const T&) {}

class ReturnCode;

///
/// @class FirstFailureData
///
/// This class provides storage and methods for creating and manipulating
/// FFDC.
/// It is not needed on all platforms - platforms which need this class have
/// specified this by forcing their fapi2::ReturnCode to be a subclass of
/// this class.
///
template< class R = fapi2::ReturnCode >
class FirstFailureData
{
    public:

        ///
        /// @brief Default constructor.
        /// @note We don't create our error info by default. It will be created
        /// when its needed in the setHwpError() method. Note that dereferencing
        /// the error info without first calling setHwpError() will create a
        //  problem.
        ///
        FirstFailureData(void):
            iv_info( nullptr )
//            iv_info( nullptr ), iv_platDataPtr(nullptr)
        {}

        ///
        /// @brief Copy Constructor
        ///
        /// @param[in] i_right Reference to FirstFailureData to copy
        /// @note Generates default copy constructor - no deep pointer
        /// copies necessary.
        ///
        FirstFailureData(const FirstFailureData& i_right) = default;

        ///
        /// @brief Destructor
        ///
        ~FirstFailureData(void) = default;

        ///
        /// @brief Assignment Operator.
        ///
        /// @param[in] i_right Reference to FirstFailureData to assign from.
        /// @return Reference to 'this' FirstFailureData
        ///
        FirstFailureData& operator=(const FirstFailureData& i_right) = default;

        ///
        /// @brief Sets a HWP error. Sets the rcValue to the supplied value (from
        ///      the HwpFirstFailureData enumeration) and deletes any
        /// associated data.
        ///
        /// HWP code must call the FAPI_SET_HWP_ERROR macro rather than this
        /// function
        /// directly to generate an error so that any error information is
        /// automatically added to the FirstFailureData
        ///
        /// @param[in] i_rcValue Error value to set
        ///
        inline void _setHwpError(const fapi2::HwpReturnCode i_rcValue)
        {
            FAPI_ERR("_setHwpError: Creating HWP error 0x%x", i_rcValue);
            static_cast<R*>(this)->operator=(i_rcValue);

            // Forget about any associated data (this is a new error)
            iv_info.reset(new ErrorInfo());
        }

        ///
        /// @return void *. Pointer to error info data. If NULL then no data
        ///
        void* getData(void) const;

        ///
        /// @brief Get a pointer to any error info and release ownership from
        ///      FirstFailureData. The caller is responsible for deletion.
        ///
        /// This is called by PLAT. The expected use-case is to retrieve a
        /// platform error log.
        ///
        /// @return void*. Pointer to any Error data. If NULL then no data
        ///
        inline void* releaseData(void)
        {
            void* l_pData = iv_info;
            iv_info = NULL;
            return l_pData;
        }

        ///
        /// @brief Add ErrorInfo
        ///
        /// This is called by the FAPI_SET_HWP_ERROR and macro to add ErrorInfo
        /// to the FirstFailureData when a HWP generates an error. The function
        /// is designed to add all the ErrorInfo at once rather than the
        /// FAPI_SET_HWP_ERROR macro making multiple function calls to add each
        /// piece of ErrorInfo individually in order to minimize code size
        ///
        /// @param[in] i_pObjects Pointer to array of const pointers to const
        ///     objects that are referred to by ErrorInfoEntry objects
        /// @param[in] i_pEntries Pointer to array of ErrorInfoEntry objects
        ///     defining the ErrorInfo that needs to be added
        /// @param[in] i_count    Number of ErrorInfoEntry entries
        ///
        void addErrorInfo(const void* const* i_pObjects,
                          const ErrorInfoEntry* i_pEntries,
                          const uint8_t i_count);

        ///
        /// @brief Get a pointer to any ErrorInfo
        ///
        /// This is called by PLAT to find information about an error
        ///
        /// @return ErrorInfo *. Pointer to any ErrorInfo. If NULL then no info
        ///
        inline const fapi2::ErrorInfo* getErrorInfo(void) const
        {
            return iv_info.get();
        }

        ///
        /// @brief Forgets about any associated data (PlatData and ErrorInfo)
        ///
        /// If this is the only FirstFailureData pointing to the data then the
        /// data is deleted
        ///
        inline void forgetData(void)
        {
            iv_info = nullptr;
        }
#if 0
        ///
        /// @brief Returns the platform data pointer value to the caller.
        ///
        inline void* getPlatDataPtr()
        {
            return iv_platDataPtr;
        };

        ///
        /// @brief Sets objects platform data pointer to the passed in value.
        ///
        ///
        inline void  setPlatDataPtr( void* i_ptr )
        {
            iv_platDataPtr = i_ptr;
        };
#endif
    private:

        // Pointer to the error info
        std::shared_ptr<ErrorInfo> iv_info;

        // free format data, to be used by the platform
//        void*    iv_platDataPtr;
};

}
#endif // FAPI2_FFDC_H_
<|endoftext|>


<commit_before>#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <netdb.h>
#include <errno.h>
#include <stdlib.h>

#include "NetworkDetect.h"

INetworkDetection* NetworkDetectionFactory::createNetworkDetection() {
    return new CNetworkDetection();
}

void CNetworkDetection::Cleanup()
{
	stop(1000);

}

void CNetworkDetection::Startup()
{
}

void CNetworkDetection::CheckConnectivity()
{
    bool bConnectSuccessful = false;

    struct addrinfo hints, *result = NULL, *ptr = NULL;
	int sockfd = -1;
    memset(&hints,0,sizeof(hints));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;
	char szPortAsString[5 + 1];
    snprintf(szPortAsString,5,"%d",m_iPort);
	char* szHost = new char[m_szHost.length() + 1];
	memset(szHost, 0, m_szHost.length() + 1);
	strcpy(szHost, m_szHost.c_str());
	int iResult = getaddrinfo(szHost, szPortAsString, &hints, &result);
	if (iResult != 0)
    {
		//  Log the Fact that we can't get the addr info
        int iErr = errno;
		m_szLastError = "Attempted to resolve hostname to connect to but did not succeed, return value (" + itos(iResult) +
        "), last error (" + itos(iErr) + ")";
		LOG(INFO) + m_szLastError;
	}
	else
	{
		ptr=result;
		sockfd = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);

		if (sockfd == -1)
		{
            int iErr = errno;
			m_szLastError = "Unable to create communications socket, last error was " + itos(iErr);
			LOG(INFO) + m_szLastError;
		}
		else
		{
			int iNonBlockRes = fcntl(sockfd, F_SETFL, O_NONBLOCK);
			if (iNonBlockRes == -1)
			{
				m_szLastError = "Error setting socket into Non Blocking mode";
				LOG(INFO) + m_szLastError;
			}
			else
			{
				int iConnectSuccess = connect(sockfd, ptr->ai_addr, ptr->ai_addrlen);
				if (!(iConnectSuccess == -1 && errno == EINPROGRESS))
				{
					m_szLastError = "Socket Operation unexpectedly blocked, are you connected to a PC?";
					LOG(WARNING) + m_szLastError;
				}
				else
				{
					fd_set WriteFDs;
					FD_ZERO(&WriteFDs);
					FD_SET(sockfd, &WriteFDs);
                    timeval to = m_connectionTimeout;
					int iSelectReturnVal = select(sockfd+1, 0, &WriteFDs, 0, &to);
					if (iSelectReturnVal > 0)
					{
						//  We have a socket to connect to
						bConnectSuccessful = true;
					}
					else if (iSelectReturnVal == 0)
					{
						m_szLastError = "Unable to connect to specified host " + m_szHost + " on port " + itos(m_iPort);
						LOG(INFO) + m_szLastError;
					}
					else
					{
						//  Some form of error occured
                        int iErr = errno;
						m_szLastError = "Unable to connect to specified host, last error was " + itos(iErr);
						LOG(INFO) + m_szLastError;
					}
				}
			}
			close(sockfd);
			sockfd = -1;
		}
	}
	delete[] szHost;
    if (result != 0) {
        freeaddrinfo(result);
    }
	if (bConnectSuccessful)
	{
		if (m_NetworkState != NETWORK_CONNECTED)
		{
			m_NetworkState = NETWORK_CONNECTED;
			rho::Hashtable<rho::String, rho::String> detectedCallbackData;
			detectedCallbackData.put("connectionInformation", "Connected");
			detectedCallbackData.put("failureMessage", "Connected");
			m_pDetectCallback.set(detectedCallbackData);
		}
	}
	else
	{
		//  We are not connected
		if (m_NetworkState != NETWORK_DISCONNECTED)
		{
			m_NetworkState = NETWORK_DISCONNECTED;
			rho::Hashtable<rho::String, rho::String> detectedCallbackData;
			detectedCallbackData.put("connectionInformation", "Disconnected");
			detectedCallbackData.put("failureMessage", m_szLastError);
			m_pDetectCallback.set(detectedCallbackData);
		}
	}

}

<commit_msg>Update CNetworkDetect.cpp<commit_after>#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <netdb.h>
#include <errno.h>
#include <stdlib.h>

#include "NetworkDetect.h"

INetworkDetection* NetworkDetectionFactory::createNetworkDetection() {
    return new CNetworkDetection();
}

void CNetworkDetection::Cleanup()
{
	stop(1000);

}

void CNetworkDetection::Startup()
{
}

bool CNetworkDetection::CheckConnectivity()
{
    bool bConnectSuccessful = false;

    struct addrinfo hints, *result = NULL, *ptr = NULL;
	int sockfd = -1;
    memset(&hints,0,sizeof(hints));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;
	char szPortAsString[5 + 1];
    snprintf(szPortAsString,5,"%d",m_iPort);
	char* szHost = new char[m_szHost.length() + 1];
	memset(szHost, 0, m_szHost.length() + 1);
	strcpy(szHost, m_szHost.c_str());
	int iResult = getaddrinfo(szHost, szPortAsString, &hints, &result);
	if (iResult != 0)
    {
		//  Log the Fact that we can't get the addr info
        int iErr = errno;
		m_szLastError = "Attempted to resolve hostname to connect to but did not succeed, return value (" + itos(iResult) +
        "), last error (" + itos(iErr) + ")";
		LOG(INFO) + m_szLastError;
	}
	else
	{
		ptr=result;
		sockfd = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);

		if (sockfd == -1)
		{
            int iErr = errno;
			m_szLastError = "Unable to create communications socket, last error was " + itos(iErr);
			LOG(INFO) + m_szLastError;
		}
		else
		{
			int iNonBlockRes = fcntl(sockfd, F_SETFL, O_NONBLOCK);
			if (iNonBlockRes == -1)
			{
				m_szLastError = "Error setting socket into Non Blocking mode";
				LOG(INFO) + m_szLastError;
			}
			else
			{
				int iConnectSuccess = connect(sockfd, ptr->ai_addr, ptr->ai_addrlen);
				if (!(iConnectSuccess == -1 && errno == EINPROGRESS))
				{
					m_szLastError = "Socket Operation unexpectedly blocked, are you connected to a PC?";
					LOG(WARNING) + m_szLastError;
				}
				else
				{
					fd_set WriteFDs;
					FD_ZERO(&WriteFDs);
					FD_SET(sockfd, &WriteFDs);
                    timeval to = m_connectionTimeout;
					int iSelectReturnVal = select(sockfd+1, 0, &WriteFDs, 0, &to);
					if (iSelectReturnVal > 0)
					{
						//  We have a socket to connect to
						bConnectSuccessful = true;
					}
					else if (iSelectReturnVal == 0)
					{
						m_szLastError = "Unable to connect to specified host " + m_szHost + " on port " + itos(m_iPort);
						LOG(INFO) + m_szLastError;
					}
					else
					{
						//  Some form of error occured
                        int iErr = errno;
						m_szLastError = "Unable to connect to specified host, last error was " + itos(iErr);
						LOG(INFO) + m_szLastError;
					}
				}
			}
			close(sockfd);
			sockfd = -1;
		}
	}
	delete[] szHost;
    if (result != 0) {
        freeaddrinfo(result);
    }
	if (bConnectSuccessful)
	{
		if (m_NetworkState != NETWORK_CONNECTED)
		{
			m_NetworkState = NETWORK_CONNECTED;
			rho::Hashtable<rho::String, rho::String> detectedCallbackData;
			detectedCallbackData.put("connectionInformation", "Connected");
			detectedCallbackData.put("failureMessage", "Connected");
			m_pDetectCallback.set(detectedCallbackData);
		}
	}
	else
	{
		//  We are not connected
		if (m_NetworkState != NETWORK_DISCONNECTED)
		{
			m_NetworkState = NETWORK_DISCONNECTED;
			rho::Hashtable<rho::String, rho::String> detectedCallbackData;
			detectedCallbackData.put("connectionInformation", "Disconnected");
			detectedCallbackData.put("failureMessage", m_szLastError);
			m_pDetectCallback.set(detectedCallbackData);
		}
	}
	return bConnectSuccessful;

}

<|endoftext|>