blob: 24639fbc8c149df370df67c65a3573213b7c61c2 [file] [log] [blame]
dan sinclair08903802022-12-14 18:13:37 +00001// Copyright 2022 The Tint Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
dan sinclaira2e9b492023-07-20 09:21:10 +000015#ifndef SRC_TINT_LANG_BASE_CONSTANT_SCALAR_H_
16#define SRC_TINT_LANG_BASE_CONSTANT_SCALAR_H_
dan sinclair08903802022-12-14 18:13:37 +000017
dan sinclair91b68cd2023-07-20 09:21:10 +000018#include "src/tint/core/castable.h"
19#include "src/tint/core/hash.h"
dan sinclairb14a7782023-07-20 09:21:10 +000020#include "src/tint/lang/base/builtin/number.h"
dan sinclaira2e9b492023-07-20 09:21:10 +000021#include "src/tint/lang/base/constant/manager.h"
22#include "src/tint/lang/base/constant/value.h"
dan sinclair08903802022-12-14 18:13:37 +000023#include "src/tint/type/type.h"
dan sinclair08903802022-12-14 18:13:37 +000024
dan sinclair8626c9e2022-12-14 19:22:19 +000025namespace tint::constant {
dan sinclair08903802022-12-14 18:13:37 +000026
Ben Clayton781f5bb2023-05-31 19:46:33 +000027/// ScalarBase is the base class of all Scalar<T> specializations.
28/// Used for querying whether a value is a scalar type.
29class ScalarBase : public utils::Castable<ScalarBase, Value> {
30 public:
31 ~ScalarBase() override;
32};
33
dan sinclair08903802022-12-14 18:13:37 +000034/// Scalar holds a single scalar or abstract-numeric value.
dan sinclair08903802022-12-14 18:13:37 +000035template <typename T>
Ben Clayton781f5bb2023-05-31 19:46:33 +000036class Scalar : public utils::Castable<Scalar<T>, ScalarBase> {
dan sinclair08903802022-12-14 18:13:37 +000037 public:
38 static_assert(!std::is_same_v<UnwrapNumber<T>, T> || std::is_same_v<T, bool>,
39 "T must be a Number or bool");
40
41 /// Constructor
42 /// @param t the scalar type
43 /// @param v the scalar value
44 Scalar(const type::Type* t, T v) : type(t), value(v) {
45 if constexpr (IsFloatingPoint<T>) {
dan sinclair8626c9e2022-12-14 19:22:19 +000046 TINT_ASSERT(Constant, std::isfinite(v.value));
dan sinclair08903802022-12-14 18:13:37 +000047 }
48 }
49 ~Scalar() override = default;
50
Ben Clayton574b4b12023-03-09 23:22:27 +000051 /// @copydoc Value::Type()
dan sinclair08903802022-12-14 18:13:37 +000052 const type::Type* Type() const override { return type; }
53
Ben Clayton574b4b12023-03-09 23:22:27 +000054 /// @return nullptr, as Scalar does not hold any elements.
55 const Value* Index(size_t) const override { return nullptr; }
dan sinclair08903802022-12-14 18:13:37 +000056
Ben Clayton574b4b12023-03-09 23:22:27 +000057 /// @copydoc Value::NumElements()
58 size_t NumElements() const override { return 1; }
59
60 /// @copydoc Value::AllZero()
dan sinclair08903802022-12-14 18:13:37 +000061 bool AllZero() const override { return IsPositiveZero(); }
Ben Clayton574b4b12023-03-09 23:22:27 +000062
63 /// @copydoc Value::AnyZero()
dan sinclair08903802022-12-14 18:13:37 +000064 bool AnyZero() const override { return IsPositiveZero(); }
Ben Clayton574b4b12023-03-09 23:22:27 +000065
Ben Clayton574b4b12023-03-09 23:22:27 +000066 /// @copydoc Value::Hash()
dan sinclair08903802022-12-14 18:13:37 +000067 size_t Hash() const override { return utils::Hash(type, ValueOf()); }
68
dan sinclair529c3fd2023-01-06 02:57:36 +000069 /// Clones the constant into the provided context
70 /// @param ctx the clone context
71 /// @returns the cloned node
Ben Claytona71bd222023-05-24 23:07:36 +000072 const Scalar* Clone(CloneContext& ctx) const override {
dan sinclair529c3fd2023-01-06 02:57:36 +000073 auto* ty = type->Clone(ctx.type_ctx);
Ben Clayton1e67e532023-05-24 23:07:36 +000074 return ctx.dst.Get<Scalar<T>>(ty, value);
dan sinclair529c3fd2023-01-06 02:57:36 +000075 }
76
dan sinclair08903802022-12-14 18:13:37 +000077 /// @returns `value` if `T` is not a Number, otherwise ValueOf returns the inner value of the
78 /// Number.
79 inline auto ValueOf() const {
80 if constexpr (std::is_same_v<UnwrapNumber<T>, T>) {
81 return value;
82 } else {
83 return value.value;
84 }
85 }
86
87 /// @returns true if `value` is a positive zero.
88 inline bool IsPositiveZero() const {
89 using N = UnwrapNumber<T>;
90 return Number<N>(value) == Number<N>(0); // Considers sign bit
91 }
92
93 /// The scalar type
94 type::Type const* const type;
95 /// The scalar value
96 const T value;
dan sinclairb53b8cf2022-12-15 16:25:31 +000097
98 protected:
Ben Clayton574b4b12023-03-09 23:22:27 +000099 /// @copydoc Value::InternalValue()
dan sinclairb53b8cf2022-12-15 16:25:31 +0000100 std::variant<std::monostate, AInt, AFloat> InternalValue() const override {
101 if constexpr (IsFloatingPoint<UnwrapNumber<T>>) {
102 return static_cast<AFloat>(value);
103 } else {
104 return static_cast<AInt>(value);
105 }
106 }
dan sinclair08903802022-12-14 18:13:37 +0000107};
108
dan sinclair8626c9e2022-12-14 19:22:19 +0000109} // namespace tint::constant
dan sinclair08903802022-12-14 18:13:37 +0000110
dan sinclaira2e9b492023-07-20 09:21:10 +0000111#endif // SRC_TINT_LANG_BASE_CONSTANT_SCALAR_H_