/*
 * STRUMPACK -- STRUctured Matrices PACKage, Copyright (c) 2014, The
 * Regents of the University of California, through Lawrence Berkeley
 * National Laboratory (subject to receipt of any required approvals
 * from the U.S. Dept. of Energy).  All rights reserved.
 *
 * If you have questions about your rights to use or distribute this
 * software, please contact Berkeley Lab's Technology Transfer
 * Department at TTD@lbl.gov.
 *
 * NOTICE. This software is owned by the U.S. Department of Energy. As
 * such, the U.S. Government has been granted for itself and others
 * acting on its behalf a paid-up, nonexclusive, irrevocable,
 * worldwide license in the Software to reproduce, prepare derivative
 * works, and perform publicly and display publicly.  Beginning five
 * (5) years after the date permission to assert copyright is obtained
 * from the U.S. Department of Energy, and subject to any subsequent
 * five (5) year renewals, the U.S. Government is granted for itself
 * and others acting on its behalf a paid-up, nonexclusive,
 * irrevocable, worldwide license in the Software to reproduce,
 * prepare derivative works, distribute copies to the public, perform
 * publicly and display publicly, and to permit others to do so.
 *
 * Developers: Pieter Ghysels, Francois-Henry Rouet, Xiaoye S. Li.
 *             (Lawrence Berkeley National Lab, Computational Research
 *             Division).
 */
#ifndef DISTRIBUTED_VECTOR_HPP
#define DISTRIBUTED_VECTOR_HPP

#include "misc/MPIWrapper.hpp"
#include "BLASLAPACKWrapper.hpp"

namespace strumpack {

  template<typename scalar_t> typename RealType<scalar_t>::value_type
  norm2(std::size_t n, const scalar_t* x, std::size_t incx,
        const MPIComm& comm) {
    STRUMPACK_FLOPS(static_cast<long long int>(n)*2);
    auto vdotv = blas::nrm2(n, x, incx);
    return std::sqrt(MPIComm().all_reduce(vdotv*vdotv, MPI_SUM));
  }

  template<typename scalar_t> typename RealType<scalar_t>::value_type
  norm2(const std::vector<scalar_t>& x, const MPIComm& comm) {
    return norm2<scalar_t>(x.size(), x.data(), 1, comm);
  }

  template<typename scalar_t> scalar_t
  dotc(std::size_t n, const scalar_t* u, std::size_t incu,
       const scalar_t* v, std::size_t incv, const MPIComm& comm) {
    STRUMPACK_FLOPS(static_cast<long long int>(n)*2);
    return comm.all_reduce(blas::dotc(n, u, incu, v, incv), MPI_SUM);
  }

  template<typename scalar_t> scalar_t
  dotc(const std::vector<scalar_t>& u,
       const std::vector<scalar_t>& v, const MPIComm& comm) {
    return dotc(u.size(), u.data(), 1, v.data(), 1, comm);
  }

}

#endif //DISTRIBUTED_VECTOR_HPP
