37 struct is_floating_point
38 : std::integral_constant < bool,
39 std::is_same<float, typename std::remove_cv<T>::type>::value || std::is_same<half_float::half, typename std::remove_cv<T>::type>::value
40 || std::is_same<double, typename std::remove_cv<T>::type>::value || std::is_same<long double, typename std::remove_cv<T>::type>::value >
46 constexpr
float scale1_constant = 1.f;
57 template <
typename T1,
typename T2,
typename T3>
62 const double val =
static_cast<intermediate_type
>(src1) * static_cast<intermediate_type>(src2) *
static_cast<double>(
scale);
64 if(is_floating_point<T3>::value)
66 const auto result =
static_cast<T3
>(val);
72 double rounded_val = 0;
73 switch(rounding_policy)
88 const auto result =
static_cast<T3
>((convert_policy ==
ConvertPolicy::SATURATE) ? saturate_cast<T3>(rounded_val) : rounded_val);
97 const int64_t intermediate_val =
static_cast<int64_t
>(src1) * static_cast<int64_t>(src2);
99 if(std::abs(scale - scale1_constant) < 0.00001f)
110 const auto i32_hi =
static_cast<int64_t
>(std::numeric_limits<int32_t>::max());
112 const auto i32_wi =
static_cast<int64_t
>(1) << 32;
113 int64_t wrapped_rounded_val = intermediate_val - i32_wi *
static_cast<int64_t
>(
support::cpp11::trunc(static_cast<double>(intermediate_val) / i32_wi));
114 if(wrapped_rounded_val <= i32_hi)
116 return static_cast<int32_t
>(wrapped_rounded_val);
121 return static_cast<int32_t
>((wrapped_rounded_val - i32_hi) + i32_lo - 1);
130 int scale_exponent = 0;
131 std::frexp(scale, &scale_exponent);
134 scale_exponent = std::abs(scale_exponent - 1);
135 const double scale_inv =
static_cast<int64_t
>(1) << scale_exponent;
136 const double val = intermediate_val / scale_inv;
138 double rounded_val = 0;
139 switch(rounding_policy)
161 const auto i32_hi =
static_cast<double>(std::numeric_limits<int32_t>::max());
163 const auto i32_wi =
static_cast<double>(
static_cast<int64_t
>(1) << 32);
164 double wrapped_rounded_val = rounded_val - i32_wi * std::floor(rounded_val / i32_wi);
165 if(wrapped_rounded_val <= i32_hi)
167 return static_cast<int32_t
>(wrapped_rounded_val);
172 return static_cast<int32_t
>((wrapped_rounded_val - i32_hi) + i32_lo - 1);
178 template <
size_t dim>
179 struct BroadcastUnroll
181 template <
typename T1,
typename T2,
typename T3>
182 static void unroll(
const SimpleTensor<T1> &src1,
const SimpleTensor<T2> &src2, SimpleTensor<T3> &
dst,
184 Coordinates &id_src1, Coordinates &id_src2, Coordinates &id_dst)
186 const bool src1_is_broadcast = (src1.shape()[dim - 1] != dst.shape()[dim - 1]);
187 const bool src2_is_broadcast = (src2.shape()[dim - 1] != dst.shape()[dim - 1]);
189 id_src1.set(dim - 1, 0);
190 id_src2.set(dim - 1, 0);
191 id_dst.set(dim - 1, 0);
193 for(
size_t i = 0; i < dst.shape()[dim - 1]; ++i, ++id_dst[dim - 1])
195 BroadcastUnroll < dim - 1 >::unroll(src1, src2, dst, scale, convert_policy, rounding_policy, id_src1, id_src2, id_dst);
197 id_src1[dim - 1] += !src1_is_broadcast;
198 id_src2[dim - 1] += !src2_is_broadcast;
204 struct BroadcastUnroll<0>
206 template <
typename T1,
typename T2,
typename T3>
207 static void unroll(
const SimpleTensor<T1> &src1,
const SimpleTensor<T2> &src2, SimpleTensor<T3> &dst,
209 Coordinates &id_src1, Coordinates &id_src2, Coordinates &id_dst)
211 dst[
coord2index(dst.shape(), id_dst)] = mul<T1, T2, T3>(src1[
coord2index(src1.shape(), id_src1)], src2[
coord2index(src2.shape(), id_src2)], scale, convert_policy, rounding_policy);
216 template <
typename T1,
typename T2,
typename T3>
233 BroadcastUnroll<Coordinates::num_max_dimensions>::unroll(src1, src2, dst, scale, convert_policy, rounding_policy, id_src1, id_src2, id_dst);
249 dst = convert_to_asymmetric<uint8_t>(dst_tmp, qout);
261 BroadcastUnroll<Coordinates::num_max_dimensions>::unroll(src1, src2, dst, scale, convert_policy, rounding_policy, id_src1, id_src2, id_dst);
277 dst = convert_to_symmetric<int16_t>(dst_tmp, qout);
289 BroadcastUnroll<Coordinates::num_max_dimensions>::unroll(src1, src2, dst, scale, convert_policy, rounding_policy, id_src1, id_src2, id_dst);
305 dst = convert_to_asymmetric<int8_t>(dst_tmp, qout);
317 BroadcastUnroll<Coordinates::num_max_dimensions>::unroll(src1, src2, dst, scale, convert_policy, rounding_policy, id_src1, id_src2, id_dst);
333 dst = convert_to_symmetric<int16_t>(dst_tmp, qout);
345 BroadcastUnroll<Coordinates::num_max_dimensions>::unroll(src1, src2, dst, scale, convert_policy, rounding_policy, id_src1, id_src2, id_dst);
T trunc(T value)
Truncate floating-point value.
quantized, symmetric fixed-point 16-bit number
Rounds to nearest value; half rounds away from zero.
#define ARM_COMPUTE_ERROR(msg)
Print the given message then throw an std::runtime_error.
SimpleTensor< T3 > pixel_wise_multiplication(const SimpleTensor< T1 > &src1, const SimpleTensor< T2 > &src2, float scale, ConvertPolicy convert_policy, RoundingPolicy rounding_policy, DataType dt_out, const QuantizationInfo &qout)
1 channel, 1 F32 per channel
DataType data_type() const override
Data type of the tensor.
static TensorShape broadcast_shape(const Shapes &... shapes)
If shapes are broadcast compatible, return the broadcasted shape.
SimpleTensor< float > convert_from_asymmetric(const SimpleTensor< uint8_t > &src)
TensorShape shape() const override
Shape of the tensor.
Copyright (c) 2017-2021 Arm Limited.
int coord2index(const TensorShape &shape, const Coordinates &coord)
Linearise the given coordinate.
T round_half_even(T value, T epsilon=std::numeric_limits< T >::epsilon())
Round floating-point value with half value rounding to nearest even.
Quantization information.
#define ARM_COMPUTE_UNUSED(...)
To avoid unused variables warnings.
quantized, asymmetric fixed-point 8-bit number unsigned
RoundingPolicy
Rounding method.
Simple tensor object that stores elements in a consecutive chunk of memory.
Rounds to nearest value; half rounds to nearest even.
T saturate_cast(T val)
Saturate a value of type T against the numeric limits of type U.
quantized, asymmetric fixed-point 8-bit number signed
T round_half_up(T value)
Round floating-point value with half value rounding to positive infinity.
SimpleTensor< T > scale(const SimpleTensor< T > &src, float scale_x, float scale_y, InterpolationPolicy policy, BorderMode border_mode, T constant_border_value, SamplingPolicy sampling_policy, bool ceil_policy_scale, bool align_corners)
DataType
Available data types.
Truncates the least significant values that are lost in operations.
ConvertPolicy
Policy to handle overflow.