/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "singa/core/tensor.h"
// #include "singa/utils/stacktrace.h"
#include <algorithm>
#include <utility>

#include "./tensor_math.h"
#include "./tensor_math_cpp.h"
#include "./tensor_math_cuda.h"
#include "./tensor_math_opencl.h"

#define Noaxis 9999

namespace singa {

Tensor::~Tensor() {
  if (block_ != nullptr && block_->DecRefCount() == 0) {
    device_->FreeBlock(block_);
  }
  block_ = nullptr;
}

Tensor::Tensor() {
  device_ = defaultDevice;
  stride_ = {1};
}

// non-strided constructors
Tensor::Tensor(const Shape &shape, DataType dtype)
    : data_type_(dtype), device_(defaultDevice), shape_(shape) {
  size_t size = Product(shape_) * SizeOf(data_type_);
  if (size) {
    block_ = device_->NewBlock((int)size);
  }
  generate_stride();
}

// non-strided constructors with device
Tensor::Tensor(const Shape &shape, std::shared_ptr<Device> device,
               DataType dtype)
    : data_type_(dtype), device_(device), shape_(shape) {
  size_t size = Product(shape_) * SizeOf(data_type_);
  if (size) {
    block_ = device_->NewBlock((int)size);
  }
  generate_stride();
}

Tensor::Tensor(const Tensor &in)
    : data_type_(in.data_type_),
      device_(in.device_),
      block_(in.block()),
      shape_(in.shape_),
      stride_(in.stride_) {
  // printf("i am here in &in\n");
  if (block_ != nullptr) block_->IncRefCount();
}

Tensor::Tensor(Tensor &&in)
    : data_type_(in.data_type_),
      device_(in.device_),
      shape_(std::move(in.shape_)),
      stride_(std::move(in.stride_)) {
  // printf("i am here in &&in\n");
  block_ = in.block_;
  in.block_ = nullptr;
}

Tensor &Tensor::ResetLike(const Tensor &in) {
  if (block_ == nullptr || device_ != in.device_ || MemSize() != in.MemSize()) {
    if (block_ != nullptr && block_->DecRefCount() == 0)
      device_->FreeBlock(block_);
    device_ = in.device_;
    data_type_ = in.data_type_;
    block_ = device_->NewBlock((int)in.MemSize());
  }
  shape_ = in.shape_;
  stride_ = in.stride_;
  return *this;
}

Tensor &Tensor::Resize(const Shape &shape) {
  if (Size() != Product(shape)) {
    if (block_ != nullptr && block_->DecRefCount() == 0)
      device_->FreeBlock(block_);
    block_ = device_->NewBlock((int)(Product(shape) * SizeOf(data_type_)));
  }
  shape_ = shape;
  generate_stride();
  return *this;
}

Tensor Resize(const Tensor &in, const Shape &shape) {
  Tensor out(in);
  out.Resize(shape);
  return out;
}

#define TYPE_TYPE_LANG_SWITCH(ldtype, LDType, rdtype, RDType, ltype, Lang,     \
                              ...)                                             \
  do {                                                                         \
    const int _SwitchShift = 3;                                                \
    int _SwitchHash =                                                          \
        ((ldtype) << _SwitchShift * 2) + ((rdtype) << _SwitchShift) + (ltype); \
    switch (_SwitchHash) {                                                     \
      case (((kFloat32) << _SwitchShift * 2) + (kInt << _SwitchShift) +        \
            kCuda): {                                                          \
        typedef float LDType;                                                  \
        typedef int RDType;                                                    \
        typedef lang::Cuda Lang;                                               \
        { __VA_ARGS__ }                                                        \
        break;                                                                 \
      }                                                                        \
      case (((kInt) << _SwitchShift * 2) + (kFloat32 << _SwitchShift) +        \
            kCuda): {                                                          \
        typedef int LDType;                                                    \
        typedef float RDType;                                                  \
        typedef lang::Cuda Lang;                                               \
        { __VA_ARGS__ }                                                        \
        break;                                                                 \
      }                                                                        \
      case (((kFloat32) << _SwitchShift * 2) + (kInt << _SwitchShift) +        \
            kCpp): {                                                           \
        typedef float LDType;                                                  \
        typedef int RDType;                                                    \
        typedef lang::Cpp Lang;                                                \
        { __VA_ARGS__ }                                                        \
        break;                                                                 \
      }                                                                        \
      case (((kInt) << _SwitchShift * 2) + (kFloat32 << _SwitchShift) +        \
            kCpp): {                                                           \
        typedef int LDType;                                                    \
        typedef float RDType;                                                  \
        typedef lang::Cpp Lang;                                                \
        { __VA_ARGS__ }                                                        \
        break;                                                                 \
      }                                                                        \
      default:                                                                 \
        LOG(FATAL) << "Unknown combination of left data type "                 \
                   << DataType_Name(ldtype) << " and right data type "         \
                   << DataType_Name(rdtype) << " and language "                \
                   << LangType_Name(ltype);                                    \
    }                                                                          \
  } while (0)

// return new tensor
Tensor Tensor::AsType(const DataType type) {
  CHECK(block() && block()->initialized() == true)
      << "the data of the tensor needs be initialized before casting to "
         "another type";
  if (data_type_ != type) {
    Tensor &thisRef = *this;
    Tensor ret(shape_, device_, type);
    TYPE_TYPE_LANG_SWITCH(
        data_type_, LDType, type, RDType, device_->lang(), Lang, {
          ret.device()->Exec(
              [thisRef, ret](Context *ctx) mutable {
                CastCopy<LDType, RDType, Lang>(&thisRef, &ret, ctx);
              },
              {this->block()}, {ret.block()}, "AsType");
        });
    return ret;
  } else {
    Tensor t = this->Clone();
    return t;
  }
}

Tensor &Tensor::ToDevice(std::shared_ptr<Device> dst) {
  // TODO(wangwei) the comparison is restricted. May compare against device ID?
  if (device_ != dst) {
    // WARNING: this function can't be buffered
    Tensor tmp(shape_, dst, data_type_);
    if (block_ != nullptr && Size() && block_->initialized())
      tmp.CopyData(*this);
    if (block_ != nullptr && block_->DecRefCount() == 0)
      device_->FreeBlock(block_);
    block_ = tmp.block_;
    tmp.block_ = nullptr;
    device_ = dst;
  }
  return *this;
}

Tensor &Tensor::ToHost() {
  if (device_ != defaultDevice) ToDevice(device_->host());
  return *this;
}

template <typename DType>
void Tensor::CopyDataFromHostPtr(const DType *src, const size_t num,
                                 const size_t offset) const {
  CHECK_EQ(sizeof(DType), SizeOf(data_type_))
      << "data_type is " << DataType_Name(data_type_)
      << " user given type is of size " << sizeof(DType);
  if (src != nullptr) {
    Device *dev = device_.get();
    const Tensor &thisRef = *this;
    size_t nBytes = sizeof(DType) * num;
    size_t dst_offset = sizeof(DType) * offset;
    device_->Exec(
        [dev, thisRef, src, nBytes, dst_offset](Context *ctx) mutable {
          dev->CopyDataFromHostPtr(thisRef.block(), src, nBytes, dst_offset,
                                   ctx);
        },
        {}, {block()}, "CopyDataFromHostPtr");
  } else {
    LOG(WARNING) << "Copy data from null host ptr";
  }
}
template void Tensor::CopyDataFromHostPtr(const unsigned char *src,
                                          const size_t num,
                                          const size_t offset) const;
template void Tensor::CopyDataFromHostPtr(const float *src, const size_t num,
                                          const size_t offset) const;
template void Tensor::CopyDataFromHostPtr(const int *src, const size_t num,
                                          const size_t offset) const;

void Tensor::CopyData(const Tensor &src) {
  CHECK_EQ(Size(), src.Size());
  CHECK(block_ != nullptr);
  // Do copy only if the src's block is already initialized.
  if (src.block_ != nullptr) {
    singa::CopyDataToFrom(this, src, Size(), 0, 0);
  }
}

void Tensor::RepeatData(const vector<size_t> &repeats, int axis,
                        int total_repeats, const Tensor &src) {
  if (repeats.size() == 1) {
    CHECK_EQ(Size(), src.Size() * total_repeats);
  } else {
    CHECK_EQ(Size(), src.Size() * total_repeats / src.shape()[axis]);
  }

  CHECK(block_ != nullptr);
  // Do repeat only if the src's block is already initialized.
  if (src.block_ != nullptr) {
    singa::RepeatDataToFrom(false, repeats, axis, this, src, Size());
  }
}

void Tensor::FromProto(const singa::TensorProto &proto) {
  if (block_ != nullptr && block_->DecRefCount() == 0)
    device_->FreeBlock(block_);
  block_ = nullptr;
  for (uint32_t s : proto.shape()) shape_.push_back(s);
  data_type_ = proto.data_type();
  block_ = device_->NewBlock((int)(Product(shape()) * SizeOf(data_type_)));
  // transpose_ = proto.transpose();
  stride_.clear();
  for (int32_t s : proto.stride()) stride_.push_back(s);
  switch (data_type_) {
    case kFloat32: {
      std::unique_ptr<float[]> data_ptr(new float[Product(shape_)]);
      for (size_t i = 0; i < Product(shape_); ++i)
        data_ptr[i] = static_cast<float>(proto.float_data((int)i));
      CopyDataFromHostPtr<float>(data_ptr.get(), Product(shape_));
      break;
    }
    case kDouble: {
      std::unique_ptr<double[]> data(new double[Product(shape_)]);
      for (size_t i = 0; i < Product(shape_); ++i)
        data[i] = proto.double_data((int)i);
      CopyDataFromHostPtr<double>(data.get(), Product(shape_));
      break;
    }
    case kInt: {
      std::unique_ptr<int[]> data(new int[Product(shape_)]);
      for (size_t i = 0; i < Product(shape_); ++i)
        data[i] = proto.int_data((int)i);
      CopyDataFromHostPtr<int>(data.get(), Product(shape_));
      break;
    }
    /// TODO(wangji): Implement to support C++ type char using bytes type in
    /// protobuf
    /// which is equivalent to string type is different from the other cases.
    /// The kchar
    /// and kUChar case is to be implemented.
    /*
    case kChar: {
      std::unique_ptr<char[]> data(new char[Product(shape_)]);
      for (size_t i = 0; i < Product(shape_); ++i)
        data[i] = static_cast<char>(proto.bytes_data(i));
      break;
    }
    case kUChar: {
      std::unique_ptr<unsigned char[]> data(new unsigned char[Product(shape_)]);
      for (size_t i = 0; i < Product(shape_); ++i)
        data[i] = static_cast<unsigned char>(proto.bytes_data(i));
      break;
    }
    */
    default: {
      LOG(FATAL) << "Unsupported Type" << DataType_Name(data_type_);
    }
  }
}

void Tensor::to_proto(singa::TensorProto *proto) const {
  proto->clear_shape();
  for (auto s : shape_) {
    proto->add_shape(s);
  }
  proto->set_data_type(data_type_);
  // proto->set_transpose(transpose_);
  proto->clear_stride();
  for (auto s : stride_) {
    proto->add_stride(s);
  }
  switch (data_type_) {
    case kFloat32: {
      proto->clear_float_data();
      const float *data_ptr = data<float>();
      for (size_t i = 0; i < Product(shape_); ++i)
        proto->add_float_data(data_ptr[i]);
      break;
    }
    case kDouble: {
      proto->clear_double_data();
      const double *data_ptr = data<double>();
      for (size_t i = 0; i < Product(shape_); ++i)
        proto->add_double_data(data_ptr[i]);
      break;
    }
    case kInt: {
      proto->clear_int_data();
      const int *data_ptr = data<int>();
      for (size_t i = 0; i < Product(shape_); ++i)
        proto->add_int_data(data_ptr[i]);
      break;
    }
    /*
    case kChar: {
      proto->clear_bytes_data();
      const char *data = data<char>();
      for (size_t i = 0; i < Product(shape_); ++i)
        proto->add_bytes_data(static_cast<unsigned char>(data[i]));
      break;
    }
    case kUChar: {
      proto->clear_bytes_data();
      const unsigned char *data = data<unsigned char>();
      for (size_t i = 0; i < Product(shape_); ++i)
        proto->add_bytes_data(static_cast<unsigned char>(data[i]));
      break;
    }
    */
    default: {
      LOG(FATAL) << "Unsupported Type" << DataType_Name(data_type_);
    }
  }
}

void Tensor::ToProto(singa::TensorProto *proto) const { to_proto(proto); }

Tensor Tensor::Repeat(const vector<size_t> &repeats, int axis,
                      std::shared_ptr<Device> device) {
  if (device == nullptr) device = device_;
  vector<size_t> tshape;
  int total_repeats = 0;
  if (axis == Noaxis) {
    total_repeats = repeats[0];
    tshape.push_back(Product(shape_) * total_repeats);
  } else {
    if (repeats.size() == 1) {
      total_repeats = repeats[0];
      for (int i = 0; i < static_cast<int>(shape_.size()); i++) {
        if (i == axis) {
          tshape.push_back(shape_[i] * total_repeats);
        } else {
          tshape.push_back(shape_[i]);
        }
      }
    } else {
      if (repeats.size() != shape_[axis]) {
        LOG(FATAL) << "the repeats number doesn't match the axis";
      }
      for (size_t i = 0; i < shape_[axis]; i++) {
        if (repeats[i] < 0) {
          LOG(FATAL) << "the repeats number is less than zero";
        }
        total_repeats += repeats[i];
      }
      for (int i = 0; i < static_cast<int>(shape_.size()); i++) {
        if (i == axis) {
          tshape.push_back(total_repeats);
        } else {
          tshape.push_back(shape_[i]);
        }
      }
    }
  }
  Tensor t(tshape, device_);
  // t.stride_.push_back(1);
  t.RepeatData(repeats, axis, total_repeats, *this);
  return t;
}

Tensor Tensor::Clone(std::shared_ptr<Device> device) const {
  if (device == nullptr) device = device_;
  Tensor t(shape_, device, data_type_);
  // t.transpose_ = transpose_;
  t.stride_ = stride_;
  t.CopyData(*this);
  return t;
}

void Tensor::Clone(Tensor *&other, std::shared_ptr<Device> device) const {
  if (device == nullptr) device = device_;
  other = new Tensor(shape_, device, data_type_);
  other->stride_ = stride_;
  other->CopyData(*this);
  return;
}

Tensor &Tensor::Broadcast(const Shape &shape, const int ignore_last_dim) {
  // TODO(wangwei) do we need to transform the mem layout if the tensor was
  // transposed?
  auto m = shape_.size() - 1, n = shape.size() - 1;
  // ignore_last_dim is useful for mult broadcast
  // e.g. (2,3,4)x(4,5) to (2,3,4)x(2,4,5)
  if (ignore_last_dim < std::min(m, n) + 1) {
    for (size_t i = ignore_last_dim; i <= std::min(m, n); i++) {
      if ((shape.at(n - i) != shape_.at(m - i)) && (shape.at(n - i) != 1)) {
        CHECK_EQ(shape_.at(m - i), 1) << "i= " << i << "\n";  // << Backtrace();
        shape_.at(m - i) = shape.at(n - i);
        stride_.at(m - i) = 0;
      }
    }
  }
  if (m < n) {
    for (size_t i = m + 1; i <= n; i++) {
      shape_.emplace(shape_.begin(), shape.at(n - i));
      stride_.emplace(stride_.begin(), 0);
    }
  }
  return *this;
}

Tensor Broadcast(const Tensor &in, const Shape &shape,
                 const int ignore_last_dim) {
  Tensor out(in);
  return out.Broadcast(shape, ignore_last_dim);
}

Tensor &Tensor::T() {
  // this function only works for 2d tensors
  CHECK_EQ(shape_.size(), 2u);
  Transpose();
  return *this;
}

// normal transpose without axes
Tensor &Tensor::Transpose() {
  std::reverse(shape_.begin(), shape_.end());
  std::reverse(stride_.begin(), stride_.end());
  return *this;
}

// transpose with axes
Tensor &Tensor::Transpose(const vector<size_t> &axes) {
  CHECK_EQ(axes.size(), shape_.size())
      << "Tranpose axes's length should be equal to shape";

  auto shape = shape_;
  auto stride = stride_;
  shape_.clear();
  stride_.clear();
  for (size_t n = 0; n < axes.size(); ++n) {
    shape_.push_back(shape[axes[n]]);
    stride_.push_back(stride[axes[n]]);
  }
  return *this;
}

// normal transpose without axes
Tensor Transpose(const Tensor &in) {
  Tensor out(in);
  out.Transpose();
  return out;
}

// transpose with axes
Tensor Transpose(const Tensor &in, const vector<size_t> &axes) {
  Tensor out(in);
  out.Transpose(axes);
  return out;
}

Tensor &Tensor::operator=(const Tensor &in) {
  if (block_ != nullptr && block_->DecRefCount() == 0)
    device_->FreeBlock(block_);
  stride_ = in.stride_;
  data_type_ = in.data_type_;
  shape_ = in.shape_;
  device_ = in.device_;
  block_ = in.block();
  if (block_ != nullptr) block_->IncRefCount();
  return *this;
}

Tensor &Tensor::operator=(Tensor &&in) {
  if (block_ != nullptr && block_->DecRefCount() == 0)
    device_->FreeBlock(block_);
  stride_ = std::move(in.stride_);
  data_type_ = in.data_type_;
  shape_ = std::move(in.shape_);
  device_ = in.device_;
  block_ = in.block_;
  in.block_ = nullptr;
  return *this;
}

#define GenUnaryTensorArgMemberFn(op, fn) \
  Tensor &Tensor::op(const Tensor &in) {  \
    Tensor out(*this);                    \
    fn(*this, in, &out);                  \
    return *this;                         \
  }

GenUnaryTensorArgMemberFn(operator+=, Add);
GenUnaryTensorArgMemberFn(operator-=, Sub);
GenUnaryTensorArgMemberFn(operator*=, EltwiseMult);
GenUnaryTensorArgMemberFn(operator/=, Div);

#define GenUnaryScalarArgMemberFn(op, fn) \
  template <typename DType>               \
  Tensor &Tensor::op(const DType x) {     \
    Tensor out(*this);                    \
    fn(*this, x, &out);                   \
    return *this;                         \
  }                                       \
  template Tensor &Tensor::op<float>(const float x)

GenUnaryScalarArgMemberFn(operator-=, Sub);
GenUnaryScalarArgMemberFn(operator+=, Add);
GenUnaryScalarArgMemberFn(operator*=, EltwiseMult);
GenUnaryScalarArgMemberFn(operator/=, Div);

// ====================Tensor Operations=======================================
void CopyDataToFrom(Tensor *dst, const Tensor &src, const size_t num,
                    const size_t dst_offset, const size_t src_offset) {
  auto width = SizeOf(src.data_type());
  CHECK_EQ(width, SizeOf(dst->data_type()));
  size_t nBytes = num * width;
  auto d_offset = dst_offset * width;
  auto s_offset = src_offset * width;
  CHECK_GE(src.MemSize(), s_offset + nBytes);
  CHECK_GE(dst->MemSize(), d_offset + nBytes);

  Device *dev = nullptr;
  CopyDirection direct;
  std::shared_ptr<Device> src_dev = src.device(), dst_dev = dst->device();
  if (dst_dev->lang() != src_dev->lang()) {
    // let the none cpp device conduct copy op
    if (dst_dev->lang() == kCpp) {
      dev = src_dev.get();
      direct = kDeviceToHost;
    } else if (src_dev->lang() == kCpp) {
      dev = dst_dev.get();
      direct = kHostToDevice;
    } else {
      LOG(FATAL) << "Not support mem copy between Cuda and OpenCL device";
    }
  } else {
    dev = src_dev.get();
    direct = src_dev->lang() == kCpp ? kHostToHost : kDeviceToDevice;
  }

  Tensor &dstRef = *dst;
  dev->Exec(
      [dev, dstRef, src, nBytes, direct, d_offset,
       s_offset](Context *ctx) mutable {
        Block *from = src.block(), *to = dstRef.block();
        dev->CopyDataToFrom(to, from, nBytes, direct, (int)d_offset,
                            (int)s_offset, ctx);
      },
      {src.block()}, {dst->block()}, "CopyDataToFrom");
}

void RepeatDataToFrom(bool broadcast_flag, const vector<size_t> &repeats,
                      int axis, Tensor *dst, const Tensor &src,
                      const size_t num) {
  if (repeats.size() == 1) {
    broadcast_flag = true;
  } else if (repeats.size() > 1) {
    if (axis == Noaxis) {
      LOG(FATAL) << "When repeats parameter is sequence, axis cannot be None";
    }
  }
  for (size_t i = 0; i < repeats.size(); i++) {
    CHECK_GE(repeats[i], 0);
  }
  auto width = SizeOf(src.data_type());
  CHECK_EQ(width, SizeOf(dst->data_type()));
  // size_t nBytes = num * width;
  int chunk = width;
  int axis_shape = 1;
  int shape_outer = 1;
  if (axis == Noaxis) {
    axis_shape = 1;
    shape_outer = Product(src.shape());
  } else {
    for (int i = 0; i < axis; i++) {
      shape_outer *= src.shape()[i];
    }
    axis_shape = src.shape()[axis];
    for (int i = axis + 1; i < static_cast<int>(src.nDim()); i++) {
      chunk *= src.shape()[i];
    }
  }

  Device *dev = nullptr;
  CopyDirection direct;
  std::shared_ptr<Device> src_dev = src.device(), dst_dev = dst->device();
  if (dst_dev->lang() != src_dev->lang()) {
    // let the none cpp device conduct copy op
    if (dst_dev->lang() == kCpp) {
      dev = src_dev.get();
      direct = kDeviceToHost;
    } else if (src_dev->lang() == kCpp) {
      dev = dst_dev.get();
      direct = kHostToDevice;
    } else {
      LOG(FATAL)
          << "Not support mem repeat copy between Cuda and OpenCL device";
    }
  } else {
    dev = src_dev.get();
    direct = src_dev->lang() == kCpp ? kHostToHost : kDeviceToDevice;
  }

  int dst_offset = 0;
  int src_offset = 0;
  Tensor &dstRef = *dst;
  for (int i = 0; i < shape_outer; i++) {
    for (int j = 0; j < axis_shape; j++) {
      int temp = broadcast_flag ? repeats[0] : repeats[j];
      for (int k = 0; k < temp; k++) {
        dev->Exec(
            [dev, dstRef, src, chunk, direct, dst_offset,
             src_offset](Context *ctx) mutable {
              Block *from = src.block(), *to = dstRef.block();
              dev->CopyDataToFrom(to, from, chunk, direct, dst_offset,
                                  src_offset, ctx);
            },
            {src.block()}, {dst->block()}, "CopyDataToFrom");
        dst_offset += chunk;
      }
      src_offset += chunk;
    }
  }
}

//============================================================================
/// typedef DType accroding to type value.
/// DType would be used in the code block __VA_ARGS__.
#define TYPE_SWITCH(type, DType, ...)                               \
  do {                                                              \
    switch (type) {                                                 \
      case kFloat32: {                                              \
        typedef float DType;                                        \
        { __VA_ARGS__ }                                             \
        break;                                                      \
      }                                                             \
      case kInt: {                                                  \
        typedef int DType;                                          \
        { __VA_ARGS__ }                                             \
        break;                                                      \
      }                                                             \
      case kChar: {                                                 \
        typedef char DType;                                         \
        { __VA_ARGS__ }                                             \
        break;                                                      \
      }                                                             \
      case kDouble: {                                               \
        typedef double DType;                                       \
        { __VA_ARGS__ }                                             \
        break;                                                      \
      }                                                             \
      default:                                                      \
        LOG(FATAL) << "Unknow data type = " << DataType_Name(type); \
    }                                                               \
  } while (0)

/// typedef DType and Lang according to data type and device programming
/// language respectively.
/// type is from DataType, and lang is from LangType.
/// DType and Lang would be used in __VA_ARGS__.
#define TYPE_LANG_SWITCH(dtype, DType, ltype, Lang, ...)       \
  do {                                                         \
    const int _SwitchShift = 3;                                \
    int _SwitchHash = ((dtype) << _SwitchShift) + (ltype);     \
    switch (_SwitchHash) {                                     \
      case ((kFloat32 << _SwitchShift) + kCuda): {             \
        typedef float DType;                                   \
        typedef lang::Cuda Lang;                               \
        { __VA_ARGS__ }                                        \
        break;                                                 \
      }                                                        \
      case ((kInt << _SwitchShift) + kCuda): {                 \
        typedef int DType;                                     \
        typedef lang::Cuda Lang;                               \
        { __VA_ARGS__ }                                        \
        break;                                                 \
      }                                                        \
      case ((kFloat32 << _SwitchShift) + kCpp): {              \
        typedef float DType;                                   \
        typedef lang::Cpp Lang;                                \
        { __VA_ARGS__ }                                        \
        break;                                                 \
      }                                                        \
      case ((kInt << _SwitchShift) + kCpp): {                  \
        typedef int DType;                                     \
        typedef lang::Cpp Lang;                                \
        { __VA_ARGS__ }                                        \
        break;                                                 \
      }                                                        \
      case ((kFloat32 << _SwitchShift) + kOpencl): {           \
        typedef float DType;                                   \
        typedef lang::Opencl Lang;                             \
        { __VA_ARGS__ }                                        \
        break;                                                 \
      }                                                        \
      default:                                                 \
        LOG(FATAL) << "Unknown combination of data type "      \
                   << DataType_Name(dtype) << " and language " \
                   << LangType_Name(ltype);                    \
    }                                                          \
  } while (0)

// =============Element-wise operations====================================
float Tensor::l1() const {
  float nrm = 0.0f;
  TYPE_LANG_SWITCH(data_type_, DType, device_->lang(), Lang, {
    device_->Exec(
        [&nrm, this](Context *ctx) {
          DType ret = DType(0);
          Asum<DType, Lang>(*this, &ret, ctx);
          nrm = TypeCast<DType, float>(ret);
        },
        {this->block()}, {}, "l1");
  });
  return nrm / Size();
}

// DEPRECATED use l1()
float Tensor::L1() const { return l1(); }

/// L2 norm, Do not use Nrm2 (name conflict).
float Tensor::l2() const {
  float nrm = 0.0f;
  TYPE_LANG_SWITCH(data_type_, DType, device_->lang(), Lang, {
    device_->Exec(
        [&nrm, this](Context *ctx) {
          Nrm2<DType, Lang>(*this, &nrm, ctx);
        },
        {this->block()}, {}, "L1");
  });
  return nrm / Size();
}

// DEPRECATED use l2()
float Tensor::L2() const { return l2(); }

template <typename SType>
void Tensor::SetValue(const SType x) {
  CHECK_EQ(sizeof(SType), SizeOf(data_type_));
  // auto size = Size();
  auto ptr = block_;

  TYPE_LANG_SWITCH(data_type_, DType, device_->lang(), Lang, {
    // TODO(wangwei) cast x to DType
    Tensor &thisRef = *this;
    device_->Exec(
        [thisRef, x](Context *ctx) mutable {
          Set<DType, Lang>(x, &thisRef, ctx);
        },
        {}, {ptr}, "SetValue");
  });
}
template void Tensor::SetValue<float>(const float x);
template void Tensor::SetValue<int>(const int x);

template <typename SType>
void Tensor::get_value(SType *value, const size_t num) const {
  CHECK(device_ == defaultDevice);
  Tensor t(shape_, device_, data_type_);
  // transform function arrange data in memory considering stride
  singa::Transform(*this, &t);
  auto ptr = static_cast<const SType *>(t.block()->data());
  for (size_t i = 0; i < num; i++) value[i] = ptr[i];
}
template void Tensor::get_value<float>(float *value, const size_t num) const;
template void Tensor::get_value<int>(int *value, const size_t num) const;

// DEPRECATED
template <typename SType>
void Tensor::GetValue(SType *value, const size_t num) const {
  get_value(value, num);
}
template void Tensor::GetValue<float>(float *value, const size_t num) const;
template void Tensor::GetValue<int>(int *value, const size_t num) const;

#define EltwiseUnaryTensorFn(fn, t, ret)                               \
  do {                                                                 \
    TYPE_LANG_SWITCH(t.data_type(), DType, t.device()->lang(), Lang, { \
      Tensor &retRef = *ret;                                           \
      ret->device()->Exec(                                             \
          [t, retRef](Context *ctx) mutable {                          \
            fn<DType, Lang>(t, &retRef, ctx);                          \
          },                                                           \
          {t.block()}, {ret->block()}, #fn);                           \
    });                                                                \
  } while (0)

#define GenUnaryTensorFn(fn)                             \
  Tensor fn(const Tensor &in) {                          \
    Tensor ret(in.shape(), in.device(), in.data_type()); \
    Tensor *retptr = &ret;                               \
    EltwiseUnaryTensorFn(fn, in, retptr);                \
    return ret;                                          \
  }                                                      \
  void fn(const Tensor &in, Tensor *out) { EltwiseUnaryTensorFn(fn, in, out); }

GenUnaryTensorFn(Abs);
GenUnaryTensorFn(Erf);
GenUnaryTensorFn(Ceil);
GenUnaryTensorFn(Floor);
GenUnaryTensorFn(Round);
GenUnaryTensorFn(RoundE);
GenUnaryTensorFn(Exp);
GenUnaryTensorFn(Log);
GenUnaryTensorFn(ReLU);
GenUnaryTensorFn(Sigmoid);
GenUnaryTensorFn(SoftPlus);
GenUnaryTensorFn(SoftSign);
GenUnaryTensorFn(Sign);
GenUnaryTensorFn(Sqrt);
GenUnaryTensorFn(Square);
GenUnaryTensorFn(Transform);
GenUnaryTensorFn(Cos);
GenUnaryTensorFn(Cosh);
GenUnaryTensorFn(Acos);
GenUnaryTensorFn(Acosh);
GenUnaryTensorFn(Sin);
GenUnaryTensorFn(Sinh);
GenUnaryTensorFn(Asin);
GenUnaryTensorFn(Asinh);
GenUnaryTensorFn(Tan);
GenUnaryTensorFn(Tanh);
GenUnaryTensorFn(Atan);
GenUnaryTensorFn(Atanh);
GenUnaryTensorFn(SoftMax);

// add axis to softmax API according to ONNX specification
// https://github.com/onnx/onnx/blob/master/docs/Operators.md#Softmax
void SoftMax(const Tensor &in, Tensor *out, int axis) {
  // {a_0, a_1, ..., a_k-1, a_k, ... a_n-1}
  // reshape to
  // { a_0 * a_1 * ... a_k-1, a_k * ... a_n-1 }

  // assert axis \in {-r, r-1}
  CHECK_LE(axis, (int)in.shape().size() - 1);
  CHECK_GE(axis, -1 * (int)in.nDim());

  Shape original_shape = in.shape();
  if (axis < 0) axis = in.shape().size() + axis;

  Shape coerced_shape = {1, 1};
  for (std::size_t i = 0, max = in.shape().size(); i != max; ++i) {
    if (i < axis)
      coerced_shape[0] *= in.shape()[i];
    else
      coerced_shape[1] *= in.shape()[i];
  }
  Tensor in_reshaped = Reshape(in, coerced_shape);
  out->Reshape(coerced_shape);

  // optimise by minus x - x.max()
  auto in_max = RowMax(in_reshaped);
  in_max.Reshape({coerced_shape[0], 1});
  in_reshaped = in_reshaped - in_max;

  SoftMax(in_reshaped, out);

  out->Reshape(original_shape);
}

Tensor SoftMax(const Tensor &in, int axis) {
  Tensor ret(in.shape(), in.device(), in.data_type());
  auto *retptr = &ret;
  SoftMax(in, retptr, axis);
  return ret;
}
void SoftMaxBackward(const Tensor &in, Tensor *out, int axis,
                     const Tensor &fdout) {
  // {a_0, a_1, ..., a_k-1, a_k, ... a_n-1}
  // reshape to
  // { a_0 * a_1 * ... a_k-1, a_k * ... a_n-1 }

  // assert axis \in {-r, r-1}
  CHECK_LE(axis, (int)in.shape().size() - 1);
  CHECK_GE(axis, -1 * (int)in.nDim());

  Shape original_shape = in.shape();
  if (axis < 0) axis = in.shape().size() + axis;

  Shape coerced_shape = {1, 1};
  for (std::size_t i = 0, max = in.shape().size(); i != max; ++i) {
    if (i < axis)
      coerced_shape[0] *= in.shape()[i];
    else
      coerced_shape[1] *= in.shape()[i];
  }

  Tensor in_reshaped = Reshape(in, coerced_shape);
  out->Reshape(coerced_shape);

  do {
    TYPE_LANG_SWITCH(in.data_type(), DType, in.device()->lang(), Lang, {
      Tensor &outRef = *out;
      out->device()->Exec(
          [in, outRef, fdout](Context *ctx) mutable {
            SoftMaxBackward<DType, Lang>(in, &outRef, fdout, ctx);
          },
          {in.block(), fdout.block()}, {out->block()}, "SoftmaxBackward");
    });
  } while (0);

  out->Reshape(original_shape);
}

Tensor SoftMaxBackward(const Tensor &in, int axis, const Tensor &fdout) {
  Tensor ret(in.shape(), in.device(), in.data_type());
  auto *retptr = &ret;
  SoftMaxBackward(in, retptr, axis, fdout);
  return ret;
}

#define EltwiseBinaryTensorFn(fn, lhs, rhs, ret)                           \
  do {                                                                     \
    TYPE_LANG_SWITCH(lhs.data_type(), DType, lhs.device()->lang(), Lang, { \
      CHECK_EQ(sizeof(DType), SizeOf(rhs.data_type()));                    \
      Tensor &retRef = *ret;                                               \
      ret->device()->Exec(                                                 \
          [lhs, rhs, retRef](Context *ctx) mutable {                       \
            fn<DType, Lang>(lhs, rhs, &retRef, ctx);                       \
          },                                                               \
          {lhs.block(), rhs.block()}, {ret->block()}, #fn);                \
    });                                                                    \
  } while (0)

#define GenBinaryTensorFn(op, fn)                                           \
  Tensor op(const Tensor &lhs, const Tensor &rhs) {                         \
    if (lhs.shape() != rhs.shape()) {                                       \
      if (lhs.data_type() == kFloat32 && rhs.data_type() == kFloat32) {     \
        auto lhs_ = Broadcast(lhs, rhs.shape());                            \
        auto rhs_ = Broadcast(rhs, lhs.shape());                            \
        Tensor ret(lhs_.shape(), lhs.device(), lhs.data_type());            \
        fn(lhs_, rhs_, &ret);                                               \
        return ret;                                                         \
      } else {                                                              \
        /* lhs tensor and rhs tensor are not both in float, cast to float */\
        Tensor tmp_lhs = lhs.Clone().AsType(kFloat32);                      \
        Tensor tmp_rhs = rhs.Clone().AsType(kFloat32);                      \
        tmp_lhs = Broadcast(tmp_lhs, tmp_rhs.shape());                      \
        tmp_rhs = Broadcast(tmp_rhs, tmp_lhs.shape());                      \
        Tensor ret(tmp_lhs.shape(), tmp_lhs.device(), tmp_lhs.data_type()); \
        fn(tmp_lhs, tmp_rhs, &ret);                                         \
        /* if lhs and rhs are both int, cast back to int */                 \
        if (lhs.data_type() == kInt && rhs.data_type() == kInt)             \
          return ret.Clone().AsType(kInt);                                  \
        return ret;                                                         \
      }                                                                     \
    } else {                                                                \
      if (lhs.data_type() == kFloat32 && rhs.data_type() == kFloat32) {     \
        Tensor ret(lhs.shape(), lhs.device(), lhs.data_type());             \
        fn(lhs, rhs, &ret);                                                 \
        return ret;                                                         \
      } else {                                                              \
        /* lhs tensor and rhs tensor are not both in float, cast to float */\
        Tensor tmp_lhs = lhs.Clone().AsType(kFloat32);                      \
        Tensor tmp_rhs = rhs.Clone().AsType(kFloat32);                      \
        Tensor ret(tmp_lhs.shape(), tmp_lhs.device(), tmp_lhs.data_type()); \
        fn(tmp_lhs, tmp_rhs, &ret);                                         \
        /* if lhs and rhs are both int, cast back to int */                 \
        if (lhs.data_type() == kInt && rhs.data_type() == kInt)             \
          return ret.Clone().AsType(kInt);                                  \
        return ret;                                                         \
      }                                                                     \
    }                                                                       \
  }                                                                         \
  void fn(const Tensor &lhs, const Tensor &rhs, Tensor *ret) {              \
    CHECK_EQ(lhs.device(), ret->device());                                  \
    CHECK_EQ(rhs.device(), ret->device());                                  \
    if (lhs.shape() != rhs.shape()) {                                       \
      auto lhs_ = Broadcast(lhs, rhs.shape());                              \
      auto rhs_ = Broadcast(rhs, lhs.shape());                              \
      CHECK(lhs_.shape() == ret->shape());                                  \
      EltwiseBinaryTensorFn(fn, lhs_, rhs_, ret);                           \
    } else {                                                                \
      CHECK(lhs.shape() == ret->shape());                                   \
      EltwiseBinaryTensorFn(fn, lhs, rhs, ret);                             \
    }                                                                       \
  }  // namespace singa

// boradcasting operations:
// https://github.com/onnx/onnx/blob/master/docs/Broadcasting.md
GenBinaryTensorFn(operator+, Add);
GenBinaryTensorFn(operator-, Sub);
GenBinaryTensorFn(operator*, EltwiseMult);
GenBinaryTensorFn(operator/, Div);
GenBinaryTensorFn(Pow, Pow);
GenBinaryTensorFn(operator<, LT);
GenBinaryTensorFn(operator<=, LE);
GenBinaryTensorFn(operator>, GT);
GenBinaryTensorFn(operator>=, GE);
GenBinaryTensorFn(operator==, EQ);
GenBinaryTensorFn(ReLUBackward, ReLUBackward);

#define EltwiseTensorScalarFn(fn, t, x, ret)                            \
  do {                                                                  \
    TYPE_LANG_SWITCH(t.data_type(), DType, t.device()->lang(), Lang, {  \
      Tensor &retRef = *ret;                                            \
      ret->device()->Exec(                                              \
          [t, x, retRef](Context *ctx) mutable {                        \
            fn<DType, Lang>(t, x, &retRef, ctx);                        \
          },                                                            \
          {t.block()}, {ret->block()}, #fn);                            \
    });                                                                 \
  } while (0)

#define GenTensorScalarFn(op, fn)                                          \
  template <typename SType>                                                \
  Tensor op(const Tensor &in, const SType x) {                             \
    if (in.data_type() == kFloat32 && std::is_same<SType, float>::value){  \
      Tensor ret(in.shape(), in.device(), in.data_type());                 \
      fn(in, x, &ret);                                                     \
      return ret;                                                          \
    } else if (in.data_type() == kFloat32) {                               \
      Tensor ret(in.shape(), in.device(), in.data_type());                 \
      float tmp_x = x;                                                     \
      fn(in, tmp_x, &ret);                                                 \
      return ret;                                                          \
    } else {                                                               \
      /* tensor and scalar are not both in float, cast to float */         \
      Tensor tmp_in = in.Clone().AsType(kFloat32);                         \
      float tmp_x = x;                                                     \
      Tensor ret(tmp_in.shape(), tmp_in.device(), tmp_in.data_type());     \
      fn(tmp_in, tmp_x, &ret);                                             \
      /* if tensor and scalar are both int, cast back to int */            \
      if (in.data_type() == kInt && std::is_same<SType, int>::value)       \
        return ret.Clone().AsType(kInt);                                   \
      return ret;                                                          \
    }                                                                      \
  }                                                                        \
  template <typename SType>                                                \
  void fn(const Tensor &in, const SType x, Tensor *ret) {                  \
    EltwiseTensorScalarFn(fn, in, x, ret);                                 \
  }                                                                        \
  template Tensor op<float>(const Tensor &in, const float x);              \
  template void fn<float>(const Tensor &in, const float x, Tensor *ret)

GenTensorScalarFn(operator+, Add);
GenTensorScalarFn(operator-, Sub);
GenTensorScalarFn(operator*, EltwiseMult);
GenTensorScalarFn(operator/, Div);
GenTensorScalarFn(Pow, Pow);
GenTensorScalarFn(operator<, LT);
GenTensorScalarFn(operator<=, LE);
GenTensorScalarFn(operator>, GT);
GenTensorScalarFn(operator>=, GE);
GenTensorScalarFn(operator==, EQ);

template <typename SType>
Tensor Div(const SType alpha, const Tensor &in) {
  Tensor out(in.shape(), in.device(), in.data_type());
  Div(alpha, in, &out);
  return out;
}
template Tensor Div<float>(const float, const Tensor &);

template <typename SType>
void Div(const SType alpha, const Tensor &in, Tensor *out) {
  CheckDataTypeAndLang(in, *out);
  CHECK(in.shape() == out->shape());
  TYPE_LANG_SWITCH(in.data_type(), DType, in.device()->lang(), Lang, {
    // TODO(wangwei) type cast SType to DType;
    Tensor &outRef = *out;
    in.device()->Exec(
        [alpha, in, outRef](Context *ctx) mutable {
          Div<DType, Lang>(alpha, in, &outRef, ctx);
        },
        {in.block()}, {out->block()}, "Div");
  });
}
template void Div<float>(const float, const Tensor &, Tensor *);

// =============Matrix operations============================================
Tensor Average(const Tensor &M, int axis) {
  // operator/ only has implementation for float scalar type, hence it is
  // necessary to cast the denominator to a float.
  // TODO(wangwei) implement function for cast scalar type involved in Tensor
  // functions. E.g.,
  // template<S, D>
  // D CastTo(S x) {
  //   return D(x);
  // }
  // for speical types, e.g., fp16:
  // tempalte<>
  // fp16 CastType(float x) {
  //    ....
  // }
  if (axis == 0) {
    return Sum(M, 0) / (1.0f * M.shape(0));
  } else if (axis == 1) {
    return Sum(M, 1) / (1.0f * M.shape(1));
  } else {
    LOG(FATAL) << "Not currently support Sum over axis = " << axis;
  }
}
// TODO(wangwei) conside async exec
template <>
float Sum<float>(const Tensor &in) {
  float s = 0.0f;
  Tensor one(in.shape(), in.device(), in.data_type());
  one.SetValue(1.0f);
  TYPE_LANG_SWITCH(in.data_type(), DType, in.device()->lang(), Lang, {
    one.device()->Exec(
        // cannot use this sum function in computational graph
        [in, one, &s](Context *ctx) mutable {
          DType ret = DType(0);
          Dot<DType, Lang>(in, one, &ret, ctx);
          s = ret;
        },
        {in.block(), one.block()}, {}, "Sum");
  });
  return s;
}

Tensor Sum(const Tensor &M, int axis) {
  if (axis == 0) {
    Tensor out(Shape{M.shape(1)}, M.device(), M.data_type());
    SumRows(M, &out);
    return out;
  } else {
    CHECK_EQ(axis, 1) << "Not support Sum over axis = " << axis;
    Tensor out = Tensor(Shape{M.shape(0)}, M.device(), M.data_type());
    SumColumns(M, &out);
    return out;
  }
}

Tensor SumAll(const Tensor &in) {
  Tensor out({(size_t)1}, in.device(), in.data_type());
  Tensor one(in.shape(), in.device(), in.data_type());
  one.SetValue(1.0f);
  TYPE_LANG_SWITCH(in.data_type(), DType, in.device()->lang(), Lang, {
    one.device()->Exec(
        [in, one, out](Context *ctx) mutable {
          Dot<DType, Lang>(in, one, &out, ctx);
        },
        {in.block(), one.block()}, {out.block()}, "SumAll");
  });
  return out;
}

Tensor RowMax(const Tensor &in) {
  Tensor ret({in.shape(0)}, in.device(), in.data_type());
  TYPE_LANG_SWITCH(in.data_type(), DType, in.device()->lang(), Lang, {
    in.device()->Exec(
        [in, ret](Context *ctx) mutable {
          // size_t nrow = 1;
          // if (in.nDim() > 1) nrow = in.shape(0);
          // size_t ncol = in.Size() / nrow;
          RowMax<DType, Lang>(in, &ret, ctx);
        },
        {in.block()}, {ret.block()}, "RowMax");
  });
  return ret;
}

void AddColumn(const Tensor &v, Tensor *M) { AddColumn(1, 1, v, M); }
/// Add column 'v' onto each column of matrix M;
template <typename SType>
void AddColumn(const SType alpha, const SType beta, const Tensor &v,
               Tensor *M) {
  if (M->transpose()) {
    Tensor X(Transpose(*M));
    AddRow(v, &X);
  } else {
    CHECK_EQ(M->nDim(), 2u);
    // CHECK_EQ(v.nDim(), 1u); (chonho) shape of v is 2-element tuple
    size_t nb_row = M->shape(0), nb_col = M->shape(1);
    CHECK_EQ(nb_row, v.Size());

    Tensor one(Shape{1, nb_col}, M->device(), M->data_type());
    one.SetValue(1.0f);  // TODO(wangwei) cast type
    Tensor vmat(Reshape(v, Shape{nb_row, 1}));
    Mult(alpha, vmat, one, beta, M);
  }
}
template void AddColumn(const float alpha, const float beta, const Tensor &v,
                        Tensor *M);

void AddRow(const Tensor &v, Tensor *M) { AddRow(1, 1, v, M); }

/// Add row 'v' by each column of matrix M; write results into 'out'
template <typename SType>
void AddRow(const SType alpha, const SType beta, const Tensor &v, Tensor *M) {
  if (M->transpose()) {
    Tensor X(Transpose(*M));
    AddColumn(v, &X);
  } else {
    CHECK_EQ(M->nDim(), 2u);
    // CHECK_EQ(v.nDim(), 1u); (chonho) shape of v is 2-element tuple
    size_t nb_row = M->shape(0), nb_col = M->shape(1);
    CHECK_EQ(nb_col, v.Size());

    Tensor one(Shape{nb_row, 1}, M->device(), M->data_type());
    one.SetValue(1.0f);
    Tensor vmat(Reshape(v, Shape{1, nb_col}));
    Mult(alpha, one, vmat, beta, M);
  }
}
template void AddRow(const float alpha, const float beta, const Tensor &v,
                     Tensor *M);

/// Divide column 'v' by each column of matrix M; write results into 'out'
void DivColumn(const Tensor &v, Tensor *M) {
  Tensor inv;
  TYPE_SWITCH(v.data_type(), DType, { inv = Div(DType(1), v); });
  MultColumn(inv, M);
}

Tensor ConcatOn(const std::vector<Tensor> &in, int axis) {
  vector<Tensor> tmp;
  Shape out_shape = in[0].shape();
  size_t dim = in[0].shape().size();
  // CHECK_GE(dim, 2u) << " Only work for tensor of dim >=2 ";
  size_t size = in[0].Size() / in[0].shape(axis);
  size_t new_size = 0u;
  for (const auto &t : in) {
    CHECK_EQ(dim, t.shape().size()) << "All tensors should have the same dim";
    CHECK_EQ(size, t.Size() / t.shape(axis))
        << "The size of all axis should "
        << " be the same except the concatenated axis";
    new_size += t.shape(axis);
  }
  out_shape[axis] = new_size;
  if (axis == 0) {
    size_t nrow = 0;
    for (const auto &t : in) {
      nrow += t.shape(0);
      tmp.push_back(Reshape(t, {t.shape(0), t.Size() / t.shape(0)}));
    }
    auto ret = ConcatenateRows(tmp);
    ret.Reshape(out_shape);
    return ret;
  } else {
    for (const auto &t : in) {
      size_t nrow = 1;
      for (int i = 0; i < axis; i++) nrow *= t.shape(i);
      tmp.push_back(Reshape(t, {nrow, t.Size() / nrow}));
    }
    auto ret = ConcatenateColumns(tmp);
    ret.Reshape(out_shape);
    return ret;
  }
}

Tensor ConcatenateRows(const vector<Tensor> &in) {
  size_t nrow = 0, ncol = 0;
  CHECK(in.size());
  for (const auto &x : in) {
    CHECK(!x.transpose());
    CHECK_EQ(x.nDim(), 2u);
    nrow += x.shape(0);
    if (ncol == 0)
      ncol = x.shape(1);
    else
      CHECK_EQ(ncol, x.shape(1));
  }
  Tensor out(Shape{nrow, ncol}, in.at(0).device(), in.at(0).data_type());
  size_t dst_offset = 0;
  for (const auto &x : in) {
    CopyDataToFrom(&out, x, x.Size(), dst_offset, 0);
    dst_offset += x.Size();
  }
  return out;
}
Tensor ConcatRows(const vector<Tensor> &in) { return ConcatenateRows(in); }
// TODO(wangwei) add a copypatch function for improve the efficiency on GPU.
Tensor ConcatenateColumns(const vector<Tensor> &in) {
  size_t nrow = 0, ncol = 0;
  CHECK(in.size());
  for (const auto &x : in) {
    CHECK(!x.transpose());
    CHECK_EQ(x.nDim(), 2u);
    ncol += x.shape(1);
    if (nrow == 0)
      nrow = x.shape(0);
    else
      CHECK_EQ(nrow, x.shape(0));
  }
  Tensor out(Shape{nrow, ncol}, in.at(0).device(), in.at(0).data_type());
  for (size_t row = 0; row < nrow; row++) {
    size_t dst_offset = row * ncol;
    for (const auto &x : in) {
      size_t src_offset = row * x.shape(1);
      CopyDataToFrom(&out, x, x.shape(1), dst_offset, src_offset);
      dst_offset += x.shape(1);
    }
    CHECK_EQ(dst_offset, row * ncol + ncol);
  }
  return out;
}
Tensor ConcatColumns(const vector<Tensor> &in) {
  return ConcatenateColumns(in);
}

Tensor CopyRows(const Tensor &in, const size_t start, const size_t end) {
  CHECK_LT(start, end);
  CHECK_GE(in.shape(0), end) << "Tensor size must >= end";
  Shape s = in.shape();
  s[0] = end - start;
  size_t sample_size = in.Size() / in.shape(0);
  Tensor out(s, in.device(), in.data_type());
  CopyDataToFrom(&out, in, out.Size(), 0, start * sample_size);
  return out;
}

Tensor SliceOn(const Tensor &in, const size_t start, const size_t end,
               int axis) {
  Shape out_shape = in.shape();
  out_shape[axis] = end - start;
  if (axis == 0) {
    auto ret = SliceRows(Reshape(in, {in.shape(0), in.Size() / in.shape(0)}),
                         start, end);
    ret.Reshape(out_shape);
    return ret;
  } else {
    size_t nrow = 1;
    for (int i = 0; i < axis; i++) nrow *= in.shape(i);
    auto suffix = in.Size() / nrow / in.shape(axis);
    auto ret = SliceColumns(Reshape(in, {nrow, in.Size() / nrow}),
                            start * suffix, end * suffix);
    ret.Reshape(out_shape);
    return ret;
  }
}

Tensor SliceRows(const Tensor &in, const size_t start, const size_t end) {
  return CopyRows(in, start, end);
}

Tensor CopyColumns(const Tensor &in, const size_t start, const size_t end) {
  CHECK_EQ(in.nDim(), 2u);
  CHECK_LT(start, end);
  CHECK_GE(in.shape(1), end);
  Shape s{in.shape(0), end - start};
  Tensor out(s, in.device(), in.data_type());
  for (size_t row = 0; row < out.shape(0); row++) {
    size_t src_offset = row * in.shape(1) + start;
    size_t dst_offset = row * out.shape(1);
    CopyDataToFrom(&out, in, end - start, dst_offset, src_offset);
  }
  return out;
}

Tensor SliceColumns(const Tensor &in, const size_t start, const size_t end) {
  return CopyColumns(in, start, end);
}

/// Divide row 'v' by each row of matrix M; write results into 'out'
void DivRow(const Tensor &v, Tensor *M) {
  Tensor inv;
  TYPE_SWITCH(v.data_type(), DType, { inv = Div(DType(1), v); });
  MultRow(inv, M);
}

/// Multiply column 'v' and each column of matrix M; write results into 'out'
void MultColumn(const Tensor &v, Tensor *M) {
  // CHECK(!M->transpose()) << "Not supported yet";
  CHECK_EQ(M->nDim(), 2u);
  // CHECK_EQ(v.nDim(), 1u); (chonho) shape of v is 2-element tuple
  CHECK_EQ(v.Size(), M->shape(0));
  CheckDataTypeAndLang(*M, v);
  TYPE_LANG_SWITCH(v.data_type(), DType, v.device()->lang(), Lang, {
    Tensor &MRef = *M;
    v.device()->Exec(
        [MRef, v](Context *ctx) mutable {
          DGMM<DType, Lang>(false, MRef, v, &MRef, ctx);
        },
        {M->block(), v.block()}, {M->block()}, "MultColumn");
  });
}

/// Multiply row 'v' with each row of matrix M; write results into 'out'
void MultRow(const Tensor &v, Tensor *M) {
  // CHECK(!M->transpose()) << "Not supported yet";
  CHECK_EQ(M->nDim(), 2u);
  // CHECK_EQ(v.nDim(), 1u); (chonho) shape of v is 2-element tuple
  CHECK_EQ(v.Size(), M->shape(1));
  CheckDataTypeAndLang(*M, v);
  TYPE_LANG_SWITCH(v.data_type(), DType, v.device()->lang(), Lang, {
    Tensor &MRef = *M;
    v.device()->Exec(
        [MRef, v](Context *ctx) mutable {
          DGMM<DType, Lang>(true, MRef, v, &MRef, ctx);
        },
        {M->block(), v.block()}, {M->block()}, "MultRow");
  });
}

void SubColumn(const Tensor &v, Tensor *M) { AddColumn(-1, 1, v, M); }

void SubRow(const Tensor &v, Tensor *M) { AddRow(-1, 1, v, M); }

void SumColumns(const Tensor &M, Tensor *v) {
  if (M.transpose()) {
    Tensor X = Transpose(M);
    SumRows(X, v);
  } else {
    CHECK_EQ(M.nDim(), 2u);
    // CHECK_EQ(v->nDim(), 1u); (chonho) shape of v is 2-element tuple
    size_t nb_row = M.shape().at(0), nb_col = M.shape().at(1);
    CHECK_EQ(nb_row, v->Size());

    Tensor one(Shape{nb_col}, M.device(), M.data_type());
    one.SetValue(1.0f);  // TODO(wangwei) cast type
    Mult(M, one, v);
  }
}
void SumRows(const Tensor &M, Tensor *v) {
  if (M.transpose()) {
    Tensor X = Transpose(M);
    SumColumns(X, v);
  } else {
    CHECK_EQ(M.nDim(), 2u);
    // CHECK_EQ(v->nDim(), 1u); (chonho) shape of v is 2-element tuple
    size_t nb_row = M.shape(0), nb_col = M.shape(1);
    CHECK_EQ(nb_col, v->Size());

    Tensor one(Shape{nb_row}, M.device(), M.data_type());
    one.SetValue(1.0f);  // TODO(wangwei) cast type
    Tensor X = Transpose(M);
    Mult(X, one, v);
  }
}
// ====================Random operations=====================================
template <typename SType>
void Bernoulli(const SType p, Tensor *out) {
  TYPE_LANG_SWITCH(out->data_type(), DType, out->device()->lang(), Lang, {
    auto prob = TypeCast<SType, DType>(p);
    Tensor &outRef = *out;
    out->device()->Exec(
        [prob, outRef](Context *ctx) mutable {
          Bernoulli<DType, Lang>(prob, &outRef, ctx);
        },
        {}, {out->block()}, "Bernoulli", true);
  });
}

template void Bernoulli<float>(const float p, Tensor *out);

template <typename SType>
void Uniform(const SType low, const SType high, Tensor *out) {
  TYPE_LANG_SWITCH(out->data_type(), DType, out->device()->lang(), Lang, {
    auto l = TypeCast<SType, DType>(low);
    auto h = TypeCast<SType, DType>(high);
    Tensor &outRef = *out;
    out->device()->Exec(
        [l, h, outRef](Context *ctx) mutable {
          Uniform<DType, Lang>(l, h, &outRef, ctx);
        },
        {}, {out->block()}, "Uniform", true);
  });
}

template void Uniform<float>(const float low, const float high, Tensor *out);

template <typename SType>
void Gaussian(const SType mean, const SType std, Tensor *out) {
  TYPE_LANG_SWITCH(out->data_type(), DType, out->device()->lang(), Lang, {
    auto m = TypeCast<SType, DType>(mean);
    auto s = TypeCast<SType, DType>(std);
    Tensor &outRef = *out;
    out->device()->Exec(
        [m, s, outRef](Context *ctx) mutable {
          Gaussian<DType, Lang>(m, s, &outRef, ctx);
        },
        {}, {out->block()}, "Gaussian", true);
  });
}
template void Gaussian<float>(const float mean, const float std, Tensor *out);

// ================Blas operations============================================

template <typename SType>
void Axpy(const SType alpha, const Tensor &in, Tensor *out) {
  TYPE_LANG_SWITCH(in.data_type(), DType, in.device()->lang(), Lang, {
    auto a = TypeCast<SType, DType>(alpha);
    Tensor &outRef = *out;
    Tensor fake(*out);
    out->device()->Exec(
        [a, in, outRef, fake](Context *ctx) mutable {
          Axpy<DType, Lang>(a, in, &outRef, ctx);
        },
        {in.block(), out->block()}, {out->block()}, "Axpy");
  });
}

template void Axpy<float>(const float alpha, const Tensor &in, Tensor *out);

void Axpy(const Tensor &alpha, const Tensor &in, Tensor *out) {
  TYPE_SWITCH(alpha.data_type(), SType, {
    TYPE_LANG_SWITCH(in.data_type(), DType, in.device()->lang(), Lang, {
      Tensor fake(*out);
      Tensor &outRef = *out;
      out->device()->Exec(
          [alpha, in, outRef, fake](Context *ctx) mutable {
            Tensor alphaHost = alpha.Clone(defaultDevice);
            // synchronize the stream to wait for the data transfer to complete
            alpha.device()->Sync();
            const SType value =
                static_cast<const SType *>(alphaHost.block()->data())[0];
            auto a = TypeCast<SType, DType>(value);
            Axpy<DType, Lang>(a, in, &outRef, ctx);
          },
          {alpha.block(), in.block(), out->block()}, {out->block()}, "Axpy");
    });
  });
}

Tensor Mult(const Tensor &A, const Tensor &B) {
  auto A_ = Broadcast(A, B.shape(), 2);
  auto B_ = Broadcast(B, A.shape(), 2);

  Shape s = A_.shape();
  s.pop_back();
  s.push_back(B.shape(B.nDim() - 1));

  Tensor out(s, A.device(), A.data_type());
  Mult(A_, B_, &out);
  return out;
}

void Mult(const Tensor &A, const Tensor &B, Tensor *out) {
  Mult(1.0f, A, B, 0.0f, out);
}

template <typename SType>
void Mult(const SType alpha, const Tensor &A, const Tensor &B, const SType beta,
          Tensor *C) {
  Tensor fakeC;
  vector<Block *> read_blocks = {A.block(), B.block()};
  if (beta) {
    fakeC = *C;
    read_blocks.push_back(C->block());
  }
  if (B.nDim() == 1u) {
    CHECK_EQ(A.shape().size(), 2u);
    TYPE_LANG_SWITCH(A.data_type(), DType, A.device()->lang(), Lang, {
      auto a = TypeCast<SType, DType>(alpha);
      auto b = TypeCast<SType, DType>(beta);
      Tensor &CRef = *C;
      C->device()->Exec(
          [a, A, b, B, CRef, fakeC](Context *ctx) mutable {
            GEMV<DType, Lang>(a, A, B, b, &CRef, ctx);
          },
          read_blocks, {C->block()}, "GEMV");
    });
  } else if (B.nDim() == 2u) {
    CHECK_EQ(A.shape().size(), 2u);
    CHECK(!C->transpose());
    TYPE_LANG_SWITCH(A.data_type(), DType, A.device()->lang(), Lang, {
      auto a = TypeCast<SType, DType>(alpha);
      auto b = TypeCast<SType, DType>(beta);
      Tensor &CRef = *C;
      C->device()->Exec(
          [a, A, b, B, CRef, fakeC](Context *ctx) mutable {
            GEMM<DType, Lang>(a, A, B, b, &CRef, ctx);
          },
          read_blocks, {C->block()}, "GEMM");
    });
  } else if (B.nDim() == 3u || B.nDim() == 4u) {
    CHECK_EQ(A.shape().size(), B.shape().size());
    CHECK(!C->transpose());
    TYPE_LANG_SWITCH(A.data_type(), DType, A.device()->lang(), Lang, {
      auto a = TypeCast<SType, DType>(alpha);
      auto b = TypeCast<SType, DType>(beta);

      Tensor A_tmp;
      Tensor B_tmp;

      if (A.transpose() || A.broadcasted()) {
        A_tmp = Tensor(A.shape(), A.device(), A.data_type());
        singa::Transform(A, &A_tmp);
      } else {
        A_tmp = A;
      }

      if (B.transpose() || B.broadcasted()) {
        B_tmp = Tensor(B.shape(), B.device(), B.data_type());
        singa::Transform(B, &B_tmp);
      } else {
        B_tmp = B;
      }

      // batch GEMM should have same batch size
      CHECK_EQ(A_tmp.shape(0), B_tmp.shape(0));
      if (B.nDim() == 4u) CHECK_EQ(A_tmp.shape(1), B_tmp.shape(1));

      Tensor &CRef = *C;
      C->device()->Exec(
          [a, A_tmp, b, B_tmp, CRef, fakeC](Context *ctx) mutable {
            GEMMBatched<DType, Lang>(a, A_tmp, B_tmp, b, &CRef, ctx);
          },
          read_blocks, {C->block()}, "GEMMBatched");
    });
  } else {
    LOG(FATAL) << "Un-supported tensor dimentions " << A.nDim() << "d matmul "
               << B.nDim() << "d\n";
  }
}

// ************************
// Misc.
// ************************
Tensor CrossEntropyFwd(const Tensor &p, const Tensor &t) {
  Tensor loss({p.shape(0)}, p.device(), p.data_type());
  ComputeCrossEntropy(p, t, &loss);
  return loss;
}

Tensor SoftmaxCrossEntropyBwd(const Tensor &p, const Tensor &t) {
  Tensor g = p.Clone();
  SoftmaxCrossEntropyBwd(t, &g);
  return g;
}

void ComputeCrossEntropy(const Tensor &p, const Tensor &t, Tensor *loss) {
  CHECK_LE(p.nDim(), 2u);
  CHECK_LE(t.nDim(), 2u);
  size_t batchsize = 1;
  if (p.nDim() == 2u) batchsize = p.shape(0);
  size_t dim = p.Size() / batchsize;
  TYPE_LANG_SWITCH(p.data_type(), DType, p.device()->lang(), Lang, {
    Tensor &lossRef = *loss;
    p.device()->Exec(
        [batchsize, dim, t, p, lossRef](Context *ctx) mutable {
          bool int_target = t.Size() == batchsize;
          ComputeCrossEntropy<DType, Lang>(int_target, batchsize, dim,
                                           p.block(), t.block(),
                                           lossRef.block(), ctx);
        },
        {p.block(), t.block()}, {loss->block()}, "ComputeCrossEntropy");
  });
}

void SoftmaxCrossEntropyBwd(const Tensor &t, Tensor *p) {
  CHECK_LE(p->nDim(), 2u);
  CHECK_LE(t.nDim(), 2u);
  size_t batchsize = 1;
  if (p->nDim() == 2u) batchsize = p->shape(0);
  size_t dim = p->Size() / batchsize;
  TYPE_LANG_SWITCH(p->data_type(), DType, p->device()->lang(), Lang, {
    Tensor &pRef = *p;
    Tensor pFake(*p);  // just add a ref count
    p->device()->Exec(
        [batchsize, dim, t, pRef, pFake](Context *ctx) mutable {
          bool int_target = t.Size() == batchsize;
          SoftmaxCrossEntropyBwd<DType, Lang>(int_target, batchsize, dim,
                                              pRef.block(), t.block(),
                                              pRef.block(), ctx);
        },
        {p->block(), t.block()}, {p->block()}, "SoftmaxCrossEntropyBackward");
  });
}

Tensor &Tensor::Contiguous() {
  if (transpose()) {
    Tensor t(shape_, device_, data_type_);
    singa::Transform(*this, &t);
    std::swap(t.block_, block_);
  }
  return *this;
}

Tensor Contiguous(const Tensor &in) {
  Tensor out(in);
  return out.Contiguous();
}

// if tensor is not transposed yet, we change the shape and generate new stride
// if tensor is already transposed, we reallocate the memory and generate stride
Tensor &Tensor::Reshape(const Shape &shape) {
  // Check original volumn with the new one
  // do not use Product(shape_) due to stride 0 from broadcasting.
  // printf("reshape loc b\n");
  CHECK_EQ(Product(shape), Size());
  if (transpose()) {
    Tensor t(shape_, device_, data_type_);
    singa::Transform(*this, &t);
    std::swap(t.block_, block_);
    shape_ = shape;
  } else {
    shape_ = shape;
  }
  generate_stride();
  // printf("reshape loc c\n");
  return *this;
}

Tensor Reshape(const Tensor &in, const Shape &s) {
  // printf("reshape loc a\n");
  Tensor out(in);
  return out.Reshape(s);
}

}  // namespace singa
