<commit_before>/* Copyright 2015 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.
==============================================================================*/

// See docs in ../ops/math_ops.cc.

#define EIGEN_USE_THREADS

#include "tensorflow/core/kernels/sparse_tensor_dense_matmul_op.h"

#include "tensorflow/core/framework/op.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/kernels/bounds_check.h"
#include "tensorflow/core/kernels/fill_functor.h"

namespace tensorflow {

typedef Eigen::ThreadPoolDevice CPUDevice;
typedef Eigen::GpuDevice GPUDevice;

template <typename Device, typename T>
class SparseTensorDenseMatMulOp : public OpKernel {
 public:
  explicit SparseTensorDenseMatMulOp(OpKernelConstruction* ctx)
      : OpKernel(ctx) {
    OP_REQUIRES_OK(ctx, ctx->GetAttr("adjoint_a", &adjoint_a_));
    OP_REQUIRES_OK(ctx, ctx->GetAttr("adjoint_b", &adjoint_b_));
  }

  void Compute(OpKernelContext* ctx) override {
    const Tensor* a_indices;
    const Tensor* a_values;
    const Tensor* a_shape;
    const Tensor* b;
    OP_REQUIRES_OK(ctx, ctx->input("a_indices", &a_indices));
    OP_REQUIRES_OK(ctx, ctx->input("a_values", &a_values));
    OP_REQUIRES_OK(ctx, ctx->input("a_shape", &a_shape));
    OP_REQUIRES_OK(ctx, ctx->input("b", &b));

    // Check that the dimensions of the two matrices are valid.
    OP_REQUIRES(ctx, TensorShapeUtils::IsMatrix(b->shape()),
                errors::InvalidArgument("Tensor 'b' is not a matrix"));

    OP_REQUIRES(ctx, TensorShapeUtils::IsVector(a_shape->shape()),
                errors::InvalidArgument("Tensor 'a_shape' is not a vector"));

    OP_REQUIRES(
        ctx, a_shape->NumElements() == 2,
        errors::InvalidArgument("Tensor 'a_shape' must have 2 elements"));

    OP_REQUIRES(ctx, TensorShapeUtils::IsVector(a_values->shape()),
                errors::InvalidArgument("Tensor 'a_values' is not a vector"));

    OP_REQUIRES(ctx, TensorShapeUtils::IsMatrix(a_indices->shape()),
                errors::InvalidArgument("Tensor 'a_indices' is not a matrix"));

    OP_REQUIRES(ctx, a_indices->shape().dim_size(0) == a_values->NumElements(),
                errors::InvalidArgument("Number of rows of a_indices does not "
                                        "match number of entries in a_values"));

    OP_REQUIRES(
        ctx, a_indices->shape().dim_size(1) == a_shape->NumElements(),
        errors::InvalidArgument("Number of columns of a_indices does not match "
                                "number of entries in a_shape"));

    auto a_shape_t = a_shape->vec<int64>();
    const int64 outer_left = (adjoint_a_) ? a_shape_t(1) : a_shape_t(0);
    const int64 outer_right =
        (adjoint_b_) ? b->shape().dim_size(0) : b->shape().dim_size(1);
    const int64 inner_left = (adjoint_a_) ? a_shape_t(0) : a_shape_t(1);
    const int64 inner_right =
        (adjoint_b_) ? b->shape().dim_size(1) : b->shape().dim_size(0);

    OP_REQUIRES(
        ctx, inner_right == inner_left,
        errors::InvalidArgument(
            "Cannot multiply A and B because inner dimension does not match: ",
            inner_left, " vs. ", inner_right,
            ".  Did you forget a transpose?  "
            "Dimensions of A: [",
            a_shape_t(0), ", ", a_shape_t(1), ").  Dimensions of B: ",
            b->shape().DebugString()));

    TensorShape out_shape({outer_left, outer_right});
    Tensor* out = nullptr;
    OP_REQUIRES_OK(ctx, ctx->allocate_output(0, out_shape, &out));

    if (out->NumElements() == 0) {
      // If a has shape [0, x] or b has shape [x, 0], the output shape
      // is a 0-element matrix, so there is nothing to do.
      return;
    }

    if (a_values->NumElements() == 0 || b->NumElements() == 0) {
      // If a has shape [x, 0] and b has shape [0, y], the
      // output shape is [x, y] where x and y are non-zero, so we fill
      // the output with zeros.
      functor::SetZeroFunctor<Device, T> f;
      f(ctx->eigen_device<Device>(), out->flat<T>());
      return;
    }

    Tensor scratch;

    if (std::is_same<Device, GPUDevice>::value) {
      // The GPU implementation is optimized to use 32 bit indexing, so
      // give a friendly error to the programmer early on if they exceed.
      OP_REQUIRES(
          ctx,
          FastBoundsCheck(inner_left, std::numeric_limits<int>::max()) &&
              FastBoundsCheck(inner_right, std::numeric_limits<int>::max()) &&
              FastBoundsCheck(outer_left, std::numeric_limits<int>::max()) &&
              FastBoundsCheck(outer_right, std::numeric_limits<int>::max()) &&
              FastBoundsCheck(b->NumElements(),
                              std::numeric_limits<int>::max()) &&
              FastBoundsCheck(out->NumElements(),
                              std::numeric_limits<int>::max()) &&
              FastBoundsCheck(a_values->NumElements(),
                              std::numeric_limits<int>::max()),
          errors::InvalidArgument("Cannot use GPU for > 2^31 entry inputs"));
      const int nnz = static_cast<const int>(a_values->NumElements());
      // Need nnz length vec scratch space on the GPU.
      OP_REQUIRES_OK(ctx, ctx->allocate_temp(DataTypeToEnum<T>::value,
                                             TensorShape({nnz}), &scratch));
    } else {
      // We don't need scratch space on the CPU.
      OP_REQUIRES_OK(ctx, ctx->allocate_temp(DataTypeToEnum<T>::value,
                                             TensorShape({0}), &scratch));
    }

#define MAYBE_ADJOINT(ADJ_A, ADJ_B)                                            \
  if (adjoint_a_ == ADJ_A && adjoint_b_ == ADJ_B) {                            \
    functor::SparseTensorDenseMatMulFunctor<Device, T, ADJ_A, ADJ_B>::Compute( \
        ctx->eigen_device<Device>(), out->matrix<T>(),                         \
        a_indices->matrix<int64>(), a_values->vec<T>(), b->matrix<T>(),        \
        scratch.vec<T>());                                                     \
  }

    MAYBE_ADJOINT(false, false);
    MAYBE_ADJOINT(false, true);
    MAYBE_ADJOINT(true, false);
    MAYBE_ADJOINT(true, true);

#undef MAYBE_ADJOINT
  }

 private:
  bool adjoint_a_;
  bool adjoint_b_;
};

#define REGISTER_CPU(T)                                   \
  REGISTER_KERNEL_BUILDER(Name("SparseTensorDenseMatMul") \
                              .Device(DEVICE_CPU)         \
                              .TypeConstraint<T>("T")     \
                              .HostMemory("a_shape"),     \
                          SparseTensorDenseMatMulOp<CPUDevice, T>);

REGISTER_CPU(float);
REGISTER_CPU(double);
REGISTER_CPU(int32);
REGISTER_CPU(complex64);
REGISTER_CPU(complex128);

#if GOOGLE_CUDA

namespace functor {
#define DECLARE_GPU_SPEC(T, ADJ_A, ADJ_B)                                    \
  template <>                                                                \
  void SparseTensorDenseMatMulFunctor<GPUDevice, T, ADJ_A, ADJ_B>::Compute(  \
      const GPUDevice& d, typename TTypes<T>::Matrix out,                    \
      TTypes<int64>::ConstMatrix a_indices,                                  \
      typename TTypes<T>::ConstVec a_values,                                 \
      typename TTypes<T>::ConstMatrix b, typename TTypes<T>::Vec scratch);   \
  extern template struct SparseTensorDenseMatMulFunctor<GPUDevice, T, ADJ_A, \
                                                        ADJ_B>;

#define DECLARE_ADJOINT_GPU_SPEC(T) \
  DECLARE_GPU_SPEC(T, false, false) \
  DECLARE_GPU_SPEC(T, false, true)  \
  DECLARE_GPU_SPEC(T, true, false)  \
  DECLARE_GPU_SPEC(T, true, true)

DECLARE_ADJOINT_GPU_SPEC(float);
#undef DECLARE_ADJOINT_GPU_SPEC
#undef DECLARE_GPU_SPEC

}  // namespace functor

#define REGISTER_GPU(T)                                   \
  REGISTER_KERNEL_BUILDER(Name("SparseTensorDenseMatMul") \
                              .Device(DEVICE_GPU)         \
                              .TypeConstraint<T>("T")     \
                              .HostMemory("a_shape"),     \
                          SparseTensorDenseMatMulOp<GPUDevice, T>);

REGISTER_GPU(float);
#undef REGISTER_GPU
#endif  // GOOGLE_CUDA

namespace functor {

template <typename T, bool ADJ_A, bool ADJ_B>
struct SparseTensorDenseMatMulFunctor<CPUDevice, T, ADJ_A, ADJ_B> {
  // Vectorize certain operations above this size.
  static const std::size_t kNumVectorize = 32;

  static void Compute(const CPUDevice& d, typename TTypes<T>::Matrix out,
                      TTypes<int64>::ConstMatrix a_indices,
                      typename TTypes<T>::ConstVec a_values,
                      typename TTypes<T>::ConstMatrix b,
                      typename TTypes<T>::Vec scratch) {
    const std::size_t nnz = a_values.size();
    const std::size_t rhs_right = (ADJ_B ? b.dimension(0) : b.dimension(1));
    const std::size_t lhs_right = (ADJ_B ? b.dimension(1) : b.dimension(0));
    const int lhs_index_a = ADJ_A ? 1 : 0;
    const int rhs_index_a = ADJ_A ? 0 : 1;

    out.setZero();

    // TODO(ebrevdo): After many failed experiments, can't find a multi-threaded
    // approach that achieves the performance of the single threaded
    // one.  Perhaps Eigen threadpool implementation is just too slow?

    if (rhs_right < kNumVectorize) {
      // Disable vectorization if the RHS of output is too small
      auto maybe_adjoint_b = MaybeAdjoint<decltype(b), ADJ_B>(b);
      for (std::size_t i = 0; i < nnz; ++i) {
        const int64 m = internal::SubtleMustCopy(a_indices(i, lhs_index_a));
        const int64 k = internal::SubtleMustCopy(a_indices(i, rhs_index_a));
        CHECK_LT(k, lhs_right);
        CHECK_LT(m, out.dimension(0));
        const T a_value = ADJ_A ? MaybeConj(a_values(i)) : a_values(i);
        for (std::size_t n = 0; n < rhs_right; ++n) {
          const T b_value = maybe_adjoint_b(k, n);
          out(m, n) += a_value * b_value;
        }
      }
    } else {
      // Vectorization via Eigen.
      const int b_chip_index = ADJ_B ? 1 : 0;

#define LOOP_NNZ(b_passed)                                               \
  for (std::size_t i = 0; i < nnz; ++i) {                                \
    const int64 m = internal::SubtleMustCopy(a_indices(i, lhs_index_a)); \
    const int64 k = internal::SubtleMustCopy(a_indices(i, rhs_index_a)); \
    const T a_value = (ADJ_A) ? MaybeConj(a_values(i)) : a_values(i);    \
    CHECK_LT(m, out.dimension(0));                                       \
    CHECK_LT(k, lhs_right);                                              \
    out.template chip<0>(m) +=                                           \
        b_passed.template chip<b_chip_index>(k) * a_value;               \
  }

      if (ADJ_B) {
        // Perform transpose and conjugation on B once, since we chip out B's
        // columns in the nnz loop.
        Eigen::array<int, 2> shuffle(1, 0);  // preserve dimension order
        Eigen::Tensor<T, 2, Eigen::ColMajor> col_major_conj_b =
            b.swap_layout().shuffle(shuffle).unaryExpr(
                Eigen::internal::scalar_conjugate_op<T>());

        LOOP_NNZ(col_major_conj_b);
      } else {
        LOOP_NNZ(b);
      }
#undef LOOP_NNZ
    }
  }
};

}  // namespace functor

}  // namespace tensorflow
<commit_msg>Tiny cleanup: Use .conjugate() method for Eigen Tensors. Change: 134120413<commit_after>/* Copyright 2015 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.
==============================================================================*/

// See docs in ../ops/math_ops.cc.

#define EIGEN_USE_THREADS

#include "tensorflow/core/kernels/sparse_tensor_dense_matmul_op.h"

#include "tensorflow/core/framework/op.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/kernels/bounds_check.h"
#include "tensorflow/core/kernels/fill_functor.h"

namespace tensorflow {

typedef Eigen::ThreadPoolDevice CPUDevice;
typedef Eigen::GpuDevice GPUDevice;

template <typename Device, typename T>
class SparseTensorDenseMatMulOp : public OpKernel {
 public:
  explicit SparseTensorDenseMatMulOp(OpKernelConstruction* ctx)
      : OpKernel(ctx) {
    OP_REQUIRES_OK(ctx, ctx->GetAttr("adjoint_a", &adjoint_a_));
    OP_REQUIRES_OK(ctx, ctx->GetAttr("adjoint_b", &adjoint_b_));
  }

  void Compute(OpKernelContext* ctx) override {
    const Tensor* a_indices;
    const Tensor* a_values;
    const Tensor* a_shape;
    const Tensor* b;
    OP_REQUIRES_OK(ctx, ctx->input("a_indices", &a_indices));
    OP_REQUIRES_OK(ctx, ctx->input("a_values", &a_values));
    OP_REQUIRES_OK(ctx, ctx->input("a_shape", &a_shape));
    OP_REQUIRES_OK(ctx, ctx->input("b", &b));

    // Check that the dimensions of the two matrices are valid.
    OP_REQUIRES(ctx, TensorShapeUtils::IsMatrix(b->shape()),
                errors::InvalidArgument("Tensor 'b' is not a matrix"));

    OP_REQUIRES(ctx, TensorShapeUtils::IsVector(a_shape->shape()),
                errors::InvalidArgument("Tensor 'a_shape' is not a vector"));

    OP_REQUIRES(
        ctx, a_shape->NumElements() == 2,
        errors::InvalidArgument("Tensor 'a_shape' must have 2 elements"));

    OP_REQUIRES(ctx, TensorShapeUtils::IsVector(a_values->shape()),
                errors::InvalidArgument("Tensor 'a_values' is not a vector"));

    OP_REQUIRES(ctx, TensorShapeUtils::IsMatrix(a_indices->shape()),
                errors::InvalidArgument("Tensor 'a_indices' is not a matrix"));

    OP_REQUIRES(ctx, a_indices->shape().dim_size(0) == a_values->NumElements(),
                errors::InvalidArgument("Number of rows of a_indices does not "
                                        "match number of entries in a_values"));

    OP_REQUIRES(
        ctx, a_indices->shape().dim_size(1) == a_shape->NumElements(),
        errors::InvalidArgument("Number of columns of a_indices does not match "
                                "number of entries in a_shape"));

    auto a_shape_t = a_shape->vec<int64>();
    const int64 outer_left = (adjoint_a_) ? a_shape_t(1) : a_shape_t(0);
    const int64 outer_right =
        (adjoint_b_) ? b->shape().dim_size(0) : b->shape().dim_size(1);
    const int64 inner_left = (adjoint_a_) ? a_shape_t(0) : a_shape_t(1);
    const int64 inner_right =
        (adjoint_b_) ? b->shape().dim_size(1) : b->shape().dim_size(0);

    OP_REQUIRES(
        ctx, inner_right == inner_left,
        errors::InvalidArgument(
            "Cannot multiply A and B because inner dimension does not match: ",
            inner_left, " vs. ", inner_right,
            ".  Did you forget a transpose?  "
            "Dimensions of A: [",
            a_shape_t(0), ", ", a_shape_t(1), ").  Dimensions of B: ",
            b->shape().DebugString()));

    TensorShape out_shape({outer_left, outer_right});
    Tensor* out = nullptr;
    OP_REQUIRES_OK(ctx, ctx->allocate_output(0, out_shape, &out));

    if (out->NumElements() == 0) {
      // If a has shape [0, x] or b has shape [x, 0], the output shape
      // is a 0-element matrix, so there is nothing to do.
      return;
    }

    if (a_values->NumElements() == 0 || b->NumElements() == 0) {
      // If a has shape [x, 0] and b has shape [0, y], the
      // output shape is [x, y] where x and y are non-zero, so we fill
      // the output with zeros.
      functor::SetZeroFunctor<Device, T> f;
      f(ctx->eigen_device<Device>(), out->flat<T>());
      return;
    }

    Tensor scratch;

    if (std::is_same<Device, GPUDevice>::value) {
      // The GPU implementation is optimized to use 32 bit indexing, so
      // give a friendly error to the programmer early on if they exceed.
      OP_REQUIRES(
          ctx,
          FastBoundsCheck(inner_left, std::numeric_limits<int>::max()) &&
              FastBoundsCheck(inner_right, std::numeric_limits<int>::max()) &&
              FastBoundsCheck(outer_left, std::numeric_limits<int>::max()) &&
              FastBoundsCheck(outer_right, std::numeric_limits<int>::max()) &&
              FastBoundsCheck(b->NumElements(),
                              std::numeric_limits<int>::max()) &&
              FastBoundsCheck(out->NumElements(),
                              std::numeric_limits<int>::max()) &&
              FastBoundsCheck(a_values->NumElements(),
                              std::numeric_limits<int>::max()),
          errors::InvalidArgument("Cannot use GPU for > 2^31 entry inputs"));
      const int nnz = static_cast<const int>(a_values->NumElements());
      // Need nnz length vec scratch space on the GPU.
      OP_REQUIRES_OK(ctx, ctx->allocate_temp(DataTypeToEnum<T>::value,
                                             TensorShape({nnz}), &scratch));
    } else {
      // We don't need scratch space on the CPU.
      OP_REQUIRES_OK(ctx, ctx->allocate_temp(DataTypeToEnum<T>::value,
                                             TensorShape({0}), &scratch));
    }

#define MAYBE_ADJOINT(ADJ_A, ADJ_B)                                            \
  if (adjoint_a_ == ADJ_A && adjoint_b_ == ADJ_B) {                            \
    functor::SparseTensorDenseMatMulFunctor<Device, T, ADJ_A, ADJ_B>::Compute( \
        ctx->eigen_device<Device>(), out->matrix<T>(),                         \
        a_indices->matrix<int64>(), a_values->vec<T>(), b->matrix<T>(),        \
        scratch.vec<T>());                                                     \
  }

    MAYBE_ADJOINT(false, false);
    MAYBE_ADJOINT(false, true);
    MAYBE_ADJOINT(true, false);
    MAYBE_ADJOINT(true, true);

#undef MAYBE_ADJOINT
  }

 private:
  bool adjoint_a_;
  bool adjoint_b_;
};

#define REGISTER_CPU(T)                                   \
  REGISTER_KERNEL_BUILDER(Name("SparseTensorDenseMatMul") \
                              .Device(DEVICE_CPU)         \
                              .TypeConstraint<T>("T")     \
                              .HostMemory("a_shape"),     \
                          SparseTensorDenseMatMulOp<CPUDevice, T>);

REGISTER_CPU(float);
REGISTER_CPU(double);
REGISTER_CPU(int32);
REGISTER_CPU(complex64);
REGISTER_CPU(complex128);

#if GOOGLE_CUDA

namespace functor {
#define DECLARE_GPU_SPEC(T, ADJ_A, ADJ_B)                                    \
  template <>                                                                \
  void SparseTensorDenseMatMulFunctor<GPUDevice, T, ADJ_A, ADJ_B>::Compute(  \
      const GPUDevice& d, typename TTypes<T>::Matrix out,                    \
      TTypes<int64>::ConstMatrix a_indices,                                  \
      typename TTypes<T>::ConstVec a_values,                                 \
      typename TTypes<T>::ConstMatrix b, typename TTypes<T>::Vec scratch);   \
  extern template struct SparseTensorDenseMatMulFunctor<GPUDevice, T, ADJ_A, \
                                                        ADJ_B>;

#define DECLARE_ADJOINT_GPU_SPEC(T) \
  DECLARE_GPU_SPEC(T, false, false) \
  DECLARE_GPU_SPEC(T, false, true)  \
  DECLARE_GPU_SPEC(T, true, false)  \
  DECLARE_GPU_SPEC(T, true, true)

DECLARE_ADJOINT_GPU_SPEC(float);
#undef DECLARE_ADJOINT_GPU_SPEC
#undef DECLARE_GPU_SPEC

}  // namespace functor

#define REGISTER_GPU(T)                                   \
  REGISTER_KERNEL_BUILDER(Name("SparseTensorDenseMatMul") \
                              .Device(DEVICE_GPU)         \
                              .TypeConstraint<T>("T")     \
                              .HostMemory("a_shape"),     \
                          SparseTensorDenseMatMulOp<GPUDevice, T>);

REGISTER_GPU(float);
#undef REGISTER_GPU
#endif  // GOOGLE_CUDA

namespace functor {

template <typename T, bool ADJ_A, bool ADJ_B>
struct SparseTensorDenseMatMulFunctor<CPUDevice, T, ADJ_A, ADJ_B> {
  // Vectorize certain operations above this size.
  static const std::size_t kNumVectorize = 32;

  static void Compute(const CPUDevice& d, typename TTypes<T>::Matrix out,
                      TTypes<int64>::ConstMatrix a_indices,
                      typename TTypes<T>::ConstVec a_values,
                      typename TTypes<T>::ConstMatrix b,
                      typename TTypes<T>::Vec scratch) {
    const std::size_t nnz = a_values.size();
    const std::size_t rhs_right = (ADJ_B ? b.dimension(0) : b.dimension(1));
    const std::size_t lhs_right = (ADJ_B ? b.dimension(1) : b.dimension(0));
    const int lhs_index_a = ADJ_A ? 1 : 0;
    const int rhs_index_a = ADJ_A ? 0 : 1;

    out.setZero();

    // TODO(ebrevdo): After many failed experiments, can't find a multi-threaded
    // approach that achieves the performance of the single threaded
    // one.  Perhaps Eigen threadpool implementation is just too slow?

    if (rhs_right < kNumVectorize) {
      // Disable vectorization if the RHS of output is too small
      auto maybe_adjoint_b = MaybeAdjoint<decltype(b), ADJ_B>(b);
      for (std::size_t i = 0; i < nnz; ++i) {
        const int64 m = internal::SubtleMustCopy(a_indices(i, lhs_index_a));
        const int64 k = internal::SubtleMustCopy(a_indices(i, rhs_index_a));
        CHECK_LT(k, lhs_right);
        CHECK_LT(m, out.dimension(0));
        const T a_value = ADJ_A ? MaybeConj(a_values(i)) : a_values(i);
        for (std::size_t n = 0; n < rhs_right; ++n) {
          const T b_value = maybe_adjoint_b(k, n);
          out(m, n) += a_value * b_value;
        }
      }
    } else {
      // Vectorization via Eigen.
      const int b_chip_index = ADJ_B ? 1 : 0;

#define LOOP_NNZ(b_passed)                                               \
  for (std::size_t i = 0; i < nnz; ++i) {                                \
    const int64 m = internal::SubtleMustCopy(a_indices(i, lhs_index_a)); \
    const int64 k = internal::SubtleMustCopy(a_indices(i, rhs_index_a)); \
    const T a_value = (ADJ_A) ? MaybeConj(a_values(i)) : a_values(i);    \
    CHECK_LT(m, out.dimension(0));                                       \
    CHECK_LT(k, lhs_right);                                              \
    out.template chip<0>(m) +=                                           \
        b_passed.template chip<b_chip_index>(k) * a_value;               \
  }

      if (ADJ_B) {
        // Perform transpose and conjugation on B once, since we chip out B's
        // columns in the nnz loop.
        Eigen::array<int, 2> shuffle(1, 0);  // preserve dimension order
        Eigen::Tensor<T, 2, Eigen::ColMajor> col_major_conj_b =
            b.swap_layout().shuffle(shuffle).conjugate();
        LOOP_NNZ(col_major_conj_b);
      } else {
        LOOP_NNZ(b);
      }
#undef LOOP_NNZ
    }
  }
};

}  // namespace functor

}  // namespace tensorflow
<|endoftext|>


<commit_before>/*
 * Copyright 2019 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/gpu/GrRecordingContext.h"

#include "include/gpu/GrContextThreadSafeProxy.h"
#include "src/core/SkArenaAlloc.h"
#include "src/gpu/GrAuditTrail.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrContextThreadSafeProxyPriv.h"
#include "src/gpu/GrDrawingManager.h"
#include "src/gpu/GrMemoryPool.h"
#include "src/gpu/GrProgramDesc.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrSurfaceContext.h"
#include "src/gpu/GrSurfaceDrawContext.h"
#include "src/gpu/SkGr.h"
#include "src/gpu/effects/GrSkSLFP.h"
#include "src/gpu/ops/GrAtlasTextOp.h"
#include "src/gpu/text/GrTextBlob.h"
#include "src/gpu/text/GrTextBlobCache.h"

GrRecordingContext::ProgramData::ProgramData(std::unique_ptr<const GrProgramDesc> desc,
                                             const GrProgramInfo* info)
        : fDesc(std::move(desc))
        , fInfo(info) {
}

GrRecordingContext::ProgramData::ProgramData(ProgramData&& other)
        : fDesc(std::move(other.fDesc))
        , fInfo(other.fInfo) {
}

GrRecordingContext::ProgramData::~ProgramData() = default;

GrRecordingContext::GrRecordingContext(sk_sp<GrContextThreadSafeProxy> proxy)
        : INHERITED(std::move(proxy))
        , fAuditTrail(new GrAuditTrail()) {
    fProxyProvider = std::make_unique<GrProxyProvider>(this);
}

GrRecordingContext::~GrRecordingContext() {
    GrAtlasTextOp::ClearCache();
}

int GrRecordingContext::maxSurfaceSampleCountForColorType(SkColorType colorType) const {
    GrBackendFormat format =
            this->caps()->getDefaultBackendFormat(SkColorTypeToGrColorType(colorType),
                                                  GrRenderable::kYes);
    return this->caps()->maxRenderTargetSampleCount(format);
}

bool GrRecordingContext::init() {
    if (!INHERITED::init()) {
        return false;
    }

    GrPathRendererChain::Options prcOptions;
    prcOptions.fAllowPathMaskCaching = this->options().fAllowPathMaskCaching;
#if GR_TEST_UTILS
    prcOptions.fGpuPathRenderers = this->options().fGpuPathRenderers;
#endif
    // FIXME: Once this is removed from Chrome and Android, rename to fEnable"".
    if (this->options().fDisableDistanceFieldPaths) {
        prcOptions.fGpuPathRenderers &= ~GpuPathRenderers::kSmall;
    }

    bool reduceOpsTaskSplitting = false;
    if (GrContextOptions::Enable::kYes == this->options().fReduceOpsTaskSplitting) {
        reduceOpsTaskSplitting = true;
    } else if (GrContextOptions::Enable::kNo == this->options().fReduceOpsTaskSplitting) {
        reduceOpsTaskSplitting = false;
    }
    fDrawingManager.reset(new GrDrawingManager(this,
                                               prcOptions,
                                               reduceOpsTaskSplitting));
    return true;
}

void GrRecordingContext::abandonContext() {
    INHERITED::abandonContext();

    this->destroyDrawingManager();
}

GrDrawingManager* GrRecordingContext::drawingManager() {
    return fDrawingManager.get();
}

void GrRecordingContext::destroyDrawingManager() {
    fDrawingManager.reset();
}

GrRecordingContext::Arenas::Arenas(SkArenaAlloc* recordTimeAllocator,
                                   GrSubRunAllocator* subRunAllocator)
        : fRecordTimeAllocator(recordTimeAllocator)
        , fRecordTimeSubRunAllocator(subRunAllocator) {
    // OwnedArenas should instantiate these before passing the bare pointer off to this struct.
    SkASSERT(recordTimeAllocator);
    SkASSERT(subRunAllocator);
}

// Must be defined here so that std::unique_ptr can see the sizes of the various pools, otherwise
// it can't generate a default destructor for them.
GrRecordingContext::OwnedArenas::OwnedArenas() {}
GrRecordingContext::OwnedArenas::~OwnedArenas() {}

GrRecordingContext::OwnedArenas& GrRecordingContext::OwnedArenas::operator=(OwnedArenas&& a) {
    fRecordTimeAllocator = std::move(a.fRecordTimeAllocator);
    fRecordTimeSubRunAllocator = std::move(a.fRecordTimeSubRunAllocator);
    return *this;
}

GrRecordingContext::Arenas GrRecordingContext::OwnedArenas::get() {
    if (!fRecordTimeAllocator) {
        // TODO: empirically determine a better number for SkArenaAlloc's firstHeapAllocation param
        fRecordTimeAllocator = std::make_unique<SkArenaAlloc>(sizeof(GrPipeline) * 100);
    }

    if (!fRecordTimeSubRunAllocator) {
        fRecordTimeSubRunAllocator = std::make_unique<GrSubRunAllocator>();
    }

    return {fRecordTimeAllocator.get(), fRecordTimeSubRunAllocator.get()};
}

GrRecordingContext::OwnedArenas&& GrRecordingContext::detachArenas() {
    return std::move(fArenas);
}

GrTextBlobCache* GrRecordingContext::getTextBlobCache() {
    return fThreadSafeProxy->priv().getTextBlobCache();
}

const GrTextBlobCache* GrRecordingContext::getTextBlobCache() const {
    return fThreadSafeProxy->priv().getTextBlobCache();
}

GrThreadSafeCache* GrRecordingContext::threadSafeCache() {
    return fThreadSafeProxy->priv().threadSafeCache();
}

const GrThreadSafeCache* GrRecordingContext::threadSafeCache() const {
    return fThreadSafeProxy->priv().threadSafeCache();
}

void GrRecordingContext::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) {
    this->drawingManager()->addOnFlushCallbackObject(onFlushCBObject);
}

////////////////////////////////////////////////////////////////////////////////

int GrRecordingContext::maxTextureSize() const { return this->caps()->maxTextureSize(); }

int GrRecordingContext::maxRenderTargetSize() const { return this->caps()->maxRenderTargetSize(); }

bool GrRecordingContext::colorTypeSupportedAsImage(SkColorType colorType) const {
    GrBackendFormat format =
            this->caps()->getDefaultBackendFormat(SkColorTypeToGrColorType(colorType),
                                                  GrRenderable::kNo);
    return format.isValid();
}

///////////////////////////////////////////////////////////////////////////////////////////////////
sk_sp<const GrCaps> GrRecordingContextPriv::refCaps() const {
    return fContext->refCaps();
}

void GrRecordingContextPriv::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) {
    fContext->addOnFlushCallbackObject(onFlushCBObject);
}

///////////////////////////////////////////////////////////////////////////////////////////////////

#ifdef SK_ENABLE_DUMP_GPU
#include "src/utils/SkJSONWriter.h"

void GrRecordingContext::dumpJSON(SkJSONWriter* writer) const {
    writer->beginObject();

#if GR_GPU_STATS
    writer->appendS32("path_masks_generated", this->stats()->numPathMasksGenerated());
    writer->appendS32("path_mask_cache_hits", this->stats()->numPathMaskCacheHits());
#endif

    writer->endObject();
}
#else
void GrRecordingContext::dumpJSON(SkJSONWriter*) const { }
#endif

#if GR_TEST_UTILS

#if GR_GPU_STATS

void GrRecordingContext::Stats::dump(SkString* out) {
    out->appendf("Num Path Masks Generated: %d\n", fNumPathMasksGenerated);
    out->appendf("Num Path Mask Cache Hits: %d\n", fNumPathMaskCacheHits);
}

void GrRecordingContext::Stats::dumpKeyValuePairs(SkTArray<SkString>* keys,
                                                  SkTArray<double>* values) {
    keys->push_back(SkString("path_masks_generated"));
    values->push_back(fNumPathMasksGenerated);

    keys->push_back(SkString("path_mask_cache_hits"));
    values->push_back(fNumPathMaskCacheHits);
}

#endif // GR_GPU_STATS
#endif // GR_TEST_UTILS

<commit_msg>reduce record time allocator's initial block size<commit_after>/*
 * Copyright 2019 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/gpu/GrRecordingContext.h"

#include "include/gpu/GrContextThreadSafeProxy.h"
#include "src/core/SkArenaAlloc.h"
#include "src/gpu/GrAuditTrail.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrContextThreadSafeProxyPriv.h"
#include "src/gpu/GrDrawingManager.h"
#include "src/gpu/GrMemoryPool.h"
#include "src/gpu/GrProgramDesc.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrSurfaceContext.h"
#include "src/gpu/GrSurfaceDrawContext.h"
#include "src/gpu/SkGr.h"
#include "src/gpu/effects/GrSkSLFP.h"
#include "src/gpu/ops/GrAtlasTextOp.h"
#include "src/gpu/text/GrTextBlob.h"
#include "src/gpu/text/GrTextBlobCache.h"

GrRecordingContext::ProgramData::ProgramData(std::unique_ptr<const GrProgramDesc> desc,
                                             const GrProgramInfo* info)
        : fDesc(std::move(desc))
        , fInfo(info) {
}

GrRecordingContext::ProgramData::ProgramData(ProgramData&& other)
        : fDesc(std::move(other.fDesc))
        , fInfo(other.fInfo) {
}

GrRecordingContext::ProgramData::~ProgramData() = default;

GrRecordingContext::GrRecordingContext(sk_sp<GrContextThreadSafeProxy> proxy)
        : INHERITED(std::move(proxy))
        , fAuditTrail(new GrAuditTrail()) {
    fProxyProvider = std::make_unique<GrProxyProvider>(this);
}

GrRecordingContext::~GrRecordingContext() {
    GrAtlasTextOp::ClearCache();
}

int GrRecordingContext::maxSurfaceSampleCountForColorType(SkColorType colorType) const {
    GrBackendFormat format =
            this->caps()->getDefaultBackendFormat(SkColorTypeToGrColorType(colorType),
                                                  GrRenderable::kYes);
    return this->caps()->maxRenderTargetSampleCount(format);
}

bool GrRecordingContext::init() {
    if (!INHERITED::init()) {
        return false;
    }

    GrPathRendererChain::Options prcOptions;
    prcOptions.fAllowPathMaskCaching = this->options().fAllowPathMaskCaching;
#if GR_TEST_UTILS
    prcOptions.fGpuPathRenderers = this->options().fGpuPathRenderers;
#endif
    // FIXME: Once this is removed from Chrome and Android, rename to fEnable"".
    if (this->options().fDisableDistanceFieldPaths) {
        prcOptions.fGpuPathRenderers &= ~GpuPathRenderers::kSmall;
    }

    bool reduceOpsTaskSplitting = false;
    if (GrContextOptions::Enable::kYes == this->options().fReduceOpsTaskSplitting) {
        reduceOpsTaskSplitting = true;
    } else if (GrContextOptions::Enable::kNo == this->options().fReduceOpsTaskSplitting) {
        reduceOpsTaskSplitting = false;
    }
    fDrawingManager.reset(new GrDrawingManager(this,
                                               prcOptions,
                                               reduceOpsTaskSplitting));
    return true;
}

void GrRecordingContext::abandonContext() {
    INHERITED::abandonContext();

    this->destroyDrawingManager();
}

GrDrawingManager* GrRecordingContext::drawingManager() {
    return fDrawingManager.get();
}

void GrRecordingContext::destroyDrawingManager() {
    fDrawingManager.reset();
}

GrRecordingContext::Arenas::Arenas(SkArenaAlloc* recordTimeAllocator,
                                   GrSubRunAllocator* subRunAllocator)
        : fRecordTimeAllocator(recordTimeAllocator)
        , fRecordTimeSubRunAllocator(subRunAllocator) {
    // OwnedArenas should instantiate these before passing the bare pointer off to this struct.
    SkASSERT(recordTimeAllocator);
    SkASSERT(subRunAllocator);
}

// Must be defined here so that std::unique_ptr can see the sizes of the various pools, otherwise
// it can't generate a default destructor for them.
GrRecordingContext::OwnedArenas::OwnedArenas() {}
GrRecordingContext::OwnedArenas::~OwnedArenas() {}

GrRecordingContext::OwnedArenas& GrRecordingContext::OwnedArenas::operator=(OwnedArenas&& a) {
    fRecordTimeAllocator = std::move(a.fRecordTimeAllocator);
    fRecordTimeSubRunAllocator = std::move(a.fRecordTimeSubRunAllocator);
    return *this;
}

GrRecordingContext::Arenas GrRecordingContext::OwnedArenas::get() {
    if (!fRecordTimeAllocator) {
        // TODO: empirically determine a better number for SkArenaAlloc's firstHeapAllocation param
        fRecordTimeAllocator = std::make_unique<SkArenaAlloc>(1024);
    }

    if (!fRecordTimeSubRunAllocator) {
        fRecordTimeSubRunAllocator = std::make_unique<GrSubRunAllocator>();
    }

    return {fRecordTimeAllocator.get(), fRecordTimeSubRunAllocator.get()};
}

GrRecordingContext::OwnedArenas&& GrRecordingContext::detachArenas() {
    return std::move(fArenas);
}

GrTextBlobCache* GrRecordingContext::getTextBlobCache() {
    return fThreadSafeProxy->priv().getTextBlobCache();
}

const GrTextBlobCache* GrRecordingContext::getTextBlobCache() const {
    return fThreadSafeProxy->priv().getTextBlobCache();
}

GrThreadSafeCache* GrRecordingContext::threadSafeCache() {
    return fThreadSafeProxy->priv().threadSafeCache();
}

const GrThreadSafeCache* GrRecordingContext::threadSafeCache() const {
    return fThreadSafeProxy->priv().threadSafeCache();
}

void GrRecordingContext::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) {
    this->drawingManager()->addOnFlushCallbackObject(onFlushCBObject);
}

////////////////////////////////////////////////////////////////////////////////

int GrRecordingContext::maxTextureSize() const { return this->caps()->maxTextureSize(); }

int GrRecordingContext::maxRenderTargetSize() const { return this->caps()->maxRenderTargetSize(); }

bool GrRecordingContext::colorTypeSupportedAsImage(SkColorType colorType) const {
    GrBackendFormat format =
            this->caps()->getDefaultBackendFormat(SkColorTypeToGrColorType(colorType),
                                                  GrRenderable::kNo);
    return format.isValid();
}

///////////////////////////////////////////////////////////////////////////////////////////////////
sk_sp<const GrCaps> GrRecordingContextPriv::refCaps() const {
    return fContext->refCaps();
}

void GrRecordingContextPriv::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) {
    fContext->addOnFlushCallbackObject(onFlushCBObject);
}

///////////////////////////////////////////////////////////////////////////////////////////////////

#ifdef SK_ENABLE_DUMP_GPU
#include "src/utils/SkJSONWriter.h"

void GrRecordingContext::dumpJSON(SkJSONWriter* writer) const {
    writer->beginObject();

#if GR_GPU_STATS
    writer->appendS32("path_masks_generated", this->stats()->numPathMasksGenerated());
    writer->appendS32("path_mask_cache_hits", this->stats()->numPathMaskCacheHits());
#endif

    writer->endObject();
}
#else
void GrRecordingContext::dumpJSON(SkJSONWriter*) const { }
#endif

#if GR_TEST_UTILS

#if GR_GPU_STATS

void GrRecordingContext::Stats::dump(SkString* out) {
    out->appendf("Num Path Masks Generated: %d\n", fNumPathMasksGenerated);
    out->appendf("Num Path Mask Cache Hits: %d\n", fNumPathMaskCacheHits);
}

void GrRecordingContext::Stats::dumpKeyValuePairs(SkTArray<SkString>* keys,
                                                  SkTArray<double>* values) {
    keys->push_back(SkString("path_masks_generated"));
    values->push_back(fNumPathMasksGenerated);

    keys->push_back(SkString("path_mask_cache_hits"));
    values->push_back(fNumPathMaskCacheHits);
}

#endif // GR_GPU_STATS
#endif // GR_TEST_UTILS

<|endoftext|>


<commit_before>8190619e-4b02-11e5-80bb-28cfe9171a43<commit_msg>oh my, I hate charles<commit_after>819dd11c-4b02-11e5-812c-28cfe9171a43<|endoftext|>


<commit_before>#include <fstream>
#include <string>

#include <vpr/DynLoad/Library.h>
#include <vpr/System.h>
#include <modules/TestInterface.h>

#include <LibraryTest.h>

namespace vprTest
{

static const std::string C_MOD("libcmod.so");

void LibraryTest::setUp()
{
   std::string c_lib_path(MODULE_DIR);
   c_lib_path += "/" + C_MOD;
   mCModuleName = c_lib_path;

   std::string cxx_lib_path(MODULE_DIR);
   cxx_lib_path += "/libcxxmod.so";
   mCxxModuleName = cxx_lib_path;
}

void LibraryTest::namingTest()
{
   const std::string lib_name("libTest.so");

   vpr::Library lib(lib_name);
   CPPUNIT_ASSERT(lib.getName() == lib_name && "Names do not match");
}

void LibraryTest::loadTest()
{
   // Test for library existence.  This could be done better.
   std::ifstream mod_file;
   mod_file.open(mCModuleName.c_str());
   CPPUNIT_ASSERT(mod_file.good() && "Module does not exist");
   mod_file.close();

   vpr::ReturnStatus status;
   vpr::Library c_lib(mCModuleName);
   status = c_lib.load();
   CPPUNIT_ASSERT(status.success() && "Load failed");
}

void LibraryTest::unloadTest()
{
   // Test for library existence.  This could be done better.
   std::ifstream mod_file;
   mod_file.open(mCModuleName.c_str());
   CPPUNIT_ASSERT(mod_file.good() && "Module does not exist");
   mod_file.close();

   vpr::ReturnStatus status;
   vpr::Library c_lib(mCModuleName);
   status = c_lib.load();
   CPPUNIT_ASSERT(status.success() && "Load failed");

   status = c_lib.unload();
   CPPUNIT_ASSERT(status.success() && "Unload failed");
}

void LibraryTest::libraryPathTest()
{
   vpr::ReturnStatus status;
   vpr::Library lib(C_MOD);

   status = vpr::System::setenv(std::string("LD_LIBRARY_PATH"),
                                std::string(MODULE_DIR));
   CPPUNIT_ASSERT(status.success() && "Failed to extend library path");

   status = lib.load();
   CPPUNIT_ASSERT(status.success() && "Library load failed");
}

void LibraryTest::loadCSymbolTest()
{
   vpr::Library c_lib(mCModuleName);
   int (*test_func)();

   vpr::ReturnStatus status;
   status = c_lib.load();
   CPPUNIT_ASSERT(status.success() && "C module load failed");

   // This is the weirdest cast I have ever written.
   test_func = (int(*)()) c_lib.findSymbol("function");
   CPPUNIT_ASSERT(NULL != test_func && "Symbol lookup failed");

   int result = (*test_func)();
   CPPUNIT_ASSERT(1 == result && "Wrong result from loaded function");

   test_func = (int(*)()) c_lib.findSymbol("bogusFunc");
   CPPUNIT_ASSERT(NULL == test_func && "Found non-existent symbol");

   status = c_lib.unload();
   CPPUNIT_ASSERT(status.success() && "C module unload failed");
}

void LibraryTest::loadCxxSymbolTest()
{
   vpr::Library cxx_lib(mCxxModuleName);
   void* (*creator)();
   TestInterface* test_obj;

   vpr::ReturnStatus status;
   status = cxx_lib.load();
   CPPUNIT_ASSERT(status.success() && "C++ module load failed");

   // No, *this* is the weirdest cast I have ever written.
   creator = (void*(*)()) cxx_lib.findSymbol("entryFunc");
   CPPUNIT_ASSERT(NULL != creator && "Entry point lookup failed");

   void* object = (*creator)();
   CPPUNIT_ASSERT(NULL != test_obj && "Object creation failed");

   // Is there a way to test that this cast was successful?
   test_obj = static_cast<TestInterface*>(object);
//   CPPUNIT_ASSERT(NULL != test_obj && "Dynamic casting of created object failed");

   CPPUNIT_ASSERT(test_obj->function() == true && "Unexpected results from TestInterface object");

   status = cxx_lib.unload();
   CPPUNIT_ASSERT(status.success() && "C++ module unload failed");
}

}
<commit_msg>Bug fixed:	The wrong pointer value was tested after the creator 		function was called.<commit_after>#include <fstream>
#include <string>

#include <vpr/DynLoad/Library.h>
#include <vpr/System.h>
#include <modules/TestInterface.h>

#include <LibraryTest.h>

namespace vprTest
{

static const std::string C_MOD("libcmod.so");

void LibraryTest::setUp()
{
   std::string c_lib_path(MODULE_DIR);
   c_lib_path += "/" + C_MOD;
   mCModuleName = c_lib_path;

   std::string cxx_lib_path(MODULE_DIR);
   cxx_lib_path += "/libcxxmod.so";
   mCxxModuleName = cxx_lib_path;
}

void LibraryTest::namingTest()
{
   const std::string lib_name("libTest.so");

   vpr::Library lib(lib_name);
   CPPUNIT_ASSERT(lib.getName() == lib_name && "Names do not match");
}

void LibraryTest::loadTest()
{
   // Test for library existence.  This could be done better.
   std::ifstream mod_file;
   mod_file.open(mCModuleName.c_str());
   CPPUNIT_ASSERT(mod_file.good() && "Module does not exist");
   mod_file.close();

   vpr::ReturnStatus status;
   vpr::Library c_lib(mCModuleName);
   status = c_lib.load();
   CPPUNIT_ASSERT(status.success() && "Load failed");
}

void LibraryTest::unloadTest()
{
   // Test for library existence.  This could be done better.
   std::ifstream mod_file;
   mod_file.open(mCModuleName.c_str());
   CPPUNIT_ASSERT(mod_file.good() && "Module does not exist");
   mod_file.close();

   vpr::ReturnStatus status;
   vpr::Library c_lib(mCModuleName);
   status = c_lib.load();
   CPPUNIT_ASSERT(status.success() && "Load failed");

   status = c_lib.unload();
   CPPUNIT_ASSERT(status.success() && "Unload failed");
}

void LibraryTest::libraryPathTest()
{
   vpr::ReturnStatus status;
   vpr::Library lib(C_MOD);

   status = vpr::System::setenv(std::string("LD_LIBRARY_PATH"),
                                std::string(MODULE_DIR));
   CPPUNIT_ASSERT(status.success() && "Failed to extend library path");

   status = lib.load();
   CPPUNIT_ASSERT(status.success() && "Library load failed");
}

void LibraryTest::loadCSymbolTest()
{
   vpr::Library c_lib(mCModuleName);
   int (*test_func)();

   vpr::ReturnStatus status;
   status = c_lib.load();
   CPPUNIT_ASSERT(status.success() && "C module load failed");

   // This is the weirdest cast I have ever written.
   test_func = (int(*)()) c_lib.findSymbol("function");
   CPPUNIT_ASSERT(NULL != test_func && "Symbol lookup failed");

   int result = (*test_func)();
   CPPUNIT_ASSERT(1 == result && "Wrong result from loaded function");

   test_func = (int(*)()) c_lib.findSymbol("bogusFunc");
   CPPUNIT_ASSERT(NULL == test_func && "Found non-existent symbol");

   status = c_lib.unload();
   CPPUNIT_ASSERT(status.success() && "C module unload failed");
}

void LibraryTest::loadCxxSymbolTest()
{
   vpr::Library cxx_lib(mCxxModuleName);
   void* (*creator)();
   TestInterface* test_obj(NULL);

   vpr::ReturnStatus status;
   status = cxx_lib.load();
   CPPUNIT_ASSERT(status.success() && "C++ module load failed");

   // No, *this* is the weirdest cast I have ever written.
   creator = (void*(*)()) cxx_lib.findSymbol("entryFunc");
   CPPUNIT_ASSERT(NULL != creator && "Entry point lookup failed");

   void* object = (*creator)();
   CPPUNIT_ASSERT(NULL != object && "Object creation failed");

   // Is there a way to test that this cast was successful?
   test_obj = static_cast<TestInterface*>(object);
//   CPPUNIT_ASSERT(NULL != test_obj && "Dynamic casting of created object failed");

   CPPUNIT_ASSERT(test_obj->function() == true && "Unexpected results from TestInterface object");

   status = cxx_lib.unload();
   CPPUNIT_ASSERT(status.success() && "C++ module unload failed");
}

}
<|endoftext|>


<commit_before>#include "aquila/global.h"
#include "aquila/source/generator/SquareGenerator.h"
#include "aquila/source/SignalSource.h"
#include "aquila/transform/FftFactory.h"
#include "aquila/tools/TextPlot.h"
#include "aquila/source/WaveFile.h"
#include <algorithm>
#include <functional>
#include <memory>
#include <iostream>
#include <cstdlib>
using namespace std;

const std::size_t SIZE = 512;

void findMax(Aquila::SpectrumType spectrum, Aquila::FrequencyType sampleFreq)
    {
        std::size_t halfLength = spectrum.size() / 2;
        std::vector<double> absSpectrum(halfLength);
        double max = 0;
        int peak_freq  = 0;
        for (std::size_t i = 0; i < halfLength; ++i)
        {
            absSpectrum[i] = std::abs(spectrum[i]);
            //cout << i*(sampleFreq/halfLength)<< " amp " <<absSpectrum[i] << endl;
            if(absSpectrum[i] > max){
                max = absSpectrum[i];
                peak_freq = i*(sampleFreq/halfLength)/2;
            }
        }
        cout << "\n\npeak freq for input with sample size: "<< halfLength*2 << " which needs to be pow of 2" <<endl;
        cout <<peak_freq << " Hz max amp:" << max << endl;
        //plot(absSpectrum);
    }

void freqOfindex(std::size_t start, Aquila::WaveFile wav){
    Aquila::FrequencyType sampleFreq = wav.getSampleFrequency();
    vector<Aquila::SampleType> chunk;
    for (std::size_t i =start; i< start+SIZE; ++i)
    {

        chunk.push_back(wav.sample(i));

    }
    Aquila::SignalSource data(chunk, sampleFreq);

    Aquila::TextPlot plt("input wave");

    auto fft = Aquila::FftFactory::getFft(SIZE);
    Aquila::SpectrumType spectrum = fft->fft(data.toArray());
    plt.setTitle("Signal spectrum of "+ std::to_string(start));

    findMax(spectrum, sampleFreq);
    plt.plotSpectrum(spectrum);

}

int main(int argc, char *argv[])
{
	if (argc < 2)
    {
        std::cout << "Usage: main <FILENAME>" << std::endl;
        return 1;
    }

    Aquila::WaveFile wav(argv[1]);

    const std::size_t END = wav.getSamplesCount();
    std::size_t start = 0;

    while(start < END && wav.sample(start) <= 1000 ) start++;
    //220500
    cout << END <<endl;
    cout << start;

    for(int x = start; x < END; x+=END/5) freqOfindex(x, wav);

    return 0;
}
<commit_msg>track max freq<commit_after>#include "aquila/global.h"
#include "aquila/source/generator/SquareGenerator.h"
#include "aquila/source/SignalSource.h"
#include "aquila/transform/FftFactory.h"
#include "aquila/tools/TextPlot.h"
#include "aquila/source/WaveFile.h"
#include <algorithm>
#include <functional>
#include <memory>
#include <iostream>
#include <cstdlib>
using namespace std;

const std::size_t SIZE = 512;

void findMax(Aquila::SpectrumType spectrum, Aquila::FrequencyType sampleFreq)
    {
        std::size_t halfLength = spectrum.size() / 2;
        std::vector<double> absSpectrum(halfLength);
        double max = 0;
        int peak_freq  = 0;
        for (std::size_t i = 0; i < halfLength; ++i)
        {
            absSpectrum[i] = std::abs(spectrum[i]);
            //cout << i*(sampleFreq/halfLength)<< " amp " <<absSpectrum[i] << endl;
            if(absSpectrum[i] > max){
                max = absSpectrum[i];
                peak_freq = i*(sampleFreq/halfLength)/2;
            }
        }
        cout << "peak freq for input with sample size: "<< halfLength*2 << " which needs to be pow of 2" <<endl;
        cout <<peak_freq << " Hz max amp:" << max << endl;
        //plot(absSpectrum);
    }

void freqOfindex(std::size_t start, Aquila::WaveFile wav){
    Aquila::FrequencyType sampleFreq = wav.getSampleFrequency();
    vector<Aquila::SampleType> chunk;
    for (std::size_t i =start; i< start+SIZE; ++i)
    {

        chunk.push_back(wav.sample(i));

    }
    Aquila::SignalSource data(chunk, sampleFreq);

    Aquila::TextPlot plt("input wave");

    auto fft = Aquila::FftFactory::getFft(SIZE);
    cout << "\n\nSignal spectrum of "<<start<< endl;
    Aquila::SpectrumType spectrum = fft->fft(data.toArray());
    plt.setTitle("Signal spectrum of "+ std::to_string(start));

    findMax(spectrum, sampleFreq);
    // plt.plotSpectrum(spectrum);

}

int main(int argc, char *argv[])
{
	if (argc < 2)
    {
        std::cout << "Usage: main <FILENAME>" << std::endl;
        return 1;
    }

    Aquila::WaveFile wav(argv[1]);

    const std::size_t END = wav.getSamplesCount();
    std::size_t start = 0;

    while(start < END && wav.sample(start) <= 1000 ) start++;
    //220500 = 5*44100
    // cout << END <<endl;
    // cout << start;

    for(int x = start; x < END; x+=END/5) freqOfindex(x, wav);

    return 0;
}
<|endoftext|>


<commit_before>#include <GLFW/glfw3.h>
#include <GL/glu.h>
#include <iostream>
#include <vector>
#include <cmath>
#include <random>
#include <cctype>
#include "RubiksCube.hpp"

constexpr GLdouble const vertex[6][4][3] =
{
	{
		{-2, 1, 1},
		{-2, 1, -1},
		{-2, -1, -1},
		{-2, -1, 1}
	},
	{
		{1, -2, 1},
		{-1, -2, 1},
		{-1, -2, -1},
		{1, -2, -1}
	},
	{
		{1, 1, -2},
		{1, -1, -2},
		{-1, -1, -2},
		{-1, 1, -2}
	},
	{
		{1, 1, 2},
		{1, -1, 2},
		{-1, -1, 2},
		{-1, 1, 2}
	},
	{
		{1, 2, 1},
		{-1, 2, 1},
		{-1, 2, -1},
		{1, 2, -1}
	},
	{
		{2, 1, 1},
		{2, 1, -1},
		{2, -1, -1},
		{2, -1, 1}
	},
};
GLubyte color[][3] =
{
	{0xFF, 0xA0, 0x00},
	{0xFF, 0xFF, 0x00},
	{0x00, 0xFF, 0x00},
	{0x00, 0x00, 0xFF},
	{0xFF, 0xFF, 0xFF},
	{0xFF, 0x00, 0x00}
};

int main(int argc, char * argv[])
{
	constexpr int SIZE = 3;
	RubiksCube<SIZE> rc;

	glfwInit();
	int count;
	GLFWmonitor ** monitors = glfwGetMonitors(&count);
	GLFWmonitor * monitor = monitors[1];//glfwGetPrimaryMonitor();
	GLFWvidmode const * mode = glfwGetVideoMode(monitor);
	glfwWindowHint(GLFW_RED_BITS, mode->redBits);
	glfwWindowHint(GLFW_GREEN_BITS, mode->greenBits);
	glfwWindowHint(GLFW_BLUE_BITS, mode->blueBits);
	glfwWindowHint(GLFW_REFRESH_RATE, mode->refreshRate);
	GLFWwindow * window = glfwCreateWindow(mode->width, mode->height, "RubiksCube", monitor, nullptr);
    glfwMakeContextCurrent(window);

	/*auto pa = [&](std::string s)
	{
		for (auto i = s.begin(); i != s.end(); ++i)
		{
			Axis axis = static_cast<Axis>(std::tolower(*i) - 'x');
			bool isPrime = std::isupper(*i);
			++i;
			int index = *i - '0';
			rc.rotate(axis, index, isPrime);
		}
	};*/

    while(!glfwWindowShouldClose(window))
	{
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		glEnable(GL_DEPTH_TEST);
		glPopMatrix();
		glPushMatrix();

		//window size chagne
		int width, height;
		glfwGetFramebufferSize(window, &width, &height);
		glViewport(0, 0, width, height);
		glLoadIdentity();
		gluPerspective(90, static_cast<double>(width) / static_cast<double>(height), 1, 128);
		gluLookAt(10, 10, 10, 0, 0, 0, 0, 1, 0);

		//view
		static int theta = 0;
		static int iota = 0;
		if (glfwGetKey(window, GLFW_KEY_RIGHT))
		{
			++theta;
		}
		if (glfwGetKey(window, GLFW_KEY_LEFT))
		{
			--theta;
		}
		if (glfwGetKey(window, GLFW_KEY_UP))
		{
			++iota;
		}
		if (glfwGetKey(window, GLFW_KEY_DOWN))
		{
			--iota;
		}

		//animation
		static int index = 0;
		static Axis axis = {};
		static double angle = 0;
		static bool isPrime = {};

		//key
		static bool key[256] = {};
		for (int i = 0; i < 256; ++i)
		{
			if (glfwGetKey(window, static_cast<char>(i)))
			{
				if (!key[i])
				{
					switch (static_cast<char>(i))
					{
						case '1':
							index = 0;
							break;
						case '2':
							index = 1;
							break;
						case '3':
							index = 2;
							break;
						case 'X':
							axis = Axis::X;
							isPrime = glfwGetKey(window, GLFW_KEY_LEFT_SHIFT);
							angle = 90;
							rc.rotate(axis, index, isPrime);
							break;
						case 'C':
							axis = Axis::Y;
							isPrime = glfwGetKey(window, GLFW_KEY_LEFT_SHIFT);
							angle = 90;
							rc.rotate(axis, index, isPrime);
							break;
						case 'Z':
							axis = Axis::Z;
							angle = 90;
							isPrime = glfwGetKey(window, GLFW_KEY_LEFT_SHIFT);
							rc.rotate(axis, index, isPrime);
							break;
						case 'R':
						{
							//pa("X2Y2Z0x2y1z0");
							static std::mt19937 engine(std::random_device{}());
							std::uniform_int_distribution<int> axis(0, 2);
							std::uniform_int_distribution<int> index(0, SIZE - 1);
							std::uniform_int_distribution<bool> isPrime(false, true);
							for (int i = 0; i < 128; ++i)
							{
								rc.rotate(static_cast<Axis>(axis(engine)), index(engine), isPrime(engine));
							}
							break;
						}
						case 'S':
							rc.solve();
							break;
						default:
							break;
					}
				}
				key[i] = true;
			}
			else
			{
				key[i] = false;
			}
		}

		//animation
		if (angle > 0)
		{
			angle -= 10;
		}
		//view
		glRotated(theta, 0, 1, 0);
		glRotated(iota, 1, 0, 0);
		//centralize
		glTranslated(-4, -4, -4);

		for (int i = 0; i < SIZE; ++i)
		{
			for (int j = 0; j < SIZE; ++j)
			{
				for (int k = 0; k < SIZE; ++k)
				{
					for (auto && e : rc.getCube(i, j, k))
					{
						glPushMatrix();

						//animation
						if (angle > 0)
						{
							std::array<int, 3> wrapper = {i, j, k};
							if (wrapper[static_cast<int>(axis)] == index)
							{
								glTranslated(((axis == Axis::X) ? 0 : 4), ((axis == Axis::Y) ? 0 : 4), ((axis == Axis::Z) ? 0 : 4));
								glRotated(isPrime ? -angle : angle, ((axis == Axis::X) ? 1 : 0), ((axis == Axis::Y) ? 1 : 0), ((axis == Axis::Z) ? 1 : 0));
								glTranslated(((axis == Axis::X) ? 0 : -4), ((axis == Axis::Y) ? 0 : -4), ((axis == Axis::Z) ? 0 : -4));
							}
						}

						glTranslated(i * 4, j * 4, k * 4);
						glColor3ubv(color[static_cast<int>(e.second)]);
						glBegin(GL_QUADS);
						for (auto && e : vertex[static_cast<int>(e.first)])
						{
							glVertex3dv(e);
						}
						glEnd();
						glPopMatrix();
					}
				}
			}
		}
		glfwSwapBuffers(window);
		glfwPollEvents();
	}
	glfwTerminate();
}

<commit_msg>remove arg<commit_after>#include <GLFW/glfw3.h>
#include <GL/glu.h>
#include <iostream>
#include <vector>
#include <cmath>
#include <random>
#include <cctype>
#include "RubiksCube.hpp"

constexpr GLdouble const vertex[6][4][3] =
{
	{
		{-2, 1, 1},
		{-2, 1, -1},
		{-2, -1, -1},
		{-2, -1, 1}
	},
	{
		{1, -2, 1},
		{-1, -2, 1},
		{-1, -2, -1},
		{1, -2, -1}
	},
	{
		{1, 1, -2},
		{1, -1, -2},
		{-1, -1, -2},
		{-1, 1, -2}
	},
	{
		{1, 1, 2},
		{1, -1, 2},
		{-1, -1, 2},
		{-1, 1, 2}
	},
	{
		{1, 2, 1},
		{-1, 2, 1},
		{-1, 2, -1},
		{1, 2, -1}
	},
	{
		{2, 1, 1},
		{2, 1, -1},
		{2, -1, -1},
		{2, -1, 1}
	},
};
GLubyte color[][3] =
{
	{0xFF, 0xA0, 0x00},
	{0xFF, 0xFF, 0x00},
	{0x00, 0xFF, 0x00},
	{0x00, 0x00, 0xFF},
	{0xFF, 0xFF, 0xFF},
	{0xFF, 0x00, 0x00}
};

int main()
{
	constexpr int SIZE = 3;
	RubiksCube<SIZE> rc;

	glfwInit();
	int count;
	GLFWmonitor ** monitors = glfwGetMonitors(&count);
	GLFWmonitor * monitor = monitors[1];//glfwGetPrimaryMonitor();
	GLFWvidmode const * mode = glfwGetVideoMode(monitor);
	glfwWindowHint(GLFW_RED_BITS, mode->redBits);
	glfwWindowHint(GLFW_GREEN_BITS, mode->greenBits);
	glfwWindowHint(GLFW_BLUE_BITS, mode->blueBits);
	glfwWindowHint(GLFW_REFRESH_RATE, mode->refreshRate);
	GLFWwindow * window = glfwCreateWindow(mode->width, mode->height, "RubiksCube", monitor, nullptr);
    glfwMakeContextCurrent(window);

	/*auto pa = [&](std::string s)
	{
		for (auto i = s.begin(); i != s.end(); ++i)
		{
			Axis axis = static_cast<Axis>(std::tolower(*i) - 'x');
			bool isPrime = std::isupper(*i);
			++i;
			int index = *i - '0';
			rc.rotate(axis, index, isPrime);
		}
	};*/

    while(!glfwWindowShouldClose(window))
	{
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		glEnable(GL_DEPTH_TEST);
		glPopMatrix();
		glPushMatrix();

		//window size chagne
		int width, height;
		glfwGetFramebufferSize(window, &width, &height);
		glViewport(0, 0, width, height);
		glLoadIdentity();
		gluPerspective(90, static_cast<double>(width) / static_cast<double>(height), 1, 128);
		gluLookAt(10, 10, 10, 0, 0, 0, 0, 1, 0);

		//view
		static int theta = 0;
		static int iota = 0;
		if (glfwGetKey(window, GLFW_KEY_RIGHT))
		{
			++theta;
		}
		if (glfwGetKey(window, GLFW_KEY_LEFT))
		{
			--theta;
		}
		if (glfwGetKey(window, GLFW_KEY_UP))
		{
			++iota;
		}
		if (glfwGetKey(window, GLFW_KEY_DOWN))
		{
			--iota;
		}

		//animation
		static int index = 0;
		static Axis axis = {};
		static double angle = 0;
		static bool isPrime = {};

		//key
		static bool key[256] = {};
		for (int i = 0; i < 256; ++i)
		{
			if (glfwGetKey(window, static_cast<char>(i)))
			{
				if (!key[i])
				{
					switch (static_cast<char>(i))
					{
						case '1':
							index = 0;
							break;
						case '2':
							index = 1;
							break;
						case '3':
							index = 2;
							break;
						case 'X':
							axis = Axis::X;
							isPrime = glfwGetKey(window, GLFW_KEY_LEFT_SHIFT);
							angle = 90;
							rc.rotate(axis, index, isPrime);
							break;
						case 'C':
							axis = Axis::Y;
							isPrime = glfwGetKey(window, GLFW_KEY_LEFT_SHIFT);
							angle = 90;
							rc.rotate(axis, index, isPrime);
							break;
						case 'Z':
							axis = Axis::Z;
							angle = 90;
							isPrime = glfwGetKey(window, GLFW_KEY_LEFT_SHIFT);
							rc.rotate(axis, index, isPrime);
							break;
						case 'R':
						{
							//pa("X2Y2Z0x2y1z0");
							static std::mt19937 engine(std::random_device{}());
							std::uniform_int_distribution<int> axis(0, 2);
							std::uniform_int_distribution<int> index(0, SIZE - 1);
							std::uniform_int_distribution<bool> isPrime(false, true);
							for (int i = 0; i < 128; ++i)
							{
								rc.rotate(static_cast<Axis>(axis(engine)), index(engine), isPrime(engine));
							}
							break;
						}
						case 'S':
							rc.solve();
							break;
						default:
							break;
					}
				}
				key[i] = true;
			}
			else
			{
				key[i] = false;
			}
		}

		//animation
		if (angle > 0)
		{
			angle -= 10;
		}
		//view
		glRotated(theta, 0, 1, 0);
		glRotated(iota, 1, 0, 0);
		//centralize
		glTranslated(-4, -4, -4);

		for (int i = 0; i < SIZE; ++i)
		{
			for (int j = 0; j < SIZE; ++j)
			{
				for (int k = 0; k < SIZE; ++k)
				{
					for (auto && e : rc.getCube(i, j, k))
					{
						glPushMatrix();

						//animation
						if (angle > 0)
						{
							std::array<int, 3> wrapper = {i, j, k};
							if (wrapper[static_cast<int>(axis)] == index)
							{
								glTranslated(((axis == Axis::X) ? 0 : 4), ((axis == Axis::Y) ? 0 : 4), ((axis == Axis::Z) ? 0 : 4));
								glRotated(isPrime ? -angle : angle, ((axis == Axis::X) ? 1 : 0), ((axis == Axis::Y) ? 1 : 0), ((axis == Axis::Z) ? 1 : 0));
								glTranslated(((axis == Axis::X) ? 0 : -4), ((axis == Axis::Y) ? 0 : -4), ((axis == Axis::Z) ? 0 : -4));
							}
						}

						glTranslated(i * 4, j * 4, k * 4);
						glColor3ubv(color[static_cast<int>(e.second)]);
						glBegin(GL_QUADS);
						for (auto && e : vertex[static_cast<int>(e.first)])
						{
							glVertex3dv(e);
						}
						glEnd();
						glPopMatrix();
					}
				}
			}
		}
		glfwSwapBuffers(window);
		glfwPollEvents();
	}
	glfwTerminate();
}

<|endoftext|>


<commit_before>24fa16bd-2748-11e6-8f91-e0f84713e7b8<commit_msg>this is my first commit?<commit_after>2517bb75-2748-11e6-b4ad-e0f84713e7b8<|endoftext|>


<commit_before>#include <linux/input.h>
#include <linux/fb.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fstream>
#include <stdexcept>

class Fb {
 public:
  Fb() : m_fd(open("/dev/fb1", O_RDWR)) {
    if (m_fd == -1) {
      throw std::runtime_error(strerror(errno));
    }

    ioctl(m_fd, FBIOGET_VSCREENINFO, &m_vinfo);
    ioctl(m_fd, FBIOGET_FSCREENINFO, &m_finfo);
  }
  ~Fb() { close(m_fd); }

  int getFd() const { return m_fd; }

  int getScreenSize() const {
    return m_vinfo.yres_virtual * m_finfo.line_length;
  }

  int adjust(int& x, int& y) const {
    x = x % m_vinfo.xres;
    y = y % m_vinfo.yres;
  }

  int getLocation(int x, int y) const {
    return (x + m_vinfo.xoffset) * (m_vinfo.bits_per_pixel / 8) +
           (y + m_vinfo.yoffset) * m_finfo.line_length;
  }

 private:
  int m_fd;
  fb_fix_screeninfo m_finfo;
  fb_var_screeninfo m_vinfo;
};

class Map {
 public:
  Map()
      : m_fb(),
        m_ptr(static_cast<char*>(mmap(nullptr, m_fb.getScreenSize(),
                                      PROT_READ | PROT_WRITE,
                                      MAP_SHARED, m_fb.getFd(), 0))) {
    if (m_ptr == MAP_FAILED) {
      throw std::runtime_error(strerror(errno));
    }
  }
  ~Map() { munmap(m_ptr, m_fb.getScreenSize()); }

  int adjust(int& x, int& y) const { m_fb.adjust(x, y); }

  unsigned short& pixel(int x, int y) {
    return reinterpret_cast<unsigned short&>(
        m_ptr[m_fb.getLocation(x, y)]);
  }

 private:
  Fb m_fb;
  char* m_ptr;
};

int main(int argc, char* argv[]) {
  Map map;
  std::ifstream event("/dev/input/event0",
                      std::ifstream::in | std::ifstream::binary);
  input_event ev;
  int x(0), y(0);
  unsigned short color(-1);

  map.pixel(x, y) = -1;

  while (event.read(reinterpret_cast<char*>(&ev), sizeof(ev))) {
    if (ev.type == EV_KEY && ev.value != 0) {
      map.pixel(x, y) = 0;

      switch (ev.code) {
        case KEY_UP:
          --y;
          break;
        case KEY_DOWN:
          ++y;
          break;
        case KEY_LEFT:
          --x;
          break;
        case KEY_RIGHT:
          ++x;
          break;
        case KEY_ENTER:
          color = rand();
          break;
      }

      map.adjust(x, y);
      map.pixel(x, y) = color;
    }
  }

  return 0;
}
<commit_msg>added a target to hunt<commit_after>#include <linux/input.h>
#include <linux/fb.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fstream>
#include <stdexcept>

class Fb {
 public:
  Fb() : m_fd(open("/dev/fb1", O_RDWR)) {
    if (m_fd == -1) {
      throw std::runtime_error(strerror(errno));
    }

    ioctl(m_fd, FBIOGET_VSCREENINFO, &m_vinfo);
    ioctl(m_fd, FBIOGET_FSCREENINFO, &m_finfo);
  }
  ~Fb() { close(m_fd); }

  int getFd() const { return m_fd; }

  int getScreenSize() const {
    return m_vinfo.yres_virtual * m_finfo.line_length;
  }

  int adjust(int& x, int& y) const {
    x = x % m_vinfo.xres;
    y = y % m_vinfo.yres;
  }

  int getLocation(int x, int y) const {
    return (x + m_vinfo.xoffset) * (m_vinfo.bits_per_pixel / 8) +
           (y + m_vinfo.yoffset) * m_finfo.line_length;
  }

 private:
  int m_fd;
  fb_fix_screeninfo m_finfo;
  fb_var_screeninfo m_vinfo;
};

class Map {
 public:
  Map()
      : m_fb(),
        m_ptr(static_cast<char*>(mmap(nullptr, m_fb.getScreenSize(),
                                      PROT_READ | PROT_WRITE,
                                      MAP_SHARED, m_fb.getFd(), 0))) {
    if (m_ptr == MAP_FAILED) {
      throw std::runtime_error(strerror(errno));
    }
  }
  ~Map() { munmap(m_ptr, m_fb.getScreenSize()); }

  int adjust(int& x, int& y) const { m_fb.adjust(x, y); }

  unsigned short& pixel(int x, int y) {
    return reinterpret_cast<unsigned short&>(
        m_ptr[m_fb.getLocation(x, y)]);
  }

 private:
  Fb m_fb;
  char* m_ptr;
};

int main(int argc, char* argv[]) {
  Map map;
  std::ifstream event("/dev/input/event0",
                      std::ifstream::in | std::ifstream::binary);
  input_event ev;
  int x(0), y(0);
  int xt(0), yt(0);
  unsigned short color(-1);

  map.pixel(x, y) = -1;

  while (event.read(reinterpret_cast<char*>(&ev), sizeof(ev))) {

    if (ev.type == EV_KEY && ev.value != 0) {
      map.pixel(x, y) = 0;

      switch (ev.code) {
        case KEY_UP:
          --y;
          break;
        case KEY_DOWN:
          ++y;
          break;
        case KEY_LEFT:
          --x;
          break;
        case KEY_RIGHT:
          ++x;
          break;
        case KEY_ENTER:
          color = rand();
          break;
      }

      map.adjust(x, y);
      map.pixel(x, y) = color;

    }

    if (xt == x && yt == y) {
      xt = rand();
      yt = rand();

      map.adjust(xt, yt);
      map.pixel(xt, yt) = -1;
    }
  }

  return 0;
}
<|endoftext|>


<commit_before>/******************************************************************************
* Turbo C++11 metaprogramming Library                                         *
*                                                                             *
* Copyright (C) 2013 - 2014, Manuel Sánchez Pérez                             *
*                                                                             *
* This file is part of The Turbo Library.                                     *
*                                                                             *
* The Turbo Library is free software: you can redistribute it and/or modify   *
* it under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation, version 2 of the License.                     *
*                                                                             *
* The Turbo Library is distributed in the hope that it will be useful,        *
* but WITHOUT ANY WARRANTY; without even the implied warranty of              *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               *
* GNU Lesser General Public License for more details.                         *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with The Turbo Library. If not, see <http://www.gnu.org/licenses/>.   *
******************************************************************************/

#include "eval.hpp"
#include "placeholders.hpp"
#include "let_expressions.hpp"

#include "lazy.hpp"
#include "lambda.hpp"
#include "algorithm.hpp"

#include "integral_lists.hpp"

#include "basic_types.hpp"
#include "utils/assert.hpp"
#include "warning.hpp"
#include "impl/demangle.hpp"
#include "integral_iterators.hpp"
#include "fixed_point.hpp"
#include "stl_adapters.hpp"
#include "bind.hpp"
#include "to_runtime.hpp"

#include <iostream>
#include <vector>
#include <memory>
#include <type_traits>

using namespace tml::placeholders;

#define RUN_UNIT_TESTS

#ifdef RUN_UNIT_TESTS

template<typename... ARGS>
struct f
{
    using result = tml::list<ARGS...>;
};

using t1 = tml::eval<Int<0>>;
using t2 = tml::eval<f<_1,_2,_3>,Int<1>,Int<2>,Int<3>>;
using t3 = tml::eval<tml::lazy<f>,Int<1>,Int<2>,Int<3>>;
using t4 = tml::eval<tml::lambda<_1,f<_1,Int<2>,Int<3>>>,Int<1>>;
using t5 = tml::eval<tml::multi_let<_1,_2,_3,Int<1>,Int<2>,Int<3>,f<_1,_2,_3>>>;
using t6 = tml::eval<tml::multi_lambda<_1,_2,_3 , f<_1,_2,_3>>,Int<1>,Int<2>,Int<3>>;

constexpr bool a = tml::is_function<Int<0>>::value;

TURBO_ASSERT((std::is_same<TURBO_SFINAE(
                                        DISABLE_IF(tml::is_function<Int<0>>) ,
                                        DISABLE_IF(tml::overrides_eval<Int<0>>)
                                       ),tml::sfinae_return>));

TURBO_ASSERT((std::is_same<t1,tml::integer<0>>));
TURBO_ASSERT((std::is_same<t2,tml::integer_list<1,2,3>>));
TURBO_ASSERT((std::is_same<t3,tml::integer_list<1,2,3>>));
TURBO_ASSERT((std::is_same<t4,tml::integer_list<1,2,3>>));
TURBO_ASSERT((std::is_same<t5,tml::integer_list<1,2,3>>));
TURBO_ASSERT((std::is_same<t6,tml::integer_list<1,2,3>>));

#endif /* RUN_UNIT_TESTS */

template<typename N>
struct odd : public tml::function<tml::boolean<(N::value % 2) == 0>>
{};

#ifndef RANGE_END
#define RANGE_END 20
#endif

using numbers = tml::integer_list<0,1,2,3,4,5>;
using numbers2 = tml::integer_range<0,RANGE_END>;

using map_test    = tml::map<tml::lazy<odd>,numbers2>;
using any_of_test = tml::any<tml::lazy<odd>,tml::iterator::begin<numbers> , tml::iterator::end<numbers>>;
using all_of_test = tml::all<tml::lazy<odd>,tml::integer_list<0,1,2,3,4,5>>;

using x = tml::fsingle<(1 << 7)>; //0.5
using y = tml::fsingle<(1 << 9)>; //2.0
using z = tml::eval<tml::div<x,y>>; //0.25?
using w = tml::eval<tml::mul<z,y>>; //0.5?

template<typename T>
using this_is_not_java_vector = std::vector<tml::eval<tml::stl::function<std::remove_pointer<T>>>>;

template<typename T>
using this_is_how_you_should_do_polymorphism = std::vector<std::unique_ptr<tml::stl::eval<std::remove_pointer<T>>>>;

TURBO_ASSERT(( std::is_same<std::vector<int>,this_is_not_java_vector<int*>> ));

template<typename T>
struct quux;

template<>
struct quux<char>
{};

//Conditional selection of potentially ill-formed types! Thanks to Turbo tml::lazy its easy:
using ok = tml::lazy_instance<tml::conditional<tml::false_type,
                                               tml::lazy<quux,char>,
                                               tml::lazy<quux,bool>
                                              >
                             >;

TURBO_ASSERT(( std::is_same<ok,quux<bool>> ));

template<typename A , typename B , typename C>
struct third_arg : public tml::function<C>
{};

using b = tml::bind<third_arg,_3,_2,_1>;
using bcall = tml::eval<b,char,char,int>; //Equivalent to tml::eval<third_arg<int,bool,char>>

TURBO_ASSERT(( std::is_same<bcall,char> ));

int main()
{
    std::cout << tml::to_string<numbers>() << std::endl;
    std::cout << tml::to_string<map_test>() << std::endl;
    std::cout << tml::to_string<any_of_test>() << std::endl;
    std::cout << tml::to_string<all_of_test>() << std::endl;
    std::cout << tml::to_string<numbers2>() << std::endl;

    std::cout << tml::to_string<x>() << std::endl;
    std::cout << tml::to_string<y>() << std::endl;
    std::cout << tml::to_string<z>() << std::endl;
    std::cout << tml::to_string<w>() << std::endl;

    std::cout << tml::to_string<bcall>() << std::endl;

    for( auto v : tml::to_runtime<numbers>() )
    {
        std::cout << v << std::endl;
    }

    std::cout << "(" << std::boolalpha
              << std::get<0>( tml::to_runtime<tml::list<tml::Char<'a'>,tml::Bool<true>,tml::Int<0>>>() ) << ","
              << std::get<1>( tml::to_runtime<tml::list<tml::Char<'a'>,tml::Bool<true>,tml::Int<0>>>() ) << ","
              << std::get<2>( tml::to_runtime<tml::list<tml::Char<'a'>,tml::Bool<true>,tml::Int<0>>>() ) << ")" << std::endl;
}
<commit_msg>Testing Travis LLVM toolchain<commit_after>/******************************************************************************
* Turbo C++11 metaprogramming Library                                         *
*                                                                             *
* Copyright (C) 2013 - 2014, Manuel Sánchez Pérez                             *
*                                                                             *
* This file is part of The Turbo Library.                                     *
*                                                                             *
* The Turbo Library is free software: you can redistribute it and/or modify   *
* it under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation, version 2 of the License.                     *
*                                                                             *
* The Turbo Library is distributed in the hope that it will be useful,        *
* but WITHOUT ANY WARRANTY; without even the implied warranty of              *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               *
* GNU Lesser General Public License for more details.                         *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with The Turbo Library. If not, see <http://www.gnu.org/licenses/>.   *
******************************************************************************/

#include "eval.hpp"
#include "placeholders.hpp"
#include "let_expressions.hpp"

#include "lazy.hpp"
#include "lambda.hpp"
#include "algorithm.hpp"

#include "integral_lists.hpp"

#include "basic_types.hpp"
#include "utils/assert.hpp"
#include "warning.hpp"
#include "impl/demangle.hpp"
#include "integral_iterators.hpp"
#include "fixed_point.hpp"
#include "stl_adapters.hpp"
#include "bind.hpp"
#include "to_runtime.hpp"

#include <iostream>
#include <vector>
#include <memory>
#include <type_traits>

using namespace tml::placeholders;

#define RUN_UNIT_TESTS

#ifdef RUN_UNIT_TESTS

template<typename... ARGS>
struct f
{
    using result = tml::list<ARGS...>;
};

using t1 = tml::eval<Int<0>>;
using t2 = tml::eval<f<_1,_2,_3>,Int<1>,Int<2>,Int<3>>;
using t3 = tml::eval<tml::lazy<f>,Int<1>,Int<2>,Int<3>>;
using t4 = tml::eval<tml::lambda<_1,f<_1,Int<2>,Int<3>>>,Int<1>>;
using t5 = tml::eval<tml::multi_let<_1,_2,_3,Int<1>,Int<2>,Int<3>,f<_1,_2,_3>>>;
using t6 = tml::eval<tml::multi_lambda<_1,_2,_3 , f<_1,_2,_3>>,Int<1>,Int<2>,Int<3>>;

constexpr bool a = tml::is_function<Int<0>>::value;

TURBO_ASSERT((std::is_same<TURBO_SFINAE(
                                        DISABLE_IF(tml::is_function<Int<0>>) ,
                                        DISABLE_IF(tml::overrides_eval<Int<0>>)
                                       ),tml::sfinae_return>));

TURBO_ASSERT((std::is_same<t1,tml::integer<0>>));
TURBO_ASSERT((std::is_same<t2,tml::integer_list<1,2,3>>));
TURBO_ASSERT((std::is_same<t3,tml::integer_list<1,2,3>>));
TURBO_ASSERT((std::is_same<t4,tml::integer_list<1,2,3>>));
TURBO_ASSERT((std::is_same<t5,tml::integer_list<1,2,3>>));
TURBO_ASSERT((std::is_same<t6,tml::integer_list<1,2,3>>));

#endif /* RUN_UNIT_TESTS */

template<typename N>
struct odd : public tml::function<tml::boolean<(N::value % 2) == 0>>
{};

#ifndef RANGE_END
#define RANGE_END 20
#endif

using numbers = tml::integer_list<0,1,2,3,4,5>;
using numbers2 = tml::integer_range<0,RANGE_END>;

using map_test    = tml::map<tml::lazy<odd>,numbers2>;
using any_of_test = tml::any<tml::lazy<odd>,tml::iterator::begin<numbers> , tml::iterator::end<numbers>>;
using all_of_test = tml::all<tml::lazy<odd>,tml::integer_list<0,1,2,3,4,5>>;

using x = tml::fsingle<(1 << 7)>; //0.5
using y = tml::fsingle<(1 << 9)>; //2.0
using z = tml::eval<tml::div<x,y>>; //0.25?
using w = tml::eval<tml::mul<z,y>>; //0.5?

template<typename T>
using this_is_not_java_vector = std::vector<tml::eval<tml::stl::function<std::remove_pointer<T>>>>;

template<typename T>
using this_is_how_you_should_do_polymorphism = std::vector<std::unique_ptr<tml::stl::eval<std::remove_pointer<T>>>>;

TURBO_ASSERT(( std::is_same<std::vector<int>,this_is_not_java_vector<int*>> ));

template<typename T>
struct quux;

template<>
struct quux<char>
{};

//Conditional selection of potentially ill-formed types! Thanks to Turbo tml::lazy its easy:
using ok = tml::lazy_instance<tml::conditional<tml::false_type,
                                               tml::lazy<quux,char>,
                                               tml::lazy<quux,bool>
                                              >
                             >;

TURBO_ASSERT(( std::is_same<ok,quux<bool>> ));

template<typename A , typename B , typename C>
struct third_arg : public tml::function<C>
{};

using b = tml::bind<third_arg , _3,_2,_1>;
using bcall = tml::eval<b,char,char,int>; //Equivalent to tml::eval<third_arg<int,bool,char>>

TURBO_ASSERT(( std::is_same<bcall,char> ));

int main()
{
    std::cout << tml::to_string<numbers>() << std::endl;
    std::cout << tml::to_string<map_test>() << std::endl;
    std::cout << tml::to_string<any_of_test>() << std::endl;
    std::cout << tml::to_string<all_of_test>() << std::endl;
    std::cout << tml::to_string<numbers2>() << std::endl;

    std::cout << tml::to_string<x>() << std::endl;
    std::cout << tml::to_string<y>() << std::endl;
    std::cout << tml::to_string<z>() << std::endl;
    std::cout << tml::to_string<w>() << std::endl;

    std::cout << tml::to_string<bcall>() << std::endl;

    for( auto v : tml::to_runtime<numbers>() )
    {
        std::cout << v << std::endl;
    }

    std::cout << "(" << std::boolalpha
              << std::get<0>( tml::to_runtime<tml::list<tml::Char<'a'>,tml::Bool<true>,tml::Int<0>>>() ) << ","
              << std::get<1>( tml::to_runtime<tml::list<tml::Char<'a'>,tml::Bool<true>,tml::Int<0>>>() ) << ","
              << std::get<2>( tml::to_runtime<tml::list<tml::Char<'a'>,tml::Bool<true>,tml::Int<0>>>() ) << ")" << std::endl;
}
<|endoftext|>


<commit_before>3036a600-2748-11e6-ab1f-e0f84713e7b8<commit_msg>For roselyn to integrate at some point<commit_after>30436c5c-2748-11e6-8a32-e0f84713e7b8<|endoftext|>


<commit_before>//
//  main.cpp
//  fxtract
//
//  Created by Connor Skennerton on 30/07/13.
//  Copyright (c) 2013 Connor Skennerton. All rights reserved.
//

#include <unistd.h>
#include <cstdio>
#include <cassert>

#include "util.h"
#include "fileManager.h"

#include "Fx.h"
extern "C" {
#include "util/ssearch.h"
#include "util/bpsearch.h"
#include "util/msutil.h"
}
#define VERSION "1.0-alpha"

struct Options
{
    bool   H_flag;
    bool   Q_flag;
    bool   G_flag;
    bool   E_flag;
    bool   x_flag;
    bool   r_flag;
    bool   I_flag;
    char * f_flag;

    Options() : H_flag(false),
                Q_flag(false),
                G_flag(false),
                E_flag(false),
                x_flag(false),
                r_flag(false),
                I_flag(false),
                f_flag(NULL)
    {}
};

void printSingle(Fx * mate1, FILE * out ) {
    mate1->puts(out);
}

void printPair(Fx* mate1, Fx* mate2, FILE * out) {
    // match in the first read print out pair
    printSingle(mate1, out);
    printSingle(mate2, out);
}

//void usage() {
static const char usage_msg[] =\
    "[-hHv] {-f pattern_file | pattern} <read1.fx> [<read2.fx>]\n"
    "\t-H           Evaluate patterns in the context of headers (default: sequences)\n"
    "\t-Q           Evaluate patterns in the context of quality scores (default: sequences)\n"
    "\t-G           pattern is a posix basic regular expression (default: literal substring)\n"
    "\t-E           pattern is a posix extended regular expression (default: literal substring)\n"
    "\t-P           pattern is a perl compatable regular expression (default: literal substring)\n"
    "\t-x           pattern exactly matches the whole string (default: literal substring)\n"
    "\t-I           The read file is interleaved (both pairs in a single file)\n"
    "\t-f <file>    File containing patterns, one per line\n"
    "\t-h           Print this help\n"
    "\t-V           Print version\n";
//   exit(1);
//}

int parseOptions(int argc,  char * argv[], Options& opts) {
    int c;
    while ((c = getopt(argc, argv, "HhIf:zjqVrQGEPx")) != -1 ) {
        switch (c) {
            case 'f':
                opts.f_flag = optarg;
                break;

            case 'I':
                opts.I_flag = true;
                break;

            case 'Q':
                opts.Q_flag = true;
                break;
            case 'e':
                opts.r_flag = true;
                break;
            case 'x':
                opts.x_flag = true;
                break;
            case 'V':
                puts(VERSION);
                exit(1);
                break;
            case 'H':
                opts.H_flag = true;
                break;
            case 'r':
                opts.r_flag = true;
                break;
            case 'h':
            default:
                usage(usage_msg);
                break;
        }
    }
    return optind;
}

void split( std::vector<std::string> & theStringVector,  /* Altered/returned value */
       std::string theString,
       const  std::string theDelimiter)
{
    assert(theDelimiter.size() > 0); // My own ASSERT macro.

    size_t  start = 0, end = 0;

    while ( end != std::string::npos)
    {
        end = theString.find( theDelimiter, start);

        // If at end, use length=maxLength.  Else use length=end-start.
        theStringVector.push_back( theString.substr( start,
                       (end == std::string::npos) ? std::string::npos : end - start));

        // If at end, use start=maxSize.  Else use start=end+delimiter.
        start = (   ( end > (std::string::npos - theDelimiter.size()) )
                  ?  std::string::npos  :  end + theDelimiter.size());
    }
}

void tokenizePatternFile(FILE * in, FileManager&  fmanager) {
    // tokenize a line from the pattern file.  The first part will be the pattern and the second
    // part is the file to write to.
    char * lineptr = NULL;
    size_t n;

    while(getline(&lineptr, &n, in) != -1) {
        std::vector<std::string> fields;
        split(fields, lineptr, "\t");
        switch(fields.size()) {
            case 0:
                break;
            case 1:
                fmanager.add(fields[0]);
                break;
            default:
                fmanager.add(fields[0], fields[1]);
                break;
        }
    }
    free(lineptr);
}
static int
on_match(int strnum, const char *textp, void const * context)
{
	Fx * read = (Fx *) context;
    read->puts(stdout);
    return  1;
}

int main(int argc, char * argv[])
{
    //kvec_t(sds) pattern_list;
    FileManager manager;
    Options opts;

    int opt_idx = parseOptions(argc, argv, opts);

    if(opts.f_flag == NULL) {

        if( opt_idx >= argc) {
            puts("Please provide a pattern (or pattern file) and at least one input file");
            usage(usage_msg);
        } else if (opt_idx >= argc - 1) {
            puts("Please provide an input file (or two)");
            usage(usage_msg);
        }
        std::string pattern = argv[opt_idx];
        ++opt_idx;
        manager.add(pattern);
        if(opts.r_flag) {
          std::string rcpattern = pattern;
            reverseComplement(rcpattern);
            manager.add(rcpattern);
        }

    } else {
        if (opt_idx > argc - 1) {
            puts("Please provide an input file (or two)");
            usage(usage_msg);
        }
        FILE * in = fopen(opts.f_flag, "r");
        tokenizePatternFile(in, manager);
    }

    Fxstream stream;
    if(opt_idx == argc - 2) {
        // two read files
        stream.open(argv[opt_idx], argv[opt_idx+1], opts.I_flag);
    } else if (opt_idx == argc - 1) {
        // one read file
        stream.open(argv[opt_idx], NULL, opts.I_flag);
    }

    Fx * mate1 = new Fx();
    Fx * mate2 = new Fx();

    std::string conc;
    std::map<std::string, int>::iterator iter;
    for (iter = manager.patternMapping.begin(); iter != manager.patternMapping.end() ; ++iter ) {
        conc += iter->first + "\n";
    }
    char * concstr  = (char *) malloc(conc.size() * sizeof(char *));
    strncpy(concstr, conc.c_str(), conc.size());
    concstr[conc.size()-1] = '\0';
    int npatts;
    MEMREF *pattv =  refsplit(concstr, '\n', &npatts);

    SSEARCH *ssp = ssearch_create(pattv, npatts);

    while(stream.read(&mate1, &mate2) >= 0) {
        MEMREF data;
        if(opts.H_flag) {
            data.ptr = mate1->name;
            data.len = strlen(mate1->name);

        } else if(opts.Q_flag){
            if(!mate1->isFasta()) {
                data.ptr = mate1->qual;
                data.len = (size_t)mate1->len;
            }
        } else {
            data.ptr = mate1->seq;
            data.len = (size_t)mate1->len;
        }
        int ret = ssearch_scan(ssp, data, (SSEARCH_CB)on_match, (void *)mate1);
        if(ret == 0){
            // read one did not have a match check read 2 if it exists
            if(mate2 != NULL) {
                if(opts.H_flag) {
                    data.ptr = mate2->name;
                    data.len = strlen(mate2->name);

                } else if(opts.Q_flag){
                    if(!mate2->isFasta()) {
                        data.ptr = mate2->seq;
                        data.len = (size_t)mate2->len;
                    }
                } else {
                    data.ptr = mate2->seq;
                    data.len = (size_t)mate2->len;
                }
                ssearch_scan(ssp, data, (SSEARCH_CB)on_match, (void *)mate2);
            }
        }
    }

    free(concstr);
    delete mate1;
    delete mate2;
    stream.close();
    free(pattv);

    return 0;
}
<commit_msg>fix memory leak<commit_after>//
//  main.cpp
//  fxtract
//
//  Created by Connor Skennerton on 30/07/13.
//  Copyright (c) 2013 Connor Skennerton. All rights reserved.
//

#include <unistd.h>
#include <cstdio>
#include <cassert>

#include "util.h"
#include "fileManager.h"

#include "Fx.h"
extern "C" {
#include "util/ssearch.h"
#include "util/bpsearch.h"
#include "util/msutil.h"
}
#define VERSION "1.0-alpha"

struct Options
{
    bool   H_flag;
    bool   Q_flag;
    bool   G_flag;
    bool   E_flag;
    bool   x_flag;
    bool   r_flag;
    bool   I_flag;
    char * f_flag;

    Options() : H_flag(false),
                Q_flag(false),
                G_flag(false),
                E_flag(false),
                x_flag(false),
                r_flag(false),
                I_flag(false),
                f_flag(NULL)
    {}
};

void printSingle(Fx * mate1, FILE * out ) {
    mate1->puts(out);
}

void printPair(Fx* mate1, Fx* mate2, FILE * out) {
    // match in the first read print out pair
    printSingle(mate1, out);
    printSingle(mate2, out);
}

//void usage() {
static const char usage_msg[] =\
    "[-hHv] {-f pattern_file | pattern} <read1.fx> [<read2.fx>]\n"
    "\t-H           Evaluate patterns in the context of headers (default: sequences)\n"
    "\t-Q           Evaluate patterns in the context of quality scores (default: sequences)\n"
    "\t-G           pattern is a posix basic regular expression (default: literal substring)\n"
    "\t-E           pattern is a posix extended regular expression (default: literal substring)\n"
    "\t-P           pattern is a perl compatable regular expression (default: literal substring)\n"
    "\t-x           pattern exactly matches the whole string (default: literal substring)\n"
    "\t-I           The read file is interleaved (both pairs in a single file)\n"
    "\t-f <file>    File containing patterns, one per line\n"
    "\t-h           Print this help\n"
    "\t-V           Print version\n";
//   exit(1);
//}

int parseOptions(int argc,  char * argv[], Options& opts) {
    int c;
    while ((c = getopt(argc, argv, "HhIf:zjqVrQGEPx")) != -1 ) {
        switch (c) {
            case 'f':
                opts.f_flag = optarg;
                break;

            case 'I':
                opts.I_flag = true;
                break;

            case 'Q':
                opts.Q_flag = true;
                break;
            case 'e':
                opts.r_flag = true;
                break;
            case 'x':
                opts.x_flag = true;
                break;
            case 'V':
                puts(VERSION);
                exit(1);
                break;
            case 'H':
                opts.H_flag = true;
                break;
            case 'r':
                opts.r_flag = true;
                break;
            case 'h':
            default:
                usage(usage_msg);
                break;
        }
    }
    return optind;
}

void split( std::vector<std::string> & theStringVector,  /* Altered/returned value */
       std::string theString,
       const  std::string theDelimiter)
{
    assert(theDelimiter.size() > 0); // My own ASSERT macro.

    size_t  start = 0, end = 0;

    while ( end != std::string::npos)
    {
        end = theString.find( theDelimiter, start);

        // If at end, use length=maxLength.  Else use length=end-start.
        theStringVector.push_back( theString.substr( start,
                       (end == std::string::npos) ? std::string::npos : end - start));

        // If at end, use start=maxSize.  Else use start=end+delimiter.
        start = (   ( end > (std::string::npos - theDelimiter.size()) )
                  ?  std::string::npos  :  end + theDelimiter.size());
    }
}

void tokenizePatternFile(FILE * in, FileManager&  fmanager) {
    // tokenize a line from the pattern file.  The first part will be the pattern and the second
    // part is the file to write to.
    char * lineptr = NULL;
    size_t n;

    while(getline(&lineptr, &n, in) != -1) {
        std::vector<std::string> fields;
        split(fields, lineptr, "\t");
        switch(fields.size()) {
            case 0:
                break;
            case 1:
                fmanager.add(fields[0]);
                break;
            default:
                fmanager.add(fields[0], fields[1]);
                break;
        }
    }
    free(lineptr);
}
static int
on_match(int strnum, const char *textp, void const * context)
{
	Fx * read = (Fx *) context;
    read->puts(stdout);
    return  1;
}

int main(int argc, char * argv[])
{
    //kvec_t(sds) pattern_list;
    FileManager manager;
    Options opts;

    int opt_idx = parseOptions(argc, argv, opts);

    if(opts.f_flag == NULL) {

        if( opt_idx >= argc) {
            puts("Please provide a pattern (or pattern file) and at least one input file");
            usage(usage_msg);
        } else if (opt_idx >= argc - 1) {
            puts("Please provide an input file (or two)");
            usage(usage_msg);
        }
        std::string pattern = argv[opt_idx];
        ++opt_idx;
        manager.add(pattern);
        if(opts.r_flag) {
          std::string rcpattern = pattern;
            reverseComplement(rcpattern);
            manager.add(rcpattern);
        }

    } else {
        if (opt_idx > argc - 1) {
            puts("Please provide an input file (or two)");
            usage(usage_msg);
        }
        FILE * in = fopen(opts.f_flag, "r");
        tokenizePatternFile(in, manager);
    }

    Fxstream stream;
    if(opt_idx == argc - 2) {
        // two read files
        stream.open(argv[opt_idx], argv[opt_idx+1], opts.I_flag);
    } else if (opt_idx == argc - 1) {
        // one read file
        stream.open(argv[opt_idx], NULL, opts.I_flag);
    }

    Fx * mate1 = new Fx();
    Fx * mate2 = new Fx();

    std::string conc;
    std::map<std::string, int>::iterator iter;
    for (iter = manager.patternMapping.begin(); iter != manager.patternMapping.end() ; ++iter ) {
        conc += iter->first + "\n";
    }
    char * concstr  = (char *) malloc(conc.size() * sizeof(char *));
    strncpy(concstr, conc.c_str(), conc.size());
    concstr[conc.size()-1] = '\0';
    int npatts;
    MEMREF *pattv =  refsplit(concstr, '\n', &npatts);

    SSEARCH *ssp = ssearch_create(pattv, npatts);

    while(stream.read(&mate1, &mate2) >= 0) {
        MEMREF data;
        if(opts.H_flag) {
            data.ptr = mate1->name;
            data.len = strlen(mate1->name);

        } else if(opts.Q_flag){
            if(!mate1->isFasta()) {
                data.ptr = mate1->qual;
                data.len = (size_t)mate1->len;
            }
        } else {
            data.ptr = mate1->seq;
            data.len = (size_t)mate1->len;
        }
        int ret = ssearch_scan(ssp, data, (SSEARCH_CB)on_match, (void *)mate1);
        if(ret == 0){
            // read one did not have a match check read 2 if it exists
            if(mate2 != NULL) {
                if(opts.H_flag) {
                    data.ptr = mate2->name;
                    data.len = strlen(mate2->name);

                } else if(opts.Q_flag){
                    if(!mate2->isFasta()) {
                        data.ptr = mate2->seq;
                        data.len = (size_t)mate2->len;
                    }
                } else {
                    data.ptr = mate2->seq;
                    data.len = (size_t)mate2->len;
                }
                ssearch_scan(ssp, data, (SSEARCH_CB)on_match, (void *)mate2);
            }
        }
    }

    free(concstr);
    delete mate1;
    delete mate2;
    stream.close();
    free(pattv);
    ssearch_destroy(ssp);

    return 0;
}
<|endoftext|>


<commit_before><commit_msg>BUG: extern shared variable used wrong directive<commit_after><|endoftext|>