1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//! Closed scalar sets.
//!
//! A scalar set is the closed list of scalar types one tensor value type can
//! carry. tenferro declares its own set once (as
//! [`DefaultScalars`](crate::DefaultScalars)) and gets the value enum, the tag,
//! and the membership query from that single declaration. A crate that needs a
//! different set declares it with [`define_scalar_set!`] in its own crate, and
//! its values implement this trait without touching tenferro's set.
//!
//! The trait and its declaration macro live with the host container they build
//! values from; the promotion facts themselves stay in `tenferro-tensor-core`.
/// A closed set of scalar types carried by one tensor value type.
///
/// A set is represented by one value type: the default set's payload is opaque
/// and a downstream set defines its own value enum, and [`ScalarSet::tag`]
/// reports which member a value currently holds.
///
/// # Examples
///
/// ```rust
/// use tenferro_tensor::{DefaultScalars, ScalarSet};
///
/// let value = DefaultScalars::from_vec_col_major(vec![1], vec![1.0_f64])?;
/// assert_eq!(value.tag(), tenferro_tensor_core::DType::F64);
/// # Ok::<(), tenferro_tensor::Error>(())
/// ```
/// Define a closed scalar set: its tag type, its value enum, and its membership.
///
/// The declaration lists each member once. The macro emits the tag enum, the
/// value enum whose variants hold a
/// host [`TypedTensor`](crate::TypedTensor) (`TypedTensor<T, DynRank, Host>`)
/// of the member type, and the
/// [`ScalarSet`] implementation. A downstream crate invokes this in its own
/// crate, so tenferro never needs to know the set.
///
/// # Examples
///
/// ```rust
/// use tenferro_tensor::{define_scalar_set, DynRank, Host, ScalarSet, TypedTensor};
///
/// define_scalar_set! {
/// /// Tag for a two-member set.
/// pub enum PairTag {
/// /// Double precision.
/// F64 => f64 : Float 1 64,
/// /// Single precision.
/// F32 => f32 : Float 0 32,
/// }
/// /// Value enum for a two-member set.
/// pub enum Pair;
/// }
///
/// let value = Pair::F32(TypedTensor::<f32, DynRank, Host>::from_host_vec_col_major(
/// vec![1],
/// vec![1.0_f32],
/// )?);
/// assert_eq!(value.tag(), PairTag::F32);
/// assert_eq!(<Pair as ScalarSet>::TAGS, &[PairTag::F64, PairTag::F32]);
/// # Ok::<(), tenferro_tensor::Error>(())
/// ```
$*
$set_vis:vis enum $set:ident;
$?
) => ;
}