Skip to content

Commit

Permalink
Implements log2 and log10 (#1267)
Browse files Browse the repository at this point in the history
* Implements log2 and log10

* Fixed docstrings for log10 and log2
  • Loading branch information
ndgrigorian committed Jul 4, 2023
1 parent 7510d7e commit bc59de9
Show file tree
Hide file tree
Showing 7 changed files with 864 additions and 6 deletions.
4 changes: 4 additions & 0 deletions dpctl/tensor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@
less_equal,
log,
log1p,
log2,
log10,
logical_and,
logical_not,
logical_or,
Expand Down Expand Up @@ -224,6 +226,8 @@
"logical_or",
"logical_xor",
"log1p",
"log2",
"log10",
"negative",
"positive",
"proj",
Expand Down
50 changes: 48 additions & 2 deletions dpctl/tensor/_elementwise_funcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -563,10 +563,56 @@
)

# U22: ==== LOG2 (x)
# FIXME: implement U22
_log2_docstring_ = """
log2(x, out=None, order='K')
Computes the base-2 logarithm for each element `x_i` of input array `x`.
Args:
x (usm_ndarray):
Input array, expected to have numeric data type.
out ({None, usm_ndarray}, optional):
Output array to populate.
Array have the correct shape and the expected data type.
order ("C","F","A","K", optional):
Memory layout of the newly output array, if parameter `out` is `None`.
Default: "K".
Returns:
usm_narray:
An array containing the base-2 logarithm of `x`.
The data type of the returned array is determined by the
Type Promotion Rules.
"""

log2 = UnaryElementwiseFunc(
"log2", ti._log2_result_type, ti._log2, _log2_docstring_
)

# U23: ==== LOG10 (x)
# FIXME: implement U23
_log10_docstring_ = """
log10(x, out=None, order='K')
Computes the base-10 logarithm for each element `x_i` of input array `x`.
Args:
x (usm_ndarray):
Input array, expected to have numeric data type.
out ({None, usm_ndarray}, optional):
Output array to populate.
Array have the correct shape and the expected data type.
order ("C","F","A","K", optional):
Memory layout of the newly output array, if parameter `out` is `None`.
Default: "K".
Returns:
usm_narray:
An array containing the base-1- logarithm of `x`.
The data type of the returned array is determined by the
Type Promotion Rules.
"""

log10 = UnaryElementwiseFunc(
"log10", ti._log10_result_type, ti._log10, _log10_docstring_
)

# B15: ==== LOGADDEXP (x1, x2)
# FIXME: implement B15
Expand Down
224 changes: 224 additions & 0 deletions dpctl/tensor/libtensor/include/kernels/elementwise_functions/log10.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
//=== log10.hpp - Unary function LOG10 ------
//*-C++-*--/===//
//
// Data Parallel Control (dpctl)
//
// Copyright 2020-2023 Intel Corporation
//
// 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.
//
//===---------------------------------------------------------------------===//
///
/// \file
/// This file defines kernels for elementwise evaluation of LOG10(x) function.
//===---------------------------------------------------------------------===//

#pragma once
#include <CL/sycl.hpp>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <type_traits>

#include "kernels/elementwise_functions/common.hpp"

#include "utils/offset_utils.hpp"
#include "utils/type_dispatch.hpp"
#include "utils/type_utils.hpp"
#include <pybind11/pybind11.h>

namespace dpctl
{
namespace tensor
{
namespace kernels
{
namespace log10
{

namespace py = pybind11;
namespace td_ns = dpctl::tensor::type_dispatch;

using dpctl::tensor::type_utils::is_complex;
using dpctl::tensor::type_utils::vec_cast;

template <typename argT, typename resT> struct Log10Functor
{

// is function constant for given argT
using is_constant = typename std::false_type;
// constant value, if constant
// constexpr resT constant_value = resT{};
// is function defined for sycl::vec
using supports_vec = typename std::negation<
std::disjunction<is_complex<resT>, is_complex<argT>>>;
// do both argTy and resTy support sugroup store/load operation
using supports_sg_loadstore = typename std::negation<
std::disjunction<is_complex<resT>, is_complex<argT>>>;

resT operator()(const argT &in)
{
if constexpr (is_complex<argT>::value) {
using realT = typename argT::value_type;
return (std::log(in) / std::log(realT{10}));
}
else {
return std::log10(in);
}
}

template <int vec_sz>
sycl::vec<resT, vec_sz> operator()(const sycl::vec<argT, vec_sz> &in)
{
auto const &res_vec = sycl::log10(in);
using deducedT = typename std::remove_cv_t<
std::remove_reference_t<decltype(res_vec)>>::element_type;
if constexpr (std::is_same_v<resT, deducedT>) {
return res_vec;
}
else {
return vec_cast<resT, deducedT, vec_sz>(res_vec);
}
}
};

template <typename argTy,
typename resTy = argTy,
unsigned int vec_sz = 4,
unsigned int n_vecs = 2>
using Log10ContigFunctor =
elementwise_common::UnaryContigFunctor<argTy,
resTy,
Log10Functor<argTy, resTy>,
vec_sz,
n_vecs>;

template <typename argTy, typename resTy, typename IndexerT>
using Log10StridedFunctor = elementwise_common::
UnaryStridedFunctor<argTy, resTy, IndexerT, Log10Functor<argTy, resTy>>;

template <typename T> struct Log10OutputType
{
using value_type = typename std::disjunction< // disjunction is C++17
// feature, supported by DPC++
td_ns::TypeMapResultEntry<T, sycl::half, sycl::half>,
td_ns::TypeMapResultEntry<T, float, float>,
td_ns::TypeMapResultEntry<T, double, double>,
td_ns::TypeMapResultEntry<T, std::complex<float>, std::complex<float>>,
td_ns::
TypeMapResultEntry<T, std::complex<double>, std::complex<double>>,
td_ns::DefaultResultEntry<void>>::result_type;
};

typedef sycl::event (*log10_contig_impl_fn_ptr_t)(
sycl::queue,
size_t,
const char *,
char *,
const std::vector<sycl::event> &);

template <typename T1, typename T2, unsigned int vec_sz, unsigned int n_vecs>
class log10_contig_kernel;

template <typename argTy>
sycl::event log10_contig_impl(sycl::queue exec_q,
size_t nelems,
const char *arg_p,
char *res_p,
const std::vector<sycl::event> &depends = {})
{
return elementwise_common::unary_contig_impl<
argTy, Log10OutputType, Log10ContigFunctor, log10_contig_kernel>(
exec_q, nelems, arg_p, res_p, depends);
}

template <typename fnT, typename T> struct Log10ContigFactory
{
fnT get()
{
if constexpr (std::is_same_v<typename Log10OutputType<T>::value_type,
void>) {
fnT fn = nullptr;
return fn;
}
else {
fnT fn = log10_contig_impl<T>;
return fn;
}
}
};

template <typename fnT, typename T> struct Log10TypeMapFactory
{
/*! @brief get typeid for output type of std::log10(T x) */
std::enable_if_t<std::is_same<fnT, int>::value, int> get()
{
using rT = typename Log10OutputType<T>::value_type;
;
return td_ns::GetTypeid<rT>{}.get();
}
};

template <typename T1, typename T2, typename T3> class log10_strided_kernel;

typedef sycl::event (*log10_strided_impl_fn_ptr_t)(
sycl::queue,
size_t,
int,
const py::ssize_t *,
const char *,
py::ssize_t,
char *,
py::ssize_t,
const std::vector<sycl::event> &,
const std::vector<sycl::event> &);

template <typename argTy>
sycl::event
log10_strided_impl(sycl::queue exec_q,
size_t nelems,
int nd,
const py::ssize_t *shape_and_strides,
const char *arg_p,
py::ssize_t arg_offset,
char *res_p,
py::ssize_t res_offset,
const std::vector<sycl::event> &depends,
const std::vector<sycl::event> &additional_depends)
{
return elementwise_common::unary_strided_impl<
argTy, Log10OutputType, Log10StridedFunctor, log10_strided_kernel>(
exec_q, nelems, nd, shape_and_strides, arg_p, arg_offset, res_p,
res_offset, depends, additional_depends);
}

template <typename fnT, typename T> struct Log10StridedFactory
{
fnT get()
{
if constexpr (std::is_same_v<typename Log10OutputType<T>::value_type,
void>) {
fnT fn = nullptr;
return fn;
}
else {
fnT fn = log10_strided_impl<T>;
return fn;
}
}
};

} // namespace log10
} // namespace kernels
} // namespace tensor
} // namespace dpctl

0 comments on commit bc59de9

Please sign in to comment.