<commit_before>/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.

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

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

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

// Native XLA implementations of simple binary Ops

#include "tensorflow/compiler/tf2xla/kernels/cwise_ops.h"
#include "tensorflow/compiler/tf2xla/lib/broadcast.h"
#include "tensorflow/compiler/tf2xla/shape_util.h"
#include "tensorflow/compiler/tf2xla/xla_helpers.h"
#include "tensorflow/compiler/tf2xla/xla_op_registry.h"
#include "tensorflow/compiler/xla/client/client_library.h"
#include "tensorflow/compiler/xla/client/lib/constants.h"
#include "tensorflow/compiler/xla/client/lib/math.h"
#include "tensorflow/compiler/xla/client/xla_builder.h"
#include "tensorflow/compiler/xla/primitive_util.h"
#include "tensorflow/compiler/xla/xla_data.pb.h"
#include "tensorflow/core/framework/kernel_def_builder.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/types.h"

namespace tensorflow {
namespace {

// A subclass of a XlaBinaryOp must build the computation that
// describes the (tensor,tensor)->tensor function to apply to each element of
// the input.
#define XLA_MAKE_BINARY(NAME, HLO)                                       \
  class NAME##Op : public XlaBinaryOp {                                  \
   public:                                                               \
    explicit NAME##Op(OpKernelConstruction* ctx) : XlaBinaryOp(ctx) {}   \
    xla::XlaOp Computation(                                              \
        XlaOpKernelContext* ctx, const xla::XlaOp& lhs,                  \
        const absl::Span<const int64>& lhs_shape, const xla::XlaOp& rhs, \
        const absl::Span<const int64>& rhs_shape,                        \
        const BCast& broadcast_helper,                                   \
        const std::vector<int64>& extend_dimensions) override {          \
      xla::XlaBuilder* b = ctx->builder();                               \
      (void)b;                                                           \
      (void)lhs_shape;                                                   \
      (void)rhs_shape;                                                   \
      (void)extend_dimensions;                                           \
      return HLO;                                                        \
    }                                                                    \
  };                                                                     \
  REGISTER_XLA_OP(Name(#NAME), NAME##Op)

XLA_MAKE_BINARY(Add, xla::Add(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(AddV2, xla::Add(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(Sub, xla::Sub(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(Mul, xla::Mul(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(Div, xla::Div(lhs, rhs, extend_dimensions));

XLA_MAKE_BINARY(Atan2, xla::Atan2(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(Complex, xla::Complex(lhs, rhs, extend_dimensions));

// Implementation of DivNoNan. Pseudo-code:
// if (y == 0) {
//   return 0
// } else {
//   return x / y;
// }
static xla::XlaOp DivNoNanImpl(xla::XlaBuilder* b, DataType dtype, xla::XlaOp x,
                               xla::XlaOp y, const BCast& broadcast_helper) {
  std::tie(x, y) = XlaBinaryOp::Broadcast(x, y, broadcast_helper);
  auto zero = XlaHelpers::Zero(b, dtype);
  auto y_equals_0 = xla::Eq(y, zero);
  auto zeros = xla::ZerosLike(x);
  auto result = xla::Select(y_equals_0, zeros, xla::Div(x, y));
  return result;
}
XLA_MAKE_BINARY(DivNoNan,
                DivNoNanImpl(b, input_type(0), lhs, rhs, broadcast_helper));

// Implementation of MulNoNan. Pseudo-code:
// if (y == 0) {
//   return 0
// } else {
//   return x * y;
// }
static xla::XlaOp MulNoNanImpl(xla::XlaBuilder* b, DataType dtype, xla::XlaOp x,
                               xla::XlaOp y, const BCast& broadcast_helper) {
  std::tie(x, y) = XlaBinaryOp::Broadcast(x, y, broadcast_helper);
  auto zero = XlaHelpers::Zero(b, dtype);
  auto y_equals_0 = xla::Eq(y, zero);
  auto zeros = xla::ZerosLike(x);
  auto result = xla::Select(y_equals_0, zeros, xla::Mul(x, y));
  return result;
}
XLA_MAKE_BINARY(MulNoNan,
                MulNoNanImpl(b, input_type(0), lhs, rhs, broadcast_helper));

// Implementation of FloorDiv.
//
// For floating-point values, simply returns floor(x / y).  For integers, does:
//
// if ((x < 0) != (y < 0)) {
//   T abs_x = std::abs(x);
//   T abs_y = std::abs(y);
//   return -(abs_x + abs_y - 1) / abs_y;
// } else {
//   return x / y;
// }
static xla::XlaOp FloorDivImpl(xla::XlaBuilder* b, DataType dtype, xla::XlaOp x,
                               xla::XlaOp y, const BCast& broadcast_helper) {
  std::tie(x, y) = XlaBinaryOp::Broadcast(x, y, broadcast_helper);
  if (DataTypeIsFloating(dtype)) {
    if (dtype == DataType::DT_BFLOAT16) {
      // The result of a BF16 division may produce the Ceil of what was
      // computed by F32 division, so avoid end user confusion by doing the
      // intermediate divide in F32.
      return xla::ConvertElementType(
          xla::Floor(xla::Div(xla::ConvertElementType(x, xla::F32),
                              xla::ConvertElementType(y, xla::F32))),
          xla::BF16);
    } else {
      return xla::Floor(xla::Div(x, y));
    }
  }
  if (DataTypeIsUnsigned(dtype)) {
    return xla::Div(x, y);
  }
  auto zero = XlaHelpers::Zero(b, dtype);
  auto one = XlaHelpers::One(b, dtype);
  auto different_sign = xla::Ne(xla::Lt(x, zero), xla::Lt(y, zero));
  auto abs_x = xla::Abs(x);
  auto abs_y = xla::Abs(y);
  auto t = xla::Neg(xla::Sub(xla::Add(abs_x, abs_y), one));
  return xla::Select(different_sign, xla::Div(t, abs_y), xla::Div(x, y));
}
XLA_MAKE_BINARY(FloorDiv,
                FloorDivImpl(b, input_type(0), lhs, rhs, broadcast_helper));

xla::XlaOp XlogyImpl(xla::XlaOp x, xla::XlaOp y,
                     const BCast& broadcast_helper) {
  std::tie(x, y) = XlaBinaryOp::Broadcast(x, y, broadcast_helper);
  auto zero = xla::ZerosLike(x);
  auto is_zero = xla::Eq(x, zero);
  return xla::Select(is_zero, zero, xla::Mul(x, xla::Log(y)));
}
XLA_MAKE_BINARY(Xlogy, XlogyImpl(lhs, rhs, broadcast_helper));

xla::XlaOp Xlog1pyImpl(xla::XlaOp x, xla::XlaOp y,
                       const BCast& broadcast_helper) {
  auto non_zero = xla::Mul(x, xla::Log1p(y));
  auto zero = xla::ZerosLike(x);
  auto x_is_zero = xla::Eq(x, zero);
  return xla::Select(x_is_zero, zero, non_zero);
}
XLA_MAKE_BINARY(Xlog1py, Xlog1pyImpl(lhs, rhs, broadcast_helper));

xla::XlaOp XdivyImpl(xla::XlaOp x, xla::XlaOp y,
                     const BCast& broadcast_helper) {
  std::tie(x, y) = XlaBinaryOp::Broadcast(x, y, broadcast_helper);
  auto zero = xla::ZerosLike(x);
  auto is_zero = xla::Eq(x, zero);
  return xla::Select(is_zero, zero, xla::Div(x, y));
}
XLA_MAKE_BINARY(Xdivy, XdivyImpl(lhs, rhs, broadcast_helper));

// Implementation of FloorMod. Pseudo-code:
// T trunc_mod = std::fmod(x, y);
// return trunc_mod != 0 && (y < 0 != trunc_mod < 0) ? trunc_mod + y
//                                                   : trunc_mod;
static xla::XlaOp FloorModImpl(xla::XlaBuilder* b, DataType dtype, xla::XlaOp x,
                               xla::XlaOp y, const BCast& broadcast_helper) {
  std::tie(x, y) = XlaBinaryOp::Broadcast(x, y, broadcast_helper);
  auto zero = XlaHelpers::Zero(b, dtype);
  auto trunc_mod = xla::Rem(x, y);
  auto trunc_mod_not_zero = xla::Ne(trunc_mod, zero);
  auto do_plus = xla::And(xla::Ne(xla::Lt(trunc_mod, zero), xla::Lt(y, zero)),
                          trunc_mod_not_zero);
  return xla::Select(do_plus, xla::Add(trunc_mod, y), trunc_mod);
}
XLA_MAKE_BINARY(FloorMod,
                FloorModImpl(b, input_type(0), lhs, rhs, broadcast_helper));

XLA_MAKE_BINARY(BitwiseAnd, xla::And(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(BitwiseOr, xla::Or(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(BitwiseXor, xla::Xor(lhs, rhs, extend_dimensions));

XLA_MAKE_BINARY(LeftShift, xla::ShiftLeft(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(RightShift,
                (DataTypeIsUnsigned(ctx->input_type(0))
                     ? xla::ShiftRightLogical(lhs, rhs, extend_dimensions)
                     : xla::ShiftRightArithmetic(lhs, rhs, extend_dimensions)));

XLA_MAKE_BINARY(LogicalAnd, xla::And(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(LogicalOr, xla::Or(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(Mod, xla::Rem(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(Maximum, xla::Max(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(Minimum, xla::Min(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(RealDiv, xla::Div(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(ReciprocalGrad, xla::Neg(xla::Mul(rhs, xla::Mul(lhs, lhs))));
XLA_MAKE_BINARY(
    RsqrtGrad,
    xla::Mul((lhs * lhs) * lhs,
             xla::Div(rhs, XlaHelpers::IntegerLiteral(b, input_type(0), -2)),
             extend_dimensions));
XLA_MAKE_BINARY(
    SqrtGrad,
    xla::Div(xla::Mul(rhs, XlaHelpers::FloatLiteral(b, input_type(0), 0.5)),
             lhs, extend_dimensions));

XLA_MAKE_BINARY(TruncateDiv, xla::Div(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(TruncateMod, xla::Rem(lhs, rhs, extend_dimensions));

// Comparison ops
XLA_MAKE_BINARY(Equal, xla::Eq(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(NotEqual, xla::Ne(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(Greater, xla::Gt(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(GreaterEqual, xla::Ge(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(Less, xla::Lt(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(LessEqual, xla::Le(lhs, rhs, extend_dimensions));

// Non-linear ops
XLA_MAKE_BINARY(SigmoidGrad,
                xla::Mul(xla::Mul(rhs, lhs),
                         xla::Sub(XlaHelpers::One(b, input_type(0)), lhs)));

XLA_MAKE_BINARY(SoftplusGrad, xla::Mul(lhs, xla::Logistic(rhs)));

// softsigngrad(gradients, features) = gradients / (1 + abs(features)) ** 2
XLA_MAKE_BINARY(SoftsignGrad,
                xla::Div(lhs,
                         xla::Square(xla::Add(XlaHelpers::One(b, input_type(0)),
                                              xla::Abs(rhs)))));

XLA_MAKE_BINARY(TanhGrad,
                xla::Mul(rhs, xla::Sub(XlaHelpers::One(b, input_type(0)),
                                       xla::Mul(lhs, lhs))));

XLA_MAKE_BINARY(Pow, xla::Pow(lhs, rhs, extend_dimensions));

xla::XlaOp SquaredDifferenceImpl(DataType dtype, xla::XlaOp x, xla::XlaOp y,
                                 const std::vector<int64>& extend_dimensions) {
  auto difference = xla::Sub(x, y, extend_dimensions);
  if (DataTypeIsComplex(dtype)) {
    return xla::Conj(difference) * difference;
  } else {
    return xla::Square(difference);
  }
}
XLA_MAKE_BINARY(SquaredDifference,
                SquaredDifferenceImpl(input_type(0), lhs, rhs,
                                      extend_dimensions));

#undef XLA_MAKE_BINARY

class ApproximateEqualOp : public XlaOpKernel {
 public:
  explicit ApproximateEqualOp(OpKernelConstruction* ctx) : XlaOpKernel(ctx) {
    OP_REQUIRES_OK(ctx, ctx->GetAttr("tolerance", &tolerance_));
  }

  // Computes the max of the scalar input x and 0.
  void Compile(XlaOpKernelContext* ctx) override {
    xla::XlaBuilder* b = ctx->builder();
    auto abs = xla::Abs(xla::Sub(ctx->Input(0), ctx->Input(1)));
    auto abs_shape = b->GetShape(abs);
    OP_REQUIRES_OK(ctx, abs_shape.status());
    auto abs_type = abs_shape.ValueOrDie().element_type();
    auto result =
        xla::Lt(abs, xla::ConvertElementType(
                         xla::ConstantR0<float>(b, tolerance_), abs_type));
    ctx->SetOutput(0, result);
  }

 private:
  float tolerance_;
};
REGISTER_XLA_OP(Name("ApproximateEqual"), ApproximateEqualOp);

}  // namespace
}  // namespace tensorflow
<commit_msg>All three operands to an HLO select operation must have the same shape.<commit_after>/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.

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

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

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

// Native XLA implementations of simple binary Ops

#include "tensorflow/compiler/tf2xla/kernels/cwise_ops.h"
#include "tensorflow/compiler/tf2xla/lib/broadcast.h"
#include "tensorflow/compiler/tf2xla/shape_util.h"
#include "tensorflow/compiler/tf2xla/xla_helpers.h"
#include "tensorflow/compiler/tf2xla/xla_op_registry.h"
#include "tensorflow/compiler/xla/client/client_library.h"
#include "tensorflow/compiler/xla/client/lib/constants.h"
#include "tensorflow/compiler/xla/client/lib/math.h"
#include "tensorflow/compiler/xla/client/xla_builder.h"
#include "tensorflow/compiler/xla/primitive_util.h"
#include "tensorflow/compiler/xla/xla_data.pb.h"
#include "tensorflow/core/framework/kernel_def_builder.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/types.h"

namespace tensorflow {
namespace {

// A subclass of a XlaBinaryOp must build the computation that
// describes the (tensor,tensor)->tensor function to apply to each element of
// the input.
#define XLA_MAKE_BINARY(NAME, HLO)                                       \
  class NAME##Op : public XlaBinaryOp {                                  \
   public:                                                               \
    explicit NAME##Op(OpKernelConstruction* ctx) : XlaBinaryOp(ctx) {}   \
    xla::XlaOp Computation(                                              \
        XlaOpKernelContext* ctx, const xla::XlaOp& lhs,                  \
        const absl::Span<const int64>& lhs_shape, const xla::XlaOp& rhs, \
        const absl::Span<const int64>& rhs_shape,                        \
        const BCast& broadcast_helper,                                   \
        const std::vector<int64>& extend_dimensions) override {          \
      xla::XlaBuilder* b = ctx->builder();                               \
      (void)b;                                                           \
      (void)lhs_shape;                                                   \
      (void)rhs_shape;                                                   \
      (void)extend_dimensions;                                           \
      return HLO;                                                        \
    }                                                                    \
  };                                                                     \
  REGISTER_XLA_OP(Name(#NAME), NAME##Op)

XLA_MAKE_BINARY(Add, xla::Add(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(AddV2, xla::Add(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(Sub, xla::Sub(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(Mul, xla::Mul(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(Div, xla::Div(lhs, rhs, extend_dimensions));

XLA_MAKE_BINARY(Atan2, xla::Atan2(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(Complex, xla::Complex(lhs, rhs, extend_dimensions));

// Implementation of DivNoNan. Pseudo-code:
// if (y == 0) {
//   return 0
// } else {
//   return x / y;
// }
static xla::XlaOp DivNoNanImpl(xla::XlaBuilder* b, DataType dtype, xla::XlaOp x,
                               xla::XlaOp y, const BCast& broadcast_helper) {
  std::tie(x, y) = XlaBinaryOp::Broadcast(x, y, broadcast_helper);
  auto zero = XlaHelpers::Zero(b, dtype);
  auto y_equals_0 = xla::Eq(y, zero);
  auto zeros = xla::ZerosLike(x);
  auto result = xla::Select(y_equals_0, zeros, xla::Div(x, y));
  return result;
}
XLA_MAKE_BINARY(DivNoNan,
                DivNoNanImpl(b, input_type(0), lhs, rhs, broadcast_helper));

// Implementation of MulNoNan. Pseudo-code:
// if (y == 0) {
//   return 0
// } else {
//   return x * y;
// }
static xla::XlaOp MulNoNanImpl(xla::XlaBuilder* b, DataType dtype, xla::XlaOp x,
                               xla::XlaOp y, const BCast& broadcast_helper) {
  std::tie(x, y) = XlaBinaryOp::Broadcast(x, y, broadcast_helper);
  auto zero = XlaHelpers::Zero(b, dtype);
  auto y_equals_0 = xla::Eq(y, zero);
  auto zeros = xla::ZerosLike(x);
  auto result = xla::Select(y_equals_0, zeros, xla::Mul(x, y));
  return result;
}
XLA_MAKE_BINARY(MulNoNan,
                MulNoNanImpl(b, input_type(0), lhs, rhs, broadcast_helper));

// Implementation of FloorDiv.
//
// For floating-point values, simply returns floor(x / y).  For integers, does:
//
// if ((x < 0) != (y < 0)) {
//   T abs_x = std::abs(x);
//   T abs_y = std::abs(y);
//   return -(abs_x + abs_y - 1) / abs_y;
// } else {
//   return x / y;
// }
static xla::XlaOp FloorDivImpl(xla::XlaBuilder* b, DataType dtype, xla::XlaOp x,
                               xla::XlaOp y, const BCast& broadcast_helper) {
  std::tie(x, y) = XlaBinaryOp::Broadcast(x, y, broadcast_helper);
  if (DataTypeIsFloating(dtype)) {
    if (dtype == DataType::DT_BFLOAT16) {
      // The result of a BF16 division may produce the Ceil of what was
      // computed by F32 division, so avoid end user confusion by doing the
      // intermediate divide in F32.
      return xla::ConvertElementType(
          xla::Floor(xla::Div(xla::ConvertElementType(x, xla::F32),
                              xla::ConvertElementType(y, xla::F32))),
          xla::BF16);
    } else {
      return xla::Floor(xla::Div(x, y));
    }
  }
  if (DataTypeIsUnsigned(dtype)) {
    return xla::Div(x, y);
  }
  auto zero = XlaHelpers::Zero(b, dtype);
  auto one = XlaHelpers::One(b, dtype);
  auto different_sign = xla::Ne(xla::Lt(x, zero), xla::Lt(y, zero));
  auto abs_x = xla::Abs(x);
  auto abs_y = xla::Abs(y);
  auto t = xla::Neg(xla::Sub(xla::Add(abs_x, abs_y), one));
  return xla::Select(different_sign, xla::Div(t, abs_y), xla::Div(x, y));
}
XLA_MAKE_BINARY(FloorDiv,
                FloorDivImpl(b, input_type(0), lhs, rhs, broadcast_helper));

xla::XlaOp XlogyImpl(xla::XlaOp x, xla::XlaOp y,
                     const BCast& broadcast_helper) {
  std::tie(x, y) = XlaBinaryOp::Broadcast(x, y, broadcast_helper);
  auto zero = xla::ZerosLike(x);
  auto is_zero = xla::Eq(x, zero);
  return xla::Select(is_zero, zero, xla::Mul(x, xla::Log(y)));
}
XLA_MAKE_BINARY(Xlogy, XlogyImpl(lhs, rhs, broadcast_helper));

xla::XlaOp Xlog1pyImpl(xla::XlaOp x, xla::XlaOp y,
                       const BCast& broadcast_helper) {
  auto non_zero = xla::Mul(x, xla::Log1p(y));
  auto zero = xla::ZerosLike(non_zero);
  auto x_is_zero = xla::Eq(x, zero);
  return xla::Select(x_is_zero, zero, non_zero);
}
XLA_MAKE_BINARY(Xlog1py, Xlog1pyImpl(lhs, rhs, broadcast_helper));

xla::XlaOp XdivyImpl(xla::XlaOp x, xla::XlaOp y,
                     const BCast& broadcast_helper) {
  std::tie(x, y) = XlaBinaryOp::Broadcast(x, y, broadcast_helper);
  auto zero = xla::ZerosLike(x);
  auto is_zero = xla::Eq(x, zero);
  return xla::Select(is_zero, zero, xla::Div(x, y));
}
XLA_MAKE_BINARY(Xdivy, XdivyImpl(lhs, rhs, broadcast_helper));

// Implementation of FloorMod. Pseudo-code:
// T trunc_mod = std::fmod(x, y);
// return trunc_mod != 0 && (y < 0 != trunc_mod < 0) ? trunc_mod + y
//                                                   : trunc_mod;
static xla::XlaOp FloorModImpl(xla::XlaBuilder* b, DataType dtype, xla::XlaOp x,
                               xla::XlaOp y, const BCast& broadcast_helper) {
  std::tie(x, y) = XlaBinaryOp::Broadcast(x, y, broadcast_helper);
  auto zero = XlaHelpers::Zero(b, dtype);
  auto trunc_mod = xla::Rem(x, y);
  auto trunc_mod_not_zero = xla::Ne(trunc_mod, zero);
  auto do_plus = xla::And(xla::Ne(xla::Lt(trunc_mod, zero), xla::Lt(y, zero)),
                          trunc_mod_not_zero);
  return xla::Select(do_plus, xla::Add(trunc_mod, y), trunc_mod);
}
XLA_MAKE_BINARY(FloorMod,
                FloorModImpl(b, input_type(0), lhs, rhs, broadcast_helper));

XLA_MAKE_BINARY(BitwiseAnd, xla::And(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(BitwiseOr, xla::Or(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(BitwiseXor, xla::Xor(lhs, rhs, extend_dimensions));

XLA_MAKE_BINARY(LeftShift, xla::ShiftLeft(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(RightShift,
                (DataTypeIsUnsigned(ctx->input_type(0))
                     ? xla::ShiftRightLogical(lhs, rhs, extend_dimensions)
                     : xla::ShiftRightArithmetic(lhs, rhs, extend_dimensions)));

XLA_MAKE_BINARY(LogicalAnd, xla::And(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(LogicalOr, xla::Or(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(Mod, xla::Rem(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(Maximum, xla::Max(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(Minimum, xla::Min(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(RealDiv, xla::Div(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(ReciprocalGrad, xla::Neg(xla::Mul(rhs, xla::Mul(lhs, lhs))));
XLA_MAKE_BINARY(
    RsqrtGrad,
    xla::Mul((lhs * lhs) * lhs,
             xla::Div(rhs, XlaHelpers::IntegerLiteral(b, input_type(0), -2)),
             extend_dimensions));
XLA_MAKE_BINARY(
    SqrtGrad,
    xla::Div(xla::Mul(rhs, XlaHelpers::FloatLiteral(b, input_type(0), 0.5)),
             lhs, extend_dimensions));

XLA_MAKE_BINARY(TruncateDiv, xla::Div(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(TruncateMod, xla::Rem(lhs, rhs, extend_dimensions));

// Comparison ops
XLA_MAKE_BINARY(Equal, xla::Eq(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(NotEqual, xla::Ne(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(Greater, xla::Gt(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(GreaterEqual, xla::Ge(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(Less, xla::Lt(lhs, rhs, extend_dimensions));
XLA_MAKE_BINARY(LessEqual, xla::Le(lhs, rhs, extend_dimensions));

// Non-linear ops
XLA_MAKE_BINARY(SigmoidGrad,
                xla::Mul(xla::Mul(rhs, lhs),
                         xla::Sub(XlaHelpers::One(b, input_type(0)), lhs)));

XLA_MAKE_BINARY(SoftplusGrad, xla::Mul(lhs, xla::Logistic(rhs)));

// softsigngrad(gradients, features) = gradients / (1 + abs(features)) ** 2
XLA_MAKE_BINARY(SoftsignGrad,
                xla::Div(lhs,
                         xla::Square(xla::Add(XlaHelpers::One(b, input_type(0)),
                                              xla::Abs(rhs)))));

XLA_MAKE_BINARY(TanhGrad,
                xla::Mul(rhs, xla::Sub(XlaHelpers::One(b, input_type(0)),
                                       xla::Mul(lhs, lhs))));

XLA_MAKE_BINARY(Pow, xla::Pow(lhs, rhs, extend_dimensions));

xla::XlaOp SquaredDifferenceImpl(DataType dtype, xla::XlaOp x, xla::XlaOp y,
                                 const std::vector<int64>& extend_dimensions) {
  auto difference = xla::Sub(x, y, extend_dimensions);
  if (DataTypeIsComplex(dtype)) {
    return xla::Conj(difference) * difference;
  } else {
    return xla::Square(difference);
  }
}
XLA_MAKE_BINARY(SquaredDifference,
                SquaredDifferenceImpl(input_type(0), lhs, rhs,
                                      extend_dimensions));

#undef XLA_MAKE_BINARY

class ApproximateEqualOp : public XlaOpKernel {
 public:
  explicit ApproximateEqualOp(OpKernelConstruction* ctx) : XlaOpKernel(ctx) {
    OP_REQUIRES_OK(ctx, ctx->GetAttr("tolerance", &tolerance_));
  }

  // Computes the max of the scalar input x and 0.
  void Compile(XlaOpKernelContext* ctx) override {
    xla::XlaBuilder* b = ctx->builder();
    auto abs = xla::Abs(xla::Sub(ctx->Input(0), ctx->Input(1)));
    auto abs_shape = b->GetShape(abs);
    OP_REQUIRES_OK(ctx, abs_shape.status());
    auto abs_type = abs_shape.ValueOrDie().element_type();
    auto result =
        xla::Lt(abs, xla::ConvertElementType(
                         xla::ConstantR0<float>(b, tolerance_), abs_type));
    ctx->SetOutput(0, result);
  }

 private:
  float tolerance_;
};
REGISTER_XLA_OP(Name("ApproximateEqual"), ApproximateEqualOp);

}  // namespace
}  // namespace tensorflow
<|endoftext|>


<commit_before>//! \file
/*
**  Copyright (C) - Triton
**
**  This program is under the terms of the BSD License.
*/

#include <callbacks.hpp>
#include <exceptions.hpp>

#ifdef TRITON_PYTHON_BINDINGS
  #include <pythonObjects.hpp>
  #include <pythonUtils.hpp>
  #include <pythonXFunctions.hpp>
#endif

namespace triton {
  namespace callbacks {

    Callbacks::Callbacks() {
      this->isDefined = false;
    }

    Callbacks::Callbacks(const Callbacks& copy) {
      #ifdef TRITON_PYTHON_BINDINGS
      this->pyMemoryHitCallbacks              = copy.pyMemoryHitCallbacks;
      this->pySymbolicSimplificationCallbacks = copy.pySymbolicSimplificationCallbacks;
      #endif
      this->memoryHitCallbacks                = copy.memoryHitCallbacks;
      this->symbolicSimplificationCallbacks   = copy.symbolicSimplificationCallbacks;
      this->isDefined                         = copy.isDefined;
    }

    Callbacks::~Callbacks() {
    }

    void Callbacks::operator=(const Callbacks& copy) {
      #ifdef TRITON_PYTHON_BINDINGS
      this->pyMemoryHitCallbacks              = copy.pyMemoryHitCallbacks;
      this->pySymbolicSimplificationCallbacks = copy.pySymbolicSimplificationCallbacks;
      #endif
      this->memoryHitCallbacks                = copy.memoryHitCallbacks;
      this->symbolicSimplificationCallbacks   = copy.symbolicSimplificationCallbacks;
      this->isDefined                         = copy.isDefined;
    }

    void Callbacks::addCallback(triton::callbacks::memoryHitCallback cb) {
      this->memoryHitCallbacks.push_back(cb);
      this->isDefined = true;
    }

    void Callbacks::addCallback(triton::callbacks::symbolicSimplificationCallback cb) {
      this->symbolicSimplificationCallbacks.push_back(cb);
      this->isDefined = true;
    }

    #ifdef TRITON_PYTHON_BINDINGS
    void Callbacks::addCallback(triton::callbacks::callback_e kind, PyObject* function) {
      switch (kind) {
        case MEMORY_HIT:
            this->pyMemoryHitCallbacks.push_back(function);
          break;
        case SYMBOLIC_SIMPLIFICATION:
            this->pySymbolicSimplificationCallbacks.push_back(function);
          break;
        default:
          throw triton::exceptions::Callbacks("Callbacks::addCallback(): Invalid kind of callback.");
      };
      this->isDefined = true;
    }
    #endif

    void Callbacks::deleteCallback(triton::callbacks::memoryHitCallback cb) {
      this->memoryHitCallbacks.remove(cb);
      if (this->countCallbacks() == 0)
        this->isDefined = false;
    }

    void Callbacks::deleteCallback(triton::callbacks::symbolicSimplificationCallback cb) {
      this->symbolicSimplificationCallbacks.remove(cb);
      if (this->countCallbacks() == 0)
        this->isDefined = false;
    }

    #ifdef TRITON_PYTHON_BINDINGS
    void Callbacks::deleteCallback(triton::callbacks::callback_e kind, PyObject* function) {
      switch (kind) {
        case MEMORY_HIT:
            this->pyMemoryHitCallbacks.remove(function);
          break;
        case SYMBOLIC_SIMPLIFICATION:
            this->pySymbolicSimplificationCallbacks.remove(function);
          break;
        default:
          throw triton::exceptions::Callbacks("Callbacks::deleteCallback(): Invalid kind of callback.");
      };

      if (this->countCallbacks() == 0)
        this->isDefined = false;
    }
    #endif

    triton::ast::AbstractNode* Callbacks::processCallbacks(triton::callbacks::callback_e kind, triton::ast::AbstractNode* node) const {
      switch (kind) {
        case triton::callbacks::SYMBOLIC_SIMPLIFICATION: {
          // C++ callbacks
          std::list<triton::callbacks::symbolicSimplificationCallback>::const_iterator it1;
          for (it1 = this->symbolicSimplificationCallbacks.begin(); it1 != this->symbolicSimplificationCallbacks.end(); it1++) {
            node = (*it1)(node);
            if (node == nullptr)
              throw triton::exceptions::Callbacks("Callbacks::processCallbacks(SYMBOLIC_SIMPLIFICATION): You cannot return a nullptr node.");
          }

          #ifdef TRITON_PYTHON_BINDINGS
          // Python callbacks
          std::list<PyObject*>::const_iterator it2;
          for (it2 = this->pySymbolicSimplificationCallbacks.begin(); it2 != this->pySymbolicSimplificationCallbacks.end(); it2++) {

            /* Create function args */
            PyObject* args = triton::bindings::python::xPyTuple_New(1);
            PyTuple_SetItem(args, 0, triton::bindings::python::PyAstNode(node));

            /* Call the callback */
            PyObject* ret = PyObject_CallObject(*it2, args);

            /* Check the call */
            if (ret == nullptr) {
              PyErr_Print();
              throw triton::exceptions::Callbacks("Callbacks::processCallbacks(SYMBOLIC_SIMPLIFICATION): Fail to call the python callback.");
            }

            /* Check if the callback has returned a AbstractNode */
            if (!PyAstNode_Check(ret))
              throw triton::exceptions::Callbacks("Callbacks::processCallbacks(SYMBOLIC_SIMPLIFICATION): You must return a AstNode object.");

            /* Update node */
            node = PyAstNode_AsAstNode(ret);
            Py_DECREF(args);
          }
          #endif
          break;
        }
        default:
          throw triton::exceptions::Callbacks("Callbacks::processCallbacks(): Invalid kind of callback for this C++ polymorphism.");
      };

      return node;
    }

    void Callbacks::processCallbacks(triton::callbacks::callback_e kind, triton::uint64 address) const {
      switch (kind) {
        case triton::callbacks::MEMORY_HIT: {
          // C++ callbacks
          std::list<triton::callbacks::memoryHitCallback>::const_iterator it1;
          for (it1 = this->memoryHitCallbacks.begin(); it1 != this->memoryHitCallbacks.end(); it1++)
            (*it1)(address);

          #ifdef TRITON_PYTHON_BINDINGS
          // Python callbacks
          std::list<PyObject*>::const_iterator it2;
          for (it2 = this->pyMemoryHitCallbacks.begin(); it2 != this->pyMemoryHitCallbacks.end(); it2++) {

            /* Create function args */
            PyObject* args = triton::bindings::python::xPyTuple_New(1);
            PyTuple_SetItem(args, 0, triton::bindings::python::PyLong_FromUint64(address));

            /* Call the callback */
            PyObject* ret = PyObject_CallObject(*it2, args);

            /* Check the call */
            if (ret == nullptr) {
              PyErr_Print();
              throw triton::exceptions::Callbacks("Callbacks::processCallbacks(MEMORY_HIT): Fail to call the python callback.");
            }

            Py_DECREF(args);
          }
          #endif
        }
        default:
          throw triton::exceptions::Callbacks("Callbacks::processCallbacks(): Invalid kind of callback for this C++ polymorphism.");
      };
    }

    triton::uint32 Callbacks::countCallbacks(void) const {
      triton::uint32 count = 0;

      count += this->memoryHitCallbacks.size();
      count += this->symbolicSimplificationCallbacks.size();
      #ifdef TRITON_PYTHON_BINDINGS
      count += this->pyMemoryHitCallbacks.size();
      count += this->pySymbolicSimplificationCallbacks.size();
      #endif

      return count;
    }

  }; /* callbacks namespace */
}; /* triton namespace */
<commit_msg>#318 in progress<commit_after>//! \file
/*
**  Copyright (C) - Triton
**
**  This program is under the terms of the BSD License.
*/

#include <callbacks.hpp>
#include <exceptions.hpp>

#ifdef TRITON_PYTHON_BINDINGS
  #include <pythonObjects.hpp>
  #include <pythonUtils.hpp>
  #include <pythonXFunctions.hpp>
#endif

namespace triton {
  namespace callbacks {

    Callbacks::Callbacks() {
      this->isDefined = false;
    }

    Callbacks::Callbacks(const Callbacks& copy) {
      #ifdef TRITON_PYTHON_BINDINGS
      this->pyMemoryHitCallbacks              = copy.pyMemoryHitCallbacks;
      this->pySymbolicSimplificationCallbacks = copy.pySymbolicSimplificationCallbacks;
      #endif
      this->memoryHitCallbacks                = copy.memoryHitCallbacks;
      this->symbolicSimplificationCallbacks   = copy.symbolicSimplificationCallbacks;
      this->isDefined                         = copy.isDefined;
    }

    Callbacks::~Callbacks() {
    }

    void Callbacks::operator=(const Callbacks& copy) {
      #ifdef TRITON_PYTHON_BINDINGS
      this->pyMemoryHitCallbacks              = copy.pyMemoryHitCallbacks;
      this->pySymbolicSimplificationCallbacks = copy.pySymbolicSimplificationCallbacks;
      #endif
      this->memoryHitCallbacks                = copy.memoryHitCallbacks;
      this->symbolicSimplificationCallbacks   = copy.symbolicSimplificationCallbacks;
      this->isDefined                         = copy.isDefined;
    }

    void Callbacks::addCallback(triton::callbacks::memoryHitCallback cb) {
      this->memoryHitCallbacks.push_back(cb);
      this->isDefined = true;
    }

    void Callbacks::addCallback(triton::callbacks::symbolicSimplificationCallback cb) {
      this->symbolicSimplificationCallbacks.push_back(cb);
      this->isDefined = true;
    }

    #ifdef TRITON_PYTHON_BINDINGS
    void Callbacks::addCallback(triton::callbacks::callback_e kind, PyObject* function) {
      switch (kind) {
        case MEMORY_HIT:
          this->pyMemoryHitCallbacks.push_back(function);
          break;
        case SYMBOLIC_SIMPLIFICATION:
          this->pySymbolicSimplificationCallbacks.push_back(function);
          break;
        default:
          throw triton::exceptions::Callbacks("Callbacks::addCallback(): Invalid kind of callback.");
      };
      this->isDefined = true;
    }
    #endif

    void Callbacks::deleteCallback(triton::callbacks::memoryHitCallback cb) {
      this->memoryHitCallbacks.remove(cb);
      if (this->countCallbacks() == 0)
        this->isDefined = false;
    }

    void Callbacks::deleteCallback(triton::callbacks::symbolicSimplificationCallback cb) {
      this->symbolicSimplificationCallbacks.remove(cb);
      if (this->countCallbacks() == 0)
        this->isDefined = false;
    }

    #ifdef TRITON_PYTHON_BINDINGS
    void Callbacks::deleteCallback(triton::callbacks::callback_e kind, PyObject* function) {
      switch (kind) {
        case MEMORY_HIT:
          this->pyMemoryHitCallbacks.remove(function);
          break;
        case SYMBOLIC_SIMPLIFICATION:
          this->pySymbolicSimplificationCallbacks.remove(function);
          break;
        default:
          throw triton::exceptions::Callbacks("Callbacks::deleteCallback(): Invalid kind of callback.");
      };

      if (this->countCallbacks() == 0)
        this->isDefined = false;
    }
    #endif

    triton::ast::AbstractNode* Callbacks::processCallbacks(triton::callbacks::callback_e kind, triton::ast::AbstractNode* node) const {
      switch (kind) {
        case triton::callbacks::SYMBOLIC_SIMPLIFICATION: {
          // C++ callbacks
          std::list<triton::callbacks::symbolicSimplificationCallback>::const_iterator it1;
          for (it1 = this->symbolicSimplificationCallbacks.begin(); it1 != this->symbolicSimplificationCallbacks.end(); it1++) {
            node = (*it1)(node);
            if (node == nullptr)
              throw triton::exceptions::Callbacks("Callbacks::processCallbacks(SYMBOLIC_SIMPLIFICATION): You cannot return a nullptr node.");
          }

          #ifdef TRITON_PYTHON_BINDINGS
          // Python callbacks
          std::list<PyObject*>::const_iterator it2;
          for (it2 = this->pySymbolicSimplificationCallbacks.begin(); it2 != this->pySymbolicSimplificationCallbacks.end(); it2++) {

            /* Create function args */
            PyObject* args = triton::bindings::python::xPyTuple_New(1);
            PyTuple_SetItem(args, 0, triton::bindings::python::PyAstNode(node));

            /* Call the callback */
            PyObject* ret = PyObject_CallObject(*it2, args);

            /* Check the call */
            if (ret == nullptr) {
              PyErr_Print();
              throw triton::exceptions::Callbacks("Callbacks::processCallbacks(SYMBOLIC_SIMPLIFICATION): Fail to call the python callback.");
            }

            /* Check if the callback has returned a AbstractNode */
            if (!PyAstNode_Check(ret))
              throw triton::exceptions::Callbacks("Callbacks::processCallbacks(SYMBOLIC_SIMPLIFICATION): You must return a AstNode object.");

            /* Update node */
            node = PyAstNode_AsAstNode(ret);
            Py_DECREF(args);
          }
          #endif
          break;
        }
        default:
          throw triton::exceptions::Callbacks("Callbacks::processCallbacks(): Invalid kind of callback for this C++ polymorphism.");
      };

      return node;
    }

    void Callbacks::processCallbacks(triton::callbacks::callback_e kind, triton::uint64 address) const {
      switch (kind) {
        case triton::callbacks::MEMORY_HIT: {
          // C++ callbacks
          std::list<triton::callbacks::memoryHitCallback>::const_iterator it1;
          for (it1 = this->memoryHitCallbacks.begin(); it1 != this->memoryHitCallbacks.end(); it1++)
            (*it1)(address);

          #ifdef TRITON_PYTHON_BINDINGS
          // Python callbacks
          std::list<PyObject*>::const_iterator it2;
          for (it2 = this->pyMemoryHitCallbacks.begin(); it2 != this->pyMemoryHitCallbacks.end(); it2++) {

            /* Create function args */
            PyObject* args = triton::bindings::python::xPyTuple_New(1);
            PyTuple_SetItem(args, 0, triton::bindings::python::PyLong_FromUint64(address));

            /* Call the callback */
            PyObject* ret = PyObject_CallObject(*it2, args);

            /* Check the call */
            if (ret == nullptr) {
              PyErr_Print();
              throw triton::exceptions::Callbacks("Callbacks::processCallbacks(MEMORY_HIT): Fail to call the python callback.");
            }

            Py_DECREF(args);
          }
          #endif
          break;
        }
        default:
          throw triton::exceptions::Callbacks("Callbacks::processCallbacks(): Invalid kind of callback for this C++ polymorphism.");
      };
    }

    triton::uint32 Callbacks::countCallbacks(void) const {
      triton::uint32 count = 0;

      count += this->memoryHitCallbacks.size();
      count += this->symbolicSimplificationCallbacks.size();
      #ifdef TRITON_PYTHON_BINDINGS
      count += this->pyMemoryHitCallbacks.size();
      count += this->pySymbolicSimplificationCallbacks.size();
      #endif

      return count;
    }

  }; /* callbacks namespace */
}; /* triton namespace */
<|endoftext|>


<commit_before>/****************************************************************************
 * This file is part of QtConfiguration.
 *
 * Copyright (C) 2012-2013 Pier Luigi Fiorini
 *
 * Author(s):
 *    Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
 *
 * $BEGIN_LICENSE:LGPL2$
 *
 * This library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Library General Public License as published by
 * the Free Software Foundation; version 2.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 * $END_LICENSE$
 ***************************************************************************/

#include "qconfigurationbackend.h"

QConfigurationBackend::QConfigurationBackend(QObject *parent)
    : QObject(parent)
{
}

void QConfigurationBackend::setCategory(const QString &category)
{
}

bool QConfigurationBackend::contains(const QString &key) const
{
    Q_UNUSED(key);
    return false;
}

QVariant QConfigurationBackend::value(const QString &key, const QVariant &defaultValue) const
{
    Q_UNUSED(key);
    return defaultValue;
}

void QConfigurationBackend::setValue(const QString &key, const QVariant &value)
{
    Q_UNUSED(key);
    Q_UNUSED(value);
}

#include "moc_qconfigurationbackend.cpp"
<commit_msg>Suppress unused warning<commit_after>/****************************************************************************
 * This file is part of QtConfiguration.
 *
 * Copyright (C) 2012-2013 Pier Luigi Fiorini
 *
 * Author(s):
 *    Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
 *
 * $BEGIN_LICENSE:LGPL2$
 *
 * This library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Library General Public License as published by
 * the Free Software Foundation; version 2.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 * $END_LICENSE$
 ***************************************************************************/

#include "qconfigurationbackend.h"

QConfigurationBackend::QConfigurationBackend(QObject *parent)
    : QObject(parent)
{
}

void QConfigurationBackend::setCategory(const QString &category)
{
    Q_UNUSED(category);
}

bool QConfigurationBackend::contains(const QString &key) const
{
    Q_UNUSED(key);
    return false;
}

QVariant QConfigurationBackend::value(const QString &key, const QVariant &defaultValue) const
{
    Q_UNUSED(key);
    return defaultValue;
}

void QConfigurationBackend::setValue(const QString &key, const QVariant &value)
{
    Q_UNUSED(key);
    Q_UNUSED(value);
}

#include "moc_qconfigurationbackend.cpp"
<|endoftext|>


<commit_before>#include <algorithm>
#include <string>

#include <glm/gtc/matrix_transform.hpp>

#include <zombye/assets/asset_manager.hpp>
#include <zombye/core/game.hpp>
#include <zombye/rendering/rendering_system.hpp>
#include <zombye/rendering/shader_program.hpp>
#include <zombye/rendering/vertex_buffer.hpp>
#include <zombye/rendering/vertex_array.hpp>
#include <zombye/rendering/vertex_layout.hpp>
#include <zombye/rendering/mesh.hpp>
#include <zombye/utils/logger.hpp>
#include <zombye/utils/os.h>

namespace zombye {
    rendering_system::rendering_system(game& game, SDL_Window* window)
    : game_(game), window_(window), mesh_manager_{game_}, texture_manager_{game_},
    shader_manager_{game_}, active_camera_{0}, perspective_projection_{1} {
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);

        context_ = SDL_GL_CreateContext(window);
        auto error = std::string{SDL_GetError()};
        if (error != "\0") {
            throw std::runtime_error("could not create OpenGL context with version 3.3: " + error);
        }
        SDL_ClearError();

        SDL_GL_SetSwapInterval(1);

        if (glewInit() != GLEW_OK) {
            throw std::runtime_error("could not initialize glew");
        }

        auto version = glGetString(GL_VERSION);
        log("OpenGL version " + std::string{reinterpret_cast<const char*>(version)});

        glEnable(GL_DEPTH_TEST);
        set_clear_color(0.5f, 0.5f, 0.5f, 1.0f);

        if (GLEW_KHR_debug) {
#ifdef __APPLE__
            glDebugMessageCallback(+[](GLenum source, GLenum type, GLuint id, GLenum severity,
            GLsizei length, const GLchar *message, const void *userParam) {
                log(LOG_ERROR, std::string(message, length) + " source: " + std::to_string(source)
                    + " type: " +  std::to_string(type) + " id: " + std::to_string(id)
                    + " servity: " + std::to_string(severity));
            }, nullptr);
#else
            glDebugMessageCallback(+[](GLenum source, GLenum type, GLuint id, GLenum severity,
            GLsizei length, const GLchar *message, void *userParam) {
                log(LOG_ERROR, std::string(message, length) + " source: " + std::to_string(source)
                    + " type: " +  std::to_string(type) + " id: " + std::to_string(id)
                    + " servity: " + std::to_string(severity));
            }, nullptr);
#endif
        } else {
            log(LOG_ERROR, "no OpenGL debug log available");
        }

        vertex_layout_.emplace("in_position", 3, GL_FLOAT, GL_FALSE, sizeof(vertex), 0);
        vertex_layout_.emplace("in_normal", 3, GL_FLOAT, GL_FALSE, sizeof(vertex), sizeof(glm::vec3));
        vertex_layout_.emplace("in_texel", 2, GL_FLOAT, GL_FALSE, sizeof(vertex), 2 * sizeof(glm::vec3));

        auto vs = shader_manager_.load("shader/staticmesh.vs", GL_VERTEX_SHADER);
        if (!vs) {
            throw std::runtime_error("could not load shader from file shader/staticmesh.vs");
        }
        auto fs = shader_manager_.load("shader/staticmesh.fs", GL_FRAGMENT_SHADER);
        if (!fs) {
            throw std::runtime_error("could not load shader from file shader/staticmesh.fs");
        }

        staticmesh_program_ = std::unique_ptr<shader_program>{new shader_program{}};

        staticmesh_program_->attach_shader(vs);
        staticmesh_program_->attach_shader(fs);

        vertex_layout_.setup_program(*staticmesh_program_, "fragcolor");
        staticmesh_program_->link();

        fovy_ = 90.0f * 3.14f / 180.0f;
        auto aspect_ratio = static_cast<float>(game_.width()) / static_cast<float>(game_.height());
        near_plane_ = 0.01f;
        far_plane_ = 1000.0f;
        perspective_projection_ = glm::perspective(fovy_, aspect_ratio, near_plane_, far_plane_);
    }

    rendering_system::~rendering_system() noexcept {
        window_ = nullptr;
        SDL_GL_DeleteContext(context_);
    }

    void rendering_system::update(float delta_time) {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        auto view = glm::mat4{1.0f};
        auto camera = camera_components_.find(active_camera_);
        if (camera != camera_components_.end()) {
            view = camera->second->transform();
        }
        auto vp = perspective_projection_ * view;
        staticmesh_program_->use();
        staticmesh_program_->uniform("color_texture", 0);
        for (auto& sm : staticmesh_components_) {
            staticmesh_program_->uniform("mvp", 1, GL_FALSE, vp * sm->owner().transform());
            sm->draw();
        }

        SDL_GL_SwapWindow(window_);
    }

    void rendering_system::set_clear_color(float red, float green, float blue, float alpha) {
        glClearColor(red, green, blue, alpha);
    }

    void rendering_system::resize_projection(float width, float height) noexcept {
        auto aspect_ratio = width / height;
        perspective_projection_ = glm::perspective(fovy_, aspect_ratio, near_plane_, far_plane_);
        glViewport(0, 0, width, height);
    }

    void rendering_system::register_component(staticmesh_component* component) {
        staticmesh_components_.emplace_back(component);
    }

    void rendering_system::unregister_component(staticmesh_component* component) {
        auto it = std::find(staticmesh_components_.begin(), staticmesh_components_.end() ,component);
        auto last = staticmesh_components_.end() - 1;
        if (it != last) {
            *it = std::move(*last);
        }
        staticmesh_components_.pop_back();
    }

    void rendering_system::register_component(camera_component* component) {
        camera_components_.emplace(std::make_pair(component->owner().id(), component));
    }

    void rendering_system::unregister_component(camera_component* component) {
        auto it = camera_components_.find(component->owner().id());
        if (it != camera_components_.end()) {
            camera_components_.erase(it);
        }
    }
}<commit_msg>fix weird open gl extension loading bug on intel hd 3000<commit_after>#include <algorithm>
#include <string>

#include <glm/gtc/matrix_transform.hpp>

#include <zombye/assets/asset_manager.hpp>
#include <zombye/core/game.hpp>
#include <zombye/rendering/rendering_system.hpp>
#include <zombye/rendering/shader_program.hpp>
#include <zombye/rendering/vertex_buffer.hpp>
#include <zombye/rendering/vertex_array.hpp>
#include <zombye/rendering/vertex_layout.hpp>
#include <zombye/rendering/mesh.hpp>
#include <zombye/utils/logger.hpp>
#include <zombye/utils/os.h>

namespace zombye {
    rendering_system::rendering_system(game& game, SDL_Window* window)
    : game_(game), window_(window), mesh_manager_{game_}, texture_manager_{game_},
    shader_manager_{game_}, active_camera_{0}, perspective_projection_{1} {
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);

        context_ = SDL_GL_CreateContext(window);
        auto error = std::string{SDL_GetError()};
        if (error != "\0") {
            throw std::runtime_error("could not create OpenGL context with version 3.3: " + error);
        }
        SDL_ClearError();

        SDL_GL_SetSwapInterval(1);

        glewExperimental = GL_TRUE;
        if (glewInit() != GLEW_OK) {
            throw std::runtime_error("could not initialize glew");
        }

        auto version = glGetString(GL_VERSION);
        log("OpenGL version " + std::string{reinterpret_cast<const char*>(version)});

        glEnable(GL_DEPTH_TEST);
        set_clear_color(0.5f, 0.5f, 0.5f, 1.0f);

        if (GLEW_KHR_debug) {
#ifdef __APPLE__
            glDebugMessageCallback(+[](GLenum source, GLenum type, GLuint id, GLenum severity,
            GLsizei length, const GLchar *message, const void *userParam) {
                log(LOG_ERROR, std::string(message, length) + " source: " + std::to_string(source)
                    + " type: " +  std::to_string(type) + " id: " + std::to_string(id)
                    + " servity: " + std::to_string(severity));
            }, nullptr);
#else
            glDebugMessageCallback(+[](GLenum source, GLenum type, GLuint id, GLenum severity,
            GLsizei length, const GLchar *message, void *userParam) {
                log(LOG_ERROR, std::string(message, length) + " source: " + std::to_string(source)
                    + " type: " +  std::to_string(type) + " id: " + std::to_string(id)
                    + " servity: " + std::to_string(severity));
            }, nullptr);
#endif
        } else {
            log(LOG_ERROR, "no OpenGL debug log available");
        }

        vertex_layout_.emplace("in_position", 3, GL_FLOAT, GL_FALSE, sizeof(vertex), 0);
        vertex_layout_.emplace("in_normal", 3, GL_FLOAT, GL_FALSE, sizeof(vertex), sizeof(glm::vec3));
        vertex_layout_.emplace("in_texel", 2, GL_FLOAT, GL_FALSE, sizeof(vertex), 2 * sizeof(glm::vec3));

        auto vs = shader_manager_.load("shader/staticmesh.vs", GL_VERTEX_SHADER);
        if (!vs) {
            throw std::runtime_error("could not load shader from file shader/staticmesh.vs");
        }
        auto fs = shader_manager_.load("shader/staticmesh.fs", GL_FRAGMENT_SHADER);
        if (!fs) {
            throw std::runtime_error("could not load shader from file shader/staticmesh.fs");
        }

        staticmesh_program_ = std::unique_ptr<shader_program>{new shader_program{}};

        staticmesh_program_->attach_shader(vs);
        staticmesh_program_->attach_shader(fs);

        vertex_layout_.setup_program(*staticmesh_program_, "fragcolor");
        staticmesh_program_->link();

        fovy_ = 90.0f * 3.14f / 180.0f;
        auto aspect_ratio = static_cast<float>(game_.width()) / static_cast<float>(game_.height());
        near_plane_ = 0.01f;
        far_plane_ = 1000.0f;
        perspective_projection_ = glm::perspective(fovy_, aspect_ratio, near_plane_, far_plane_);
    }

    rendering_system::~rendering_system() noexcept {
        window_ = nullptr;
        SDL_GL_DeleteContext(context_);
    }

    void rendering_system::update(float delta_time) {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        auto view = glm::mat4{1.0f};
        auto camera = camera_components_.find(active_camera_);
        if (camera != camera_components_.end()) {
            view = camera->second->transform();
        }
        auto vp = perspective_projection_ * view;
        staticmesh_program_->use();
        staticmesh_program_->uniform("color_texture", 0);
        for (auto& sm : staticmesh_components_) {
            staticmesh_program_->uniform("mvp", 1, GL_FALSE, vp * sm->owner().transform());
            sm->draw();
        }

        SDL_GL_SwapWindow(window_);
    }

    void rendering_system::set_clear_color(float red, float green, float blue, float alpha) {
        glClearColor(red, green, blue, alpha);
    }

    void rendering_system::resize_projection(float width, float height) noexcept {
        auto aspect_ratio = width / height;
        perspective_projection_ = glm::perspective(fovy_, aspect_ratio, near_plane_, far_plane_);
        glViewport(0, 0, width, height);
    }

    void rendering_system::register_component(staticmesh_component* component) {
        staticmesh_components_.emplace_back(component);
    }

    void rendering_system::unregister_component(staticmesh_component* component) {
        auto it = std::find(staticmesh_components_.begin(), staticmesh_components_.end() ,component);
        auto last = staticmesh_components_.end() - 1;
        if (it != last) {
            *it = std::move(*last);
        }
        staticmesh_components_.pop_back();
    }

    void rendering_system::register_component(camera_component* component) {
        camera_components_.emplace(std::make_pair(component->owner().id(), component));
    }

    void rendering_system::unregister_component(camera_component* component) {
        auto it = camera_components_.find(component->owner().id());
        if (it != camera_components_.end()) {
            camera_components_.erase(it);
        }
    }
}<|endoftext|>


<commit_before>#include <assert.h>
#include <utility>

#include "macros.h"
#include "libutil/exceptions.h"

#include "libinterpreter/execution_visitor.h"

void pack_values_in_array(const std::vector<Value> &value_list, uint64_t array[]) {
  for (size_t i=0; i < value_list.size(); i++) {
    array[i] = value_list[i].to_uint64_t();
  }
}

ExecutionVisitor::ExecutionVisitor(ExecutionContext &ctxt, Driver& driver)
    : driver_(driver), context_(ctxt) {}

void ExecutionVisitor::visit_assert(UnaryNode* assert, Value& val) {
  if (val.value.bval != true) {
    driver_.error(assert->location,
                  "Assertion failed");
    throw RuntimeException("Assertion failed");
  }
}

void ExecutionVisitor::visit_update(UpdateNode *update, Value &func_val, Value& expr_v) {

  UNUSED(func_val);

  casm_update* up = (casm_update*) pp_mem_alloc(&(context_.pp_stack), sizeof(casm_update));

  // TODO initialize other fields
  up->value = (void*) expr_v.to_uint64_t();
  up->func = update->func->symbol->id;
  pack_values_in_array(value_list, up->args);

  up->num_args = value_list.size();

  value_list.clear();
  if(up->func == 0) {
    DEBUG("asd "<< value_list.size() << " asd "<<up->value);
  }
  casm_update* v = (casm_update*)casm_updateset_add(&(context_.updateset),
                                                    (void*) update->func->symbol->id,
                                                    (void*) up);
  // TODO implement seq semantic
  if (v != nullptr) {
    driver_.error(update->func->location,
                  "Conflict in current block for function `"+update->func->name+"`");
    throw RuntimeException("Conflict in updateset");
  }
}

Value&& ExecutionVisitor::visit_expression(Expression *expr, Value &left_val, Value &right_val) {
  switch (expr->op) {
    case Expression::Operation::ADD: {
      switch (left_val.type) {
        case Type::INT: {
          left_val.value.ival += right_val.value.ival;
          return std::move(left_val);
        }
        default: assert(0);
      }
      break;
    }
    case Expression::Operation::EQ: {
      DEBUG ("got "<< left_val.value.ival << " and "<<right_val.value.ival);
      switch (left_val.type) {
        case Type::INT: {
          left_val.value.bval = left_val.value.ival == right_val.value.ival;
          return std::move(left_val);
        }
        case Type::BOOL: {
          left_val.value.bval = left_val.value.bval == right_val.value.bval;
          return std::move(left_val);
        }
        case Type::UNDEF:
          if (right_val.type == Type::UNDEF) {
            left_val.value.bval = true;
          } else {
            left_val.value.bval = false;
          }
          return std::move(left_val);
        default: assert(0);
      }
    }
    default: assert(0);
  }
}

Value&& ExecutionVisitor::visit_expression_single(Expression *expr, Value &val) {
  UNUSED(expr);
  return std::move(val);
}

Value&& ExecutionVisitor::visit_function_atom(FunctionAtom *atom, std::vector<Value> &expr_results) {
  size_t num_args = 1;
  if (expr_results.size() > 0) {
    num_args = expr_results.size();

  }
  uint64_t args[num_args];
  args[0] = 0;

  pack_values_in_array(value_list, args);
  casm_update *data = context_.get_function_value(atom->symbol, args);
  DEBUG("foo "<< value_list.size() << " asd "<<args[0] << " func " << atom->symbol->id<< " geto " << data->value);

  // TODO handle function access and function write differently
  value_list.swap(expr_results);

  if (data == nullptr) {
    return std::move(Value());
  }

  switch (atom->symbol->return_type_) {
    case Type::INT: return std::move(Value((int64_t)data->value));
    default: throw "invalid type in function";
  }

}

void ExecutionWalker::run() {
  for (auto pair: visitor.context_.symbol_table->table_) {
    auto function_map = std::unordered_map<ArgumentsKey, casm_update*>();

    if (pair.second->intitializers_ != nullptr) {
      for (std::pair<AtomNode*, AtomNode*> init : *pair.second->intitializers_) {
        casm_update* up = (casm_update*) pp_mem_alloc(&visitor.context_.pp_stack, sizeof(casm_update));

        size_t num_args = 0;
        if (init.first != nullptr) {
          std::vector<Value> ident;
          ident.push_back(walk_atom(init.first));
          pack_values_in_array(ident, &up->args[0]);
          num_args = ident.size();
        }

        up->func = pair.second->id;
        up->value = (void*) walk_atom(init.second).to_uint64_t();
        DEBUG("init value" << up->value << " func " << up->func << " num arg "<<num_args);
        up->args[0] = 0;
        // TODO implement for functions with arguments
        function_map[{&up->args[0], num_args}] = up;
      }
    }
    visitor.context_.functions.push_back(std::move(function_map));
  }

  Symbol *program_sym = visitor.context_.symbol_table->get("program");
  uint64_t args[1] = {0};
  while(true) {
    casm_update *program_val = visitor.context_.get_function_value(program_sym, args);
    if (program_val->value == 0) {
      break;
    }
    walk_rule(reinterpret_cast<RuleNode*>(program_val->value));
    visitor.context_.apply_updates();
  }
}
<commit_msg>Fix segfault in DEBUG message<commit_after>#include <assert.h>
#include <utility>

#include "macros.h"
#include "libutil/exceptions.h"

#include "libinterpreter/execution_visitor.h"

void pack_values_in_array(const std::vector<Value> &value_list, uint64_t array[]) {
  for (size_t i=0; i < value_list.size(); i++) {
    array[i] = value_list[i].to_uint64_t();
  }
}

ExecutionVisitor::ExecutionVisitor(ExecutionContext &ctxt, Driver& driver)
    : driver_(driver), context_(ctxt) {}

void ExecutionVisitor::visit_assert(UnaryNode* assert, Value& val) {
  if (val.value.bval != true) {
    driver_.error(assert->location,
                  "Assertion failed");
    throw RuntimeException("Assertion failed");
  }
}

void ExecutionVisitor::visit_update(UpdateNode *update, Value &func_val, Value& expr_v) {

  UNUSED(func_val);

  casm_update* up = (casm_update*) pp_mem_alloc(&(context_.pp_stack), sizeof(casm_update));

  // TODO initialize other fields
  up->value = (void*) expr_v.to_uint64_t();
  up->func = update->func->symbol->id;
  pack_values_in_array(value_list, up->args);

  up->num_args = value_list.size();

  value_list.clear();
  if(up->func == 0) {
    DEBUG("asd "<< value_list.size() << " asd "<<up->value);
  }
  casm_update* v = (casm_update*)casm_updateset_add(&(context_.updateset),
                                                    (void*) update->func->symbol->id,
                                                    (void*) up);
  // TODO implement seq semantic
  if (v != nullptr) {
    driver_.error(update->func->location,
                  "Conflict in current block for function `"+update->func->name+"`");
    throw RuntimeException("Conflict in updateset");
  }
}

Value&& ExecutionVisitor::visit_expression(Expression *expr, Value &left_val, Value &right_val) {
  switch (expr->op) {
    case Expression::Operation::ADD: {
      switch (left_val.type) {
        case Type::INT: {
          left_val.value.ival += right_val.value.ival;
          return std::move(left_val);
        }
        default: assert(0);
      }
      break;
    }
    case Expression::Operation::EQ: {
      DEBUG ("got "<< left_val.value.ival << " and "<<right_val.value.ival);
      switch (left_val.type) {
        case Type::INT: {
          left_val.value.bval = left_val.value.ival == right_val.value.ival;
          return std::move(left_val);
        }
        case Type::BOOL: {
          left_val.value.bval = left_val.value.bval == right_val.value.bval;
          return std::move(left_val);
        }
        case Type::UNDEF:
          if (right_val.type == Type::UNDEF) {
            left_val.value.bval = true;
          } else {
            left_val.value.bval = false;
          }
          return std::move(left_val);
        default: assert(0);
      }
    }
    default: assert(0);
  }
}

Value&& ExecutionVisitor::visit_expression_single(Expression *expr, Value &val) {
  UNUSED(expr);
  return std::move(val);
}

Value&& ExecutionVisitor::visit_function_atom(FunctionAtom *atom, std::vector<Value> &expr_results) {
  size_t num_args = 1;
  if (expr_results.size() > 0) {
    num_args = expr_results.size();

  }
  uint64_t args[num_args];
  args[0] = 0;

  pack_values_in_array(value_list, args);
  casm_update *data = context_.get_function_value(atom->symbol, args);
  DEBUG("foo "<< value_list.size() << " asd "<<args[0] << " func " << atom->symbol->id);

  // TODO handle function access and function write differently
  value_list.swap(expr_results);

  if (data == nullptr) {
    return std::move(Value());
  }

  switch (atom->symbol->return_type_) {
    case Type::INT: return std::move(Value((int64_t)data->value));
    default: throw "invalid type in function";
  }

}

void ExecutionWalker::run() {
  for (auto pair: visitor.context_.symbol_table->table_) {
    auto function_map = std::unordered_map<ArgumentsKey, casm_update*>();

    if (pair.second->intitializers_ != nullptr) {
      for (std::pair<AtomNode*, AtomNode*> init : *pair.second->intitializers_) {
        casm_update* up = (casm_update*) pp_mem_alloc(&visitor.context_.pp_stack, sizeof(casm_update));

        size_t num_args = 0;
        if (init.first != nullptr) {
          std::vector<Value> ident;
          ident.push_back(walk_atom(init.first));
          pack_values_in_array(ident, &up->args[0]);
          num_args = ident.size();
        }

        up->func = pair.second->id;
        up->value = (void*) walk_atom(init.second).to_uint64_t();
        DEBUG("init value" << up->value << " func " << up->func << " num arg "<<num_args);
        up->args[0] = 0;
        // TODO implement for functions with arguments
        function_map[{&up->args[0], num_args}] = up;
      }
    }
    visitor.context_.functions.push_back(std::move(function_map));
  }

  Symbol *program_sym = visitor.context_.symbol_table->get("program");
  uint64_t args[1] = {0};
  while(true) {
    casm_update *program_val = visitor.context_.get_function_value(program_sym, args);
    if (program_val->value == 0) {
      break;
    }
    walk_rule(reinterpret_cast<RuleNode*>(program_val->value));
    visitor.context_.apply_updates();
  }
}
<|endoftext|>


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

#include "theia/sfm/localize_view_to_reconstruction.h"

#include <glog/logging.h>
#include <vector>

#include "theia/sfm/bundle_adjustment/bundle_adjustment.h"
#include "theia/sfm/estimators/feature_correspondence_2d_3d.h"
#include "theia/sfm/estimators/estimate_calibrated_absolute_pose.h"
#include "theia/sfm/estimators/estimate_uncalibrated_absolute_pose.h"
#include "theia/sfm/camera/camera.h"
#include "theia/sfm/reconstruction.h"
#include "theia/sfm/types.h"
#include "theia/solvers/sample_consensus_estimator.h"

namespace theia {
namespace {

// Normalize a feature by its camera intrinsics.
void NormalizeFeature(const Camera& camera,
                      const double focal_length,
                      Feature* feature) {
  feature->y() = (feature->y() - camera.PrincipalPointY()) /
                 (focal_length * camera.AspectRatio());
  feature->x() =
      (feature->x() - camera.Skew() * feature->y() - camera.PrincipalPointX()) /
      focal_length;
}

void GetNormalized2D3DCorrespondencesForView(
        const View& view,
        const Reconstruction& reconstruction,
        const double focal_length,
        std::vector<FeatureCorrespondence2D3D>* correspondences) {
  const auto& tracks_in_view = view.TrackIds();
  const Camera& camera = view.Camera();
  correspondences->reserve(tracks_in_view.size());

  for (const TrackId track_id : tracks_in_view) {
    const Track* track = reconstruction.Track(track_id);
    // We only use 3D points that have been estimated.
    if (!track->IsEstimated()) {
      continue;
    }

    FeatureCorrespondence2D3D correspondence;
    correspondence.feature = *view.GetFeature(track_id);
    // Normalize the feature by the intrinsics.
    NormalizeFeature(camera, focal_length, &correspondence.feature);

    correspondence.world_point = track->Point().hnormalized();
    correspondences->emplace_back(correspondence);
  }
}

}  // namespace

bool LocalizeViewToReconstruction(
    const ViewId view_to_localize,
    const LocalizeViewToReconstructionOptions options,
    Reconstruction* reconstruction,
    RansacSummary* summary) {
  CHECK_NOTNULL(reconstruction);
  CHECK_NOTNULL(summary);

  View* view = reconstruction->MutableView(view_to_localize);
  Camera* camera = view->MutableCamera();

  // Normalizing the pixels to remove the camera intrinsics requires dividing by
  // the focal length. In the case where the focal length is unknown we simply
  // skip this division by making the focal length equal to 1.
  static const double kUnknownFocalLength = 1.0;
  const bool known_focal_length =
      view->CameraIntrinsicsPrior().focal_length.is_set;
  const double focal_length =
      known_focal_length ? camera->FocalLength() : kUnknownFocalLength;

  // Gather all 2D-3D correspondences.
  std::vector<FeatureCorrespondence2D3D> matches;
  GetNormalized2D3DCorrespondencesForView(*view,
                                          *reconstruction,
                                          focal_length,
                                          &matches);
  if (matches.size() < options.min_num_inliers) {
    VLOG(2) << "Not enough 2D-3D correspondences to localize view "
            << view_to_localize;
    return false;
  }

  // Set up the ransac parameters for absolute pose estimation.
  bool success = false;
  // NOTE: The value of focal_length depends on if the focal length is known or
  // not so this threshold will scale appropriately.
  RansacParameters ransac_parameters = options.ransac_params;
  ransac_parameters.error_thresh = options.reprojection_error_threshold_pixels *
                                   options.reprojection_error_threshold_pixels /
                                   (focal_length * focal_length);

  // If calibrated, estimate the pose with P3P.
  if (known_focal_length) {
    CalibratedAbsolutePose pose;
    success = EstimateCalibratedAbsolutePose(
        ransac_parameters, RansacType::RANSAC, matches, &pose, summary);
    camera->SetOrientationFromRotationMatrix(pose.rotation);
    camera->SetPosition(pose.position);
  } else {
    // If the focal length is not known, estimate the focal length and pose
    // together.
    UncalibratedAbsolutePose pose;
    success = EstimateUncalibratedAbsolutePose(
        ransac_parameters, RansacType::RANSAC, matches, &pose, summary);
    camera->SetOrientationFromRotationMatrix(pose.rotation);
    camera->SetPosition(pose.position);
    camera->SetFocalLength(pose.focal_length);
  }

  // If localization failed or did not produce a sufficient number of inliers
  // then return false.
  if (!success || summary->inliers.size() < options.min_num_inliers) {
    VLOG(2) << "Failed to localize view id " << view_to_localize
            << " with only " << summary->inliers.size() << " out of "
            << matches.size() << " features as inliers.";
    return false;
  }

  // Bundle adjust the view if desired.
  view->SetEstimated(true);
  if (options.bundle_adjust_view) {
    const BundleAdjustmentSummary summary =
        BundleAdjustView(options.ba_options, view_to_localize, reconstruction);
    success = summary.success;
  }

  VLOG(2) << "Estimated the camera pose for view " << view_to_localize
          << " with " << summary->inliers.size() << " inliers out of "
          << matches.size() << " 2D-3D matches.";
  return success;
}

}  // namespace theia
<commit_msg>LocalizeViewToReconstruction properly incorporates shared intrinsics and has better point normalization under radial distortion.<commit_after>// Copyright (C) 2015 The Regents of the University of California (Regents).
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//
//     * Neither the name of The Regents or University of California nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Please contact the author of this library if you have any questions.
// Author: Chris Sweeney (cmsweeney@cs.ucsb.edu)

#include "theia/sfm/localize_view_to_reconstruction.h"

#include <glog/logging.h>
#include <vector>

#include "theia/sfm/bundle_adjustment/bundle_adjustment.h"
#include "theia/sfm/estimators/feature_correspondence_2d_3d.h"
#include "theia/sfm/estimators/estimate_calibrated_absolute_pose.h"
#include "theia/sfm/estimators/estimate_uncalibrated_absolute_pose.h"
#include "theia/sfm/camera/camera.h"
#include "theia/sfm/reconstruction.h"
#include "theia/sfm/types.h"
#include "theia/solvers/sample_consensus_estimator.h"

namespace theia {
namespace {

bool DoesViewHaveKnownIntrinsics(const Reconstruction& reconstruction,
                                 const ViewId view_id) {
  const View* view = reconstruction.View(view_id);
  // Return true if the EXIF data provides a focal length guess
  if (view->CameraIntrinsicsPrior().focal_length.is_set) {
    return true;
  }

  // If the camera has shared intrinsics, return true if one of the shared
  // cameras has been estimated.
  const CameraIntrinsicsGroupId intrinsics_group_id =
      reconstruction.CameraIntrinsicsGroupIdFromViewId(view_id);
  const std::unordered_set<ViewId> views_in_intrinsics_group =
      reconstruction.GetViewsInCameraIntrinsicGroup(intrinsics_group_id);
  for (const ViewId shared_intrinsics_view_id : views_in_intrinsics_group) {
    const View* view = reconstruction.View(view_id);
    if (view->IsEstimated() && view_id != shared_intrinsics_view_id) {
      return true;
    }
  }
  return false;
}

void GetNormalized2D3DMatches(const Reconstruction& reconstruction,
                              const View& view,
                              const bool known_intrinsics,
                              std::vector<FeatureCorrespondence2D3D>* matches) {
  const Camera& camera = view.Camera();
  const auto& tracks_in_view = view.TrackIds();
  matches->reserve(tracks_in_view.size());
  for (const TrackId track_id : tracks_in_view) {
    const Track* track = reconstruction.Track(track_id);
    // We only use 3D points that have been estimated.
    if (!track->IsEstimated()) {
      continue;
    }

    FeatureCorrespondence2D3D correspondence;
    const Feature& feature = *view.GetFeature(track_id);
    if (known_intrinsics) {
      // Get the image feature and undistort it according to the camera
      // parameters.
      const Eigen::Vector3d normalized_feature =
          camera.PixelToUnitDepthRay(feature);
      correspondence.feature = normalized_feature.hnormalized();
    } else {
      // Otherwise, simply shift the pixel to remove the effect of the principal
      // point.
      correspondence.feature =
          feature -
          Eigen::Vector2d(camera.PrincipalPointX(), camera.PrincipalPointY());
    }
    correspondence.world_point = track->Point().hnormalized();
    matches->emplace_back(correspondence);
  }
}

}  // namespace

bool LocalizeViewToReconstruction(
    const ViewId view_to_localize,
    const LocalizeViewToReconstructionOptions options,
    Reconstruction* reconstruction,
    RansacSummary* summary) {
  CHECK_NOTNULL(reconstruction);
  CHECK_NOTNULL(summary);

  View* view = reconstruction->MutableView(view_to_localize);
  const bool known_intrinsics =
      DoesViewHaveKnownIntrinsics(*reconstruction, view_to_localize);

  Camera* camera = view->MutableCamera();
  // Set the pose to be the identity pose.
  camera->SetPosition(Eigen::Vector3d::Zero());
  camera->SetOrientationFromAngleAxis(Eigen::Vector3d::Zero());

  // Gather all 2D-3D correspondences.
  std::vector<FeatureCorrespondence2D3D> matches;
  GetNormalized2D3DMatches(*reconstruction, *view, known_intrinsics, &matches);

  // Exit early if there are not enough putative matches.
  if (matches.size() < options.min_num_inliers) {
    VLOG(2) << "Not enough 2D-3D correspondences to localize view "
            << view_to_localize;
    return false;
  }

  // Set up the ransac parameters for absolute pose estimation.
  bool success = false;
  RansacParameters ransac_parameters = options.ransac_params;

  // If calibrated, estimate the pose with P3P.
  if (known_intrinsics) {
    ransac_parameters.error_thresh =
        options.reprojection_error_threshold_pixels *
        options.reprojection_error_threshold_pixels /
        (camera->FocalLength() * camera->FocalLength());

    CalibratedAbsolutePose pose;
    success = EstimateCalibratedAbsolutePose(
        ransac_parameters, RansacType::RANSAC, matches, &pose, summary);
    camera->SetOrientationFromRotationMatrix(pose.rotation);
    camera->SetPosition(pose.position);
  } else {
    // If the focal length is not known, estimate the focal length and pose
    // together.
    ransac_parameters.error_thresh =
        options.reprojection_error_threshold_pixels *
        options.reprojection_error_threshold_pixels;

    UncalibratedAbsolutePose pose;
    success = EstimateUncalibratedAbsolutePose(
        ransac_parameters, RansacType::RANSAC, matches, &pose, summary);
    camera->SetOrientationFromRotationMatrix(pose.rotation);
    camera->SetPosition(pose.position);
    camera->SetFocalLength(pose.focal_length);
  }

  // If localization failed or did not produce a sufficient number of inliers
  // then return false.
  if (!success || summary->inliers.size() < options.min_num_inliers) {
    VLOG(2) << "Failed to localize view id " << view_to_localize
            << " with only " << summary->inliers.size() << " out of "
            << matches.size() << " features as inliers.";
    return false;
  }

  // Bundle adjust the view if desired.
  view->SetEstimated(true);
  if (options.bundle_adjust_view) {
    const BundleAdjustmentSummary summary =
        BundleAdjustView(options.ba_options, view_to_localize, reconstruction);
    success = summary.success;
  }

  VLOG(2) << "Estimated the camera pose for view " << view_to_localize
          << " with " << summary->inliers.size() << " inliers out of "
          << matches.size() << " 2D-3D matches.";
  return success;
}

}  // namespace theia
<|endoftext|>


<commit_before>#include "orbit_mpi.hh"
#include "pyORBIT_Object.hh"

#include "wrap_utils.hh"
#include "wrap_matrix.hh"
#include "wrap_bunch.hh"

#include <iostream>

#include "BunchExtremaCalculator.hh"

using namespace OrbitUtils;
using namespace wrap_orbit_utils;

namespace wrap_utils_bunch{

  void error(const char* msg){ ORBIT_MPI_Finalize(msg); }

#ifdef __cplusplus
extern "C" {
#endif
	//---------------------------------------------------------
	//Python BunchExtremaCalculator class definition
	//---------------------------------------------------------

	//constructor for python class wrapping BunchExtremaCalculator instance
	//It never will be called directly
	static PyObject* BunchExtremaCalculator_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
	{
		pyORBIT_Object* self;
		self = (pyORBIT_Object *) type->tp_alloc(type, 0);
		self->cpp_obj = NULL;
		return (PyObject *) self;
	}

  //initializator for python  BunchExtremaCalculator class
  //this is implementation of the __init__ method
  static int BunchExtremaCalculator_init(pyORBIT_Object *self, PyObject *args, PyObject *kwds){
		self->cpp_obj = new BunchExtremaCalculator();
    return 0;
  }

	//Calculates xMin,xMax,  yMin,yMax, zMin,zMax,
  static PyObject* BunchExtremaCalculator_extremaXYZ(PyObject *self, PyObject *args){
		PyObject *pyIn;
		if(!PyArg_ParseTuple(args,"O:extremaXYZ",&pyIn)){
			error("PyBunchExtremaCalculator - extremaXYZ(Bunch) - Bunch is needed.");
		}
		PyObject* pyBunchType = wrap_orbit_bunch::getBunchType("Bunch");
		if((!PyObject_IsInstance(pyIn,pyBunchType))){
			error("PyBunchExtremaCalculator - extremaXYZ(Bunch) - input parameter is not Bunch");
		}
		Bunch* bunch = (Bunch*) ((pyORBIT_Object*) pyIn)->cpp_obj;
		BunchExtremaCalculator* cpp_BunchExtremaCalculator = (BunchExtremaCalculator*) (((pyORBIT_Object*) self)->cpp_obj);
		double xMin,xMax,yMin,yMax,zMin,zMax;
		cpp_BunchExtremaCalculator->getExtremaXYZ(bunch, xMin, xMax, yMin, yMax, zMin, zMax);
		return Py_BuildValue("(d,d,d,d,d,d)", xMin, xMax, yMin, yMax, zMin, zMax);
  }

  //-----------------------------------------------------
  //destructor for python BunchExtremaCalculator class (__del__ method).
  //-----------------------------------------------------
  static void BunchExtremaCalculator_del(pyORBIT_Object* self){
		delete ((BunchExtremaCalculator*)self->cpp_obj);
		self->ob_type->tp_free((PyObject*)self);
  }

	// defenition of the methods of the python BunchExtremaCalculator wrapper class
	// they will be vailable from python level
  static PyMethodDef BunchExtremaCalculatorClassMethods[] = {
    { "extremaXYZ",   BunchExtremaCalculator_extremaXYZ  ,METH_VARARGS,"Returns tuple with (xMin, xMax, yMin, yMax, zMin, zMax)"},
    {NULL}
  };

	// defenition of the memebers of the python BunchExtremaCalculator wrapper class
	// they will be vailable from python level
	static PyMemberDef BunchExtremaCalculatorClassMembers [] = {
		{NULL}
	};

	//new python BunchExtremaCalculator wrapper type definition
	static PyTypeObject pyORBIT_BunchExtremaCalculator_Type = {
		PyObject_HEAD_INIT(NULL)
		0, /*ob_size*/
		"BunchExtremaCalculator", /*tp_name*/
		sizeof(pyORBIT_Object), /*tp_basicsize*/
		0, /*tp_itemsize*/
		(destructor) BunchExtremaCalculator_del , /*tp_dealloc*/
		0, /*tp_print*/
		0, /*tp_getattr*/
		0, /*tp_setattr*/
		0, /*tp_compare*/
		0, /*tp_repr*/
		0, /*tp_as_number*/
		0, /*tp_as_sequence*/
		0, /*tp_as_mapping*/
		0, /*tp_hash */
		0, /*tp_call*/
		0, /*tp_str*/
		0, /*tp_getattro*/
		0, /*tp_setattro*/
		0, /*tp_as_buffer*/
		Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
		"The BunchExtremaCalculator python wrapper", /* tp_doc */
		0, /* tp_traverse */
		0, /* tp_clear */
		0, /* tp_richcompare */
		0, /* tp_weaklistoffset */
		0, /* tp_iter */
		0, /* tp_iternext */
		BunchExtremaCalculatorClassMethods, /* tp_methods */
		BunchExtremaCalculatorClassMembers, /* tp_members */
		0, /* tp_getset */
		0, /* tp_base */
		0, /* tp_dict */
		0, /* tp_descr_get */
		0, /* tp_descr_set */
		0, /* tp_dictoffset */
		(initproc) BunchExtremaCalculator_init, /* tp_init */
		0, /* tp_alloc */
		BunchExtremaCalculator_new, /* tp_new */
	};

	//--------------------------------------------------
	//Initialization function of the pyBunchExtremaCalculator class
	//It will be called from Bunch wrapper initialization
	//--------------------------------------------------
  void initBunchExtremaCalculator(PyObject* module){
		if (PyType_Ready(&pyORBIT_BunchExtremaCalculator_Type) < 0) return;
		Py_INCREF(&pyORBIT_BunchExtremaCalculator_Type);
		PyModule_AddObject(module, "BunchExtremaCalculator", (PyObject *)&pyORBIT_BunchExtremaCalculator_Type);
	}

#ifdef __cplusplus
}
#endif

//end of namespace wrap_utils_martix
}
<commit_msg>New wrapper of bunch extrema calc.<commit_after>#include "orbit_mpi.hh"
#include "pyORBIT_Object.hh"

#include "wrap_utils.hh"
#include "wrap_matrix.hh"
#include "wrap_bunch.hh"

#include <iostream>

#include "BunchExtremaCalculator.hh"

using namespace OrbitUtils;
using namespace wrap_orbit_utils;

namespace wrap_utils_bunch{

  void error(const char* msg){ ORBIT_MPI_Finalize(msg); }

#ifdef __cplusplus
extern "C" {
#endif
	//---------------------------------------------------------
	//Python BunchExtremaCalculator class definition
	//---------------------------------------------------------

	//constructor for python class wrapping BunchExtremaCalculator instance
	//It never will be called directly
	static PyObject* BunchExtremaCalculator_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
	{
		pyORBIT_Object* self;
		self = (pyORBIT_Object *) type->tp_alloc(type, 0);
		self->cpp_obj = NULL;
		return (PyObject *) self;
	}

  //initializator for python  BunchExtremaCalculator class
  //this is implementation of the __init__ method
  static int BunchExtremaCalculator_init(pyORBIT_Object *self, PyObject *args, PyObject *kwds){
		self->cpp_obj = new BunchExtremaCalculator();
    return 0;
  }

	//Calculates xMin,xMax,  yMin,yMax, zMin,zMax,
  static PyObject* BunchExtremaCalculator_extremaXYZ(PyObject *self, PyObject *args){
		PyObject *pyIn;
		if(!PyArg_ParseTuple(args,"O:extremaXYZ",&pyIn)){
			error("PyBunchExtremaCalculator - extremaXYZ(Bunch) - Bunch is needed.");
		}
		PyObject* pyBunchType = wrap_orbit_bunch::getBunchType("Bunch");
		if((!PyObject_IsInstance(pyIn,pyBunchType))){
			error("PyBunchExtremaCalculator - extremaXYZ(Bunch) - input parameter is not Bunch");
		}
		Bunch* bunch = (Bunch*) ((pyORBIT_Object*) pyIn)->cpp_obj;
		BunchExtremaCalculator* cpp_BunchExtremaCalculator = (BunchExtremaCalculator*) (((pyORBIT_Object*) self)->cpp_obj);
		double xMin,xMax,yMin,yMax,zMin,zMax;
		cpp_BunchExtremaCalculator->getExtremaXYZ(bunch, xMin, xMax, yMin, yMax, zMin, zMax);
		return Py_BuildValue("(d,d,d,d,d,d)", xMin, xMax, yMin, yMax, zMin, zMax);
  }

	//Calculates zMin,zMax
  static PyObject* BunchExtremaCalculator_extremaZ(PyObject *self, PyObject *args){
		PyObject *pyIn;
		if(!PyArg_ParseTuple(args,"O:extremaZ",&pyIn)){
			error("PyBunchExtremaCalculator - extremaZ(Bunch) - Bunch is needed.");
		}
		PyObject* pyBunchType = wrap_orbit_bunch::getBunchType("Bunch");
		if((!PyObject_IsInstance(pyIn,pyBunchType))){
			error("PyBunchExtremaCalculator - extremaZ(Bunch) - input parameter is not Bunch");
		}
		Bunch* bunch = (Bunch*) ((pyORBIT_Object*) pyIn)->cpp_obj;
		BunchExtremaCalculator* cpp_BunchExtremaCalculator = (BunchExtremaCalculator*) (((pyORBIT_Object*) self)->cpp_obj);
		double zMin,zMax;
		cpp_BunchExtremaCalculator->getExtremaZ(bunch, zMin, zMax);
		return Py_BuildValue("(d,d)", zMin, zMax);
  }

  //-----------------------------------------------------
  //destructor for python BunchExtremaCalculator class (__del__ method).
  //-----------------------------------------------------
  static void BunchExtremaCalculator_del(pyORBIT_Object* self){
		delete ((BunchExtremaCalculator*)self->cpp_obj);
		self->ob_type->tp_free((PyObject*)self);
  }

	// defenition of the methods of the python BunchExtremaCalculator wrapper class
	// they will be vailable from python level
  static PyMethodDef BunchExtremaCalculatorClassMethods[] = {
    { "extremaXYZ",   BunchExtremaCalculator_extremaXYZ  ,METH_VARARGS,"Returns tuple with (xMin, xMax, yMin, yMax, zMin, zMax)"},
    { "extremaZ",   BunchExtremaCalculator_extremaZ  ,METH_VARARGS,"Returns tuple with (zMin, zMax)"},
    {NULL}
  };

	// defenition of the memebers of the python BunchExtremaCalculator wrapper class
	// they will be vailable from python level
	static PyMemberDef BunchExtremaCalculatorClassMembers [] = {
		{NULL}
	};

	//new python BunchExtremaCalculator wrapper type definition
	static PyTypeObject pyORBIT_BunchExtremaCalculator_Type = {
		PyObject_HEAD_INIT(NULL)
		0, /*ob_size*/
		"BunchExtremaCalculator", /*tp_name*/
		sizeof(pyORBIT_Object), /*tp_basicsize*/
		0, /*tp_itemsize*/
		(destructor) BunchExtremaCalculator_del , /*tp_dealloc*/
		0, /*tp_print*/
		0, /*tp_getattr*/
		0, /*tp_setattr*/
		0, /*tp_compare*/
		0, /*tp_repr*/
		0, /*tp_as_number*/
		0, /*tp_as_sequence*/
		0, /*tp_as_mapping*/
		0, /*tp_hash */
		0, /*tp_call*/
		0, /*tp_str*/
		0, /*tp_getattro*/
		0, /*tp_setattro*/
		0, /*tp_as_buffer*/
		Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
		"The BunchExtremaCalculator python wrapper", /* tp_doc */
		0, /* tp_traverse */
		0, /* tp_clear */
		0, /* tp_richcompare */
		0, /* tp_weaklistoffset */
		0, /* tp_iter */
		0, /* tp_iternext */
		BunchExtremaCalculatorClassMethods, /* tp_methods */
		BunchExtremaCalculatorClassMembers, /* tp_members */
		0, /* tp_getset */
		0, /* tp_base */
		0, /* tp_dict */
		0, /* tp_descr_get */
		0, /* tp_descr_set */
		0, /* tp_dictoffset */
		(initproc) BunchExtremaCalculator_init, /* tp_init */
		0, /* tp_alloc */
		BunchExtremaCalculator_new, /* tp_new */
	};

	//--------------------------------------------------
	//Initialization function of the pyBunchExtremaCalculator class
	//It will be called from Bunch wrapper initialization
	//--------------------------------------------------
  void initBunchExtremaCalculator(PyObject* module){
		if (PyType_Ready(&pyORBIT_BunchExtremaCalculator_Type) < 0) return;
		Py_INCREF(&pyORBIT_BunchExtremaCalculator_Type);
		PyModule_AddObject(module, "BunchExtremaCalculator", (PyObject *)&pyORBIT_BunchExtremaCalculator_Type);
	}

#ifdef __cplusplus
}
#endif

//end of namespace wrap_utils_martix
}
<|endoftext|>