1use std::fmt;
4
5use crate::closed_form::{
6 Body, Bound, ClosedForm, Edge, Excitation, Fold, ModalBank, Mode, Part, Rational, Series,
7 Unary, Var,
8};
9use crate::complex::{C64, canonical};
10use crate::lanes::Lanes;
11use crate::spectral_sum::atom::{Singular, SpectralAtom};
12use crate::spectral_sum::{Lane, SpectralSum};
13use crate::table::TABLE_VERSION;
14
15#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
18pub struct Hash(pub u64, pub u64);
19
20impl fmt::Display for Hash {
21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22 write!(f, "{:016x}{:016x}", self.0, self.1)
23 }
24}
25
26pub fn hash_spectral_sum(n: &SpectralSum) -> Hash {
27 hash_spectral_sum_under(n, TABLE_VERSION)
28}
29
30pub fn hash_closed_form(t: &ClosedForm) -> Hash {
31 hash_closed_form_under(t, TABLE_VERSION)
32}
33
34pub fn hash_spectral_sum_under(n: &SpectralSum, table_version: u64) -> Hash {
37 let mut s = Sink::new(0x01, table_version);
38 s.var(n.var);
39 s.u64(n.lanes.len() as u64);
40 for lane in &n.lanes {
41 s.lane(lane);
42 }
43 s.finish()
44}
45
46pub fn hash_closed_form_under(t: &ClosedForm, table_version: u64) -> Hash {
47 let mut s = Sink::new(0x02, table_version);
48 s.var(t.var);
49 s.formula(&t.body);
50 s.finish()
51}
52
53pub fn draw(seed: u64, key: f64) -> f64 {
55 keyed(&format!("{key}"), seed) as f64 / u64::MAX as f64
56}
57
58pub fn keyed(key: &str, seed: u64) -> u64 {
60 let mut s = Sink::new(0x03, TABLE_VERSION);
61 s.bytes(key.as_bytes());
62 s.u64(seed);
63 s.finish().0
64}
65
66struct Sink(Lanes<0>);
67
68impl Sink {
69 fn new(tag: u8, table_version: u64) -> Sink {
70 let mut s = Sink(Lanes::default());
71 s.byte(tag);
72 s.u64(table_version);
73 s
74 }
75
76 fn byte(&mut self, b: u8) {
77 self.0.word(u64::from(b));
78 }
79
80 fn bytes(&mut self, b: &[u8]) {
82 self.u64(b.len() as u64);
83 for &x in b {
84 self.byte(x);
85 }
86 }
87
88 fn u64(&mut self, v: u64) {
89 for b in v.to_le_bytes() {
90 self.byte(b);
91 }
92 }
93
94 fn i64(&mut self, v: i64) {
95 self.u64(v as u64);
96 }
97
98 fn f64(&mut self, v: f64) {
99 self.u64(canonical(v));
100 }
101
102 fn c64(&mut self, v: C64) {
103 let (re, im) = v.bits();
104 self.u64(re);
105 self.u64(im);
106 }
107
108 fn var(&mut self, v: Var) {
109 self.byte(match v {
110 Var::T => 0,
111 Var::F => 1,
112 });
113 }
114
115 fn edge(&mut self, e: Edge) {
116 match e {
117 Edge::NegInf => self.byte(0),
118 Edge::At(bits) => {
119 self.byte(1);
120 self.u64(bits);
121 }
122 Edge::PosInf => self.byte(2),
123 }
124 }
125
126 fn lane(&mut self, lane: &Lane) {
127 self.u64(lane.atoms.len() as u64);
128 for a in &lane.atoms {
129 self.atom(a);
130 }
131 self.u64(lane.series.len() as u64);
132 for s in &lane.series {
133 self.series(s);
134 }
135 self.u64(lane.modal.len() as u64);
136 for m in &lane.modal {
137 self.modal(m);
138 }
139 }
140
141 fn atom(&mut self, a: &SpectralAtom) {
143 self.c64(a.c);
144 self.u64(u64::from(a.poly));
145 match a.exp {
146 None => self.byte(0),
147 Some(e) => {
148 self.byte(1);
149 self.f64(e.sigma);
150 self.f64(e.omega);
151 }
152 }
153 match a.gauss {
154 None => self.byte(0),
155 Some(g) => {
156 self.byte(1);
157 self.f64(g.a);
158 self.f64(g.mu);
159 }
160 }
161 match a.ind {
162 None => self.byte(0),
163 Some(i) => {
164 self.byte(1);
165 self.edge(i.l);
166 self.edge(i.r);
167 }
168 }
169 match a.pole {
170 None => self.byte(0),
171 Some(p) => {
172 self.byte(1);
173 self.c64(p.at);
174 self.u64(u64::from(p.order));
175 self.byte(u8::from(p.pv));
176 }
177 }
178 match a.sing {
179 Singular::Regular => self.byte(0),
180 Singular::Delta { at, order } => {
181 self.byte(1);
182 self.f64(at);
183 self.u64(u64::from(order));
184 }
185 }
186 }
187
188 fn series(&mut self, s: &Series) {
189 self.u64(u64::from(s.index.0));
190 self.i64(s.lo);
191 match s.hi {
192 Bound::Finite(n) => {
193 self.byte(0);
194 self.i64(n);
195 }
196 Bound::Infinite => self.byte(1),
197 }
198 self.formula(&s.term.body);
199 }
200
201 fn modal(&mut self, m: &ModalBank) {
202 self.u64(m.modes.len() as u64);
203 for Mode {
204 omega,
205 tau,
206 amp,
207 phase,
208 } in &m.modes
209 {
210 self.f64(*omega);
211 self.f64(*tau);
212 self.f64(*amp);
213 self.f64(*phase);
214 }
215 match m.excite {
216 Excitation::HammerPulse { f0, t0, contact } => {
217 self.byte(0);
218 self.f64(f0);
219 self.f64(t0);
220 self.f64(contact);
221 }
222 Excitation::Impulse { t0 } => {
223 self.byte(1);
224 self.f64(t0);
225 }
226 }
227 }
228
229 fn parts(&mut self, parts: &[Part]) {
230 self.u64(parts.len() as u64);
231 for p in parts {
232 self.formula(&p.body);
233 }
234 }
235
236 fn rational(&mut self, r: &Rational) {
237 self.u64(r.zeros.len() as u64);
238 for z in &r.zeros {
239 self.c64(*z);
240 }
241 self.u64(r.poles.len() as u64);
242 for p in &r.poles {
243 self.c64(*p);
244 }
245 self.c64(r.gain);
246 }
247
248 fn formula(&mut self, f: &Body) {
249 match f {
250 Body::Const(c) => {
251 self.byte(0x10);
252 self.c64(*c);
253 }
254 Body::Line => self.byte(0x11),
255 Body::Index(i) => {
256 self.byte(0x12);
257 self.u64(u64::from(i.0));
258 }
259 Body::Param(p) => {
260 self.byte(0x13);
261 self.u64(u64::from(p.0));
262 }
263 Body::Node(n) => {
264 self.byte(0x14);
265 self.u64(u64::from(n.0));
266 }
267 Body::Add(parts) => {
268 self.byte(0x15);
269 self.parts(parts);
270 }
271 Body::Mul(parts) => {
272 self.byte(0x16);
273 self.parts(parts);
274 }
275 Body::Div(a, b) => {
276 self.byte(0x17);
277 self.formula(&a.body);
278 self.formula(&b.body);
279 }
280 Body::Pow(base, n) => {
281 self.byte(0x18);
282 self.formula(&base.body);
283 self.i64(i64::from(*n));
284 }
285 Body::Apply(op, arg) => {
286 self.byte(0x19);
287 self.byte(unary_tag(*op));
288 self.formula(&arg.body);
289 }
290 Body::Fold(op, args) => {
291 self.byte(0x1a);
292 self.byte(match op {
293 Fold::Max => 0,
294 Fold::Min => 1,
295 Fold::Mod => 2,
296 });
297 self.parts(args);
298 }
299 Body::Delta { at, order } => {
300 self.byte(0x1b);
301 self.formula(&at.body);
302 self.u64(u64::from(*order));
303 }
304 Body::Pv(at) => {
305 self.byte(0x1c);
306 self.formula(&at.body);
307 }
308 Body::Warp { at, of } => {
309 self.byte(0x27);
310 self.formula(&at.body);
311 self.formula(&of.body);
312 }
313 Body::Shift { by, of } => {
314 self.byte(0x1d);
315 self.f64(*by);
316 self.formula(&of.body);
317 }
318 Body::Deriv { order, of } => {
319 self.byte(0x1e);
320 self.u64(u64::from(*order));
321 self.formula(&of.body);
322 }
323 Body::Crop {
324 of,
325 l,
326 r,
327 rise,
328 fall,
329 } => {
330 self.byte(0x1f);
331 self.formula(&of.body);
332 self.edge(*l);
333 self.edge(*r);
334 self.f64(*rise);
335 self.f64(*fall);
336 }
337 Body::Join(parts) => {
338 self.byte(0x21);
339 self.parts(parts);
340 }
341 Body::Channel(of, k) => {
342 self.byte(0x22);
343 self.formula(&of.body);
344 self.byte(*k);
345 }
346 Body::Rational(r) => {
347 self.byte(0x23);
348 self.rational(r);
349 }
350 Body::Series(s) => {
351 self.byte(0x24);
352 self.series(s);
353 }
354 Body::Modal(m) => {
355 self.byte(0x25);
356 self.modal(m);
357 }
358 Body::Keyed { seed, of } => {
359 self.byte(0x26);
360 self.u64(*seed);
361 self.formula(&of.body);
362 }
363 }
364 }
365
366 fn finish(&self) -> Hash {
368 let Hash(a, b) = self.0.finish();
369 Hash(mix(a), mix(b))
370 }
371}
372
373fn unary_tag(op: Unary) -> u8 {
374 match op {
375 Unary::Sin => 0,
376 Unary::Cos => 1,
377 Unary::Exp => 2,
378 Unary::Tanh => 3,
379 Unary::Sat => 4,
380 Unary::Abs => 5,
381 Unary::Log => 6,
382 Unary::Sqrt => 7,
383 }
384}
385
386fn mix(mut z: u64) -> u64 {
387 z = (z ^ (z >> 30)).wrapping_mul(0xbf58_476d_1ce4_e5b9);
388 z = (z ^ (z >> 27)).wrapping_mul(0x94d0_49bb_1331_11eb);
389 z ^ (z >> 31)
390}