1/*******************************************************************************
2* Copyright 2020 Intel Corporation
3*
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at
7*
8* http://www.apache.org/licenses/LICENSE-2.0
9*
10* Unless required by applicable law or agreed to in writing, software
11* distributed under the License is distributed on an "AS IS" BASIS,
12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13* See the License for the specific language governing permissions and
14* limitations under the License.
15*******************************************************************************/
16
17#include "dnnl_test_common.hpp"
18#include "gtest/gtest.h"
19
20#include "src/common/bfloat16.hpp"
21
22namespace {
23
24template <typename IntegerType>
25void assert_same_bits_converted_from_integer_as_from_float(
26 const IntegerType value) {
27 const bfloat16_t constructed_from_float {static_cast<float>(value)};
28 const bfloat16_t constructed_from_integer {value};
29 ASSERT_EQ(constructed_from_integer.raw_bits_,
30 constructed_from_float.raw_bits_);
31}
32
33template <typename IntegerType>
34void assert_same_bits_assigned_from_integer_as_from_float(
35 const IntegerType value) {
36 bfloat16_t assigned_from_float;
37 assigned_from_float = static_cast<float>(value);
38 bfloat16_t assigned_from_integer;
39 assigned_from_integer = value;
40 ASSERT_EQ(assigned_from_integer.raw_bits_, assigned_from_float.raw_bits_);
41}
42
43template <typename IntegerType>
44void assert_same_bits_from_integer_as_from_float(const IntegerType value) {
45 assert_same_bits_converted_from_integer_as_from_float(value);
46 assert_same_bits_assigned_from_integer_as_from_float(value);
47}
48
49template <typename IntegerType>
50void assert_same_bits_from_nonnegative_integer_as_from_float() {
51 assert_same_bits_from_integer_as_from_float<IntegerType>(0);
52 assert_same_bits_from_integer_as_from_float<IntegerType>(1);
53 constexpr auto max_value = std::numeric_limits<IntegerType>::max();
54 assert_same_bits_from_integer_as_from_float(max_value - 1);
55 assert_same_bits_from_integer_as_from_float(max_value);
56}
57
58template <typename SignedType>
59void assert_same_bits_from_integer_as_from_float() {
60 constexpr auto min_value = std::numeric_limits<SignedType>::min();
61 assert_same_bits_from_integer_as_from_float(min_value);
62 assert_same_bits_from_integer_as_from_float(min_value + 1);
63 assert_same_bits_from_integer_as_from_float<SignedType>(-1);
64
65 assert_same_bits_from_nonnegative_integer_as_from_float<SignedType>();
66 using UnsignedType = typename std::make_unsigned<SignedType>::type;
67 assert_same_bits_from_nonnegative_integer_as_from_float<UnsignedType>();
68}
69
70} // namespace
71
72namespace dnnl {
73
74TEST(test_bfloat16_plus_float, TestDenormF32) {
75 const float denorm_f32 {FLT_MIN / 2.0f};
76 const bfloat16_t initial_value_bf16 {FLT_MIN};
77
78 bfloat16_t expect_bf16 {float {initial_value_bf16} + denorm_f32};
79 ASSERT_GT(float {expect_bf16}, float {initial_value_bf16});
80
81 bfloat16_t bf16_plus_equal_f32 = initial_value_bf16;
82 bf16_plus_equal_f32 += denorm_f32;
83 ASSERT_EQ(float {bf16_plus_equal_f32}, float {expect_bf16});
84
85 bfloat16_t bf16_plus_f32 = initial_value_bf16 + denorm_f32;
86 ASSERT_EQ(float {bf16_plus_f32}, float {expect_bf16});
87}
88
89TEST(test_bfloat16_denorm_f32, BitsFromDoubleSameAsFromFloat) {
90 // Test that the bits of a bfloat16 produced by passing 'denorm_f32' as a
91 // 'double' are the same as when passing 'denorm_f32' as 'float'.
92 //
93 // This test aims to check that when converting a 'double' value to
94 // 'bfloat16_t', or when assigning a 'double' to a bfloat16, this value is
95 // _not_ treated as an integer value! ('bfloat16_t' has optimized member
96 // function templates for conversion and assignment, specifically from
97 // integer types.)
98 constexpr float denorm_f32 {FLT_MIN / 2.0f};
99 const auto expected_bits = bfloat16_t {denorm_f32}.raw_bits_;
100
101 // Test converting 'double' to bfloat16:
102 EXPECT_EQ(bfloat16_t {double {denorm_f32}}.raw_bits_, expected_bits);
103
104 bfloat16_t bf16;
105 // Test assignment of 'double' to bfloat16:
106 bf16 = double {denorm_f32};
107
108 EXPECT_EQ(bf16.raw_bits_, expected_bits);
109}
110
111TEST(test_bfloat16_converting_constructor_and_assignment,
112 BitsFromIntegerSameAsFromFloat) {
113 assert_same_bits_from_integer_as_from_float<signed char>();
114 assert_same_bits_from_integer_as_from_float<short>();
115 assert_same_bits_from_integer_as_from_float<int>();
116 assert_same_bits_from_integer_as_from_float<long>();
117 assert_same_bits_from_integer_as_from_float<long long>();
118}
119
120} // namespace dnnl
121