1use std::fmt;
4
5use crate::closed_form::{
6 Body, Bound, ClosedForm, Edge, Excitation, Fold, IndexId, ModalBank, Mode, Part, Rational,
7 Series, Unary, Var,
8};
9use crate::complex::{C64, canonical};
10use crate::env::NodeId;
11use crate::lanes::Lanes;
12use crate::run::Mirror;
13use crate::spectral_sum::atom::{Singular, SpectralAtom};
14use crate::spectral_sum::{Lane, SpectralSum};
15use crate::table::TABLE_VERSION;
16
17#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
20pub struct Hash(pub u64, pub u64);
21
22impl fmt::Display for Hash {
23 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24 write!(f, "{:016x}{:016x}", self.0, self.1)
25 }
26}
27
28pub fn hash_spectral_sum(n: &SpectralSum) -> Hash {
29 hash_spectral_sum_under(n, TABLE_VERSION)
30}
31
32pub fn hash_closed_form(t: &ClosedForm) -> Hash {
33 hash_closed_form_under(t, TABLE_VERSION)
34}
35
36pub fn hash_spectral_sum_with(n: &SpectralSum, node: &mut dyn FnMut(NodeId) -> Hash) -> Hash {
40 let mut s = Sink::new(0x01, TABLE_VERSION);
41 s.node = Some(node);
42 s.var(n.var);
43 s.u64(n.lanes.len() as u64);
44 for lane in &n.lanes {
45 s.lane(lane);
46 }
47 s.finish()
48}
49
50pub fn hash_spectral_sum_under(n: &SpectralSum, table_version: u64) -> Hash {
53 let mut s = Sink::new(0x01, table_version);
54 s.var(n.var);
55 s.u64(n.lanes.len() as u64);
56 for lane in &n.lanes {
57 s.lane(lane);
58 }
59 s.finish()
60}
61
62pub fn hash_closed_form_under(t: &ClosedForm, table_version: u64) -> Hash {
63 let mut s = Sink::new(0x02, table_version);
64 s.var(t.var);
65 s.formula(&t.body);
66 s.finish()
67}
68
69pub fn either_order(operands: &mut [Hash]) {
71 if let [a, b] = operands
72 && b < a
73 {
74 std::mem::swap(a, b);
75 }
76}
77
78pub fn hash_written_with(t: &ClosedForm, node: &mut dyn FnMut(NodeId) -> Hash) -> Hash {
81 let mut s = Sink {
82 lanes: Lanes::default(),
83 node: Some(node),
84 bound: Vec::new(),
85 free: true,
86 merkle: true,
87 };
88 let held = s.part(&t.body);
89 match t.var {
90 Var::T => held,
91 Var::F => {
92 let mut f = Sink::new(0x06, 0);
93 f.u64(held.0);
94 f.u64(held.1);
95 f.finish()
96 }
97 }
98}
99
100pub fn hash_time(at: &Body) -> Hash {
103 let mut s = Sink::new(0x05, TABLE_VERSION);
104 s.free = true;
105 s.formula(at);
106 s.finish()
107}
108
109pub fn draw(seed: u64, step: i64) -> f64 {
111 mix(mix(seed ^ DRAWN) ^ step as u64) as f64 / u64::MAX as f64
112}
113
114const DRAWN: u64 = 0x9e37_79b9_7f4a_7c15;
115
116pub fn draw_nearest(seed: u64, key: f64) -> Option<f64> {
118 let step = key.round_ties_even();
119 let held = step >= i64::MIN as f64 && step < i64::MAX as f64;
120 held.then(|| draw(seed, step as i64))
121}
122
123struct Sink<'a> {
124 lanes: Lanes<0>,
125 node: Option<&'a mut dyn FnMut(NodeId) -> Hash>,
126 bound: Vec<IndexId>,
129 free: bool,
131 merkle: bool,
133}
134
135impl<'a> Sink<'a> {
136 fn new(tag: u8, table_version: u64) -> Sink<'a> {
137 let mut s = Sink {
138 lanes: Lanes::default(),
139 node: None,
140 bound: Vec::new(),
141 free: false,
142 merkle: false,
143 };
144 s.byte(tag);
145 s.u64(table_version);
146 s
147 }
148
149 fn byte(&mut self, b: u8) {
150 self.lanes.word(u64::from(b));
151 }
152
153 fn u64(&mut self, v: u64) {
154 for b in v.to_le_bytes() {
155 self.byte(b);
156 }
157 }
158
159 fn i64(&mut self, v: i64) {
160 self.u64(v as u64);
161 }
162
163 fn f64(&mut self, v: f64) {
164 self.u64(canonical(v));
165 }
166
167 fn c64(&mut self, v: C64) {
168 let (re, im) = v.bits();
169 self.u64(re);
170 self.u64(im);
171 }
172
173 fn var(&mut self, v: Var) {
174 self.byte(match v {
175 Var::T => 0,
176 Var::F => 1,
177 });
178 }
179
180 fn edge(&mut self, e: Edge) {
181 match e {
182 Edge::NegInf => self.byte(0),
183 Edge::At(bits) => {
184 self.byte(1);
185 self.u64(bits);
186 }
187 Edge::PosInf => self.byte(2),
188 }
189 }
190
191 fn lane(&mut self, lane: &Lane) {
192 self.u64(lane.atoms.len() as u64);
193 for a in &lane.atoms {
194 self.atom(a);
195 }
196 self.u64(lane.series.len() as u64);
197 for s in &lane.series {
198 self.series(s);
199 }
200 self.u64(lane.modal.len() as u64);
201 for m in &lane.modal {
202 self.modal(m);
203 }
204 }
205
206 fn atom(&mut self, a: &SpectralAtom) {
208 self.c64(a.c);
209 self.u64(u64::from(a.poly.degree));
210 self.f64(a.poly.at);
211 match a.exp {
212 None => self.byte(0),
213 Some(e) => {
214 self.byte(1);
215 self.f64(e.sigma);
216 self.f64(e.omega);
217 }
218 }
219 match a.gauss {
220 None => self.byte(0),
221 Some(g) => {
222 self.byte(1);
223 self.f64(g.a);
224 self.f64(g.mu);
225 }
226 }
227 match a.ind {
228 None => self.byte(0),
229 Some(i) => {
230 self.byte(1);
231 self.edge(i.l);
232 self.edge(i.r);
233 }
234 }
235 match a.pole {
236 None => self.byte(0),
237 Some(p) => {
238 self.byte(1);
239 self.c64(p.at);
240 self.u64(u64::from(p.order));
241 self.byte(u8::from(p.pv));
242 }
243 }
244 match a.sing {
245 Singular::Regular => self.byte(0),
246 Singular::Delta { at, order } => {
247 self.byte(1);
248 self.f64(at);
249 self.u64(u64::from(order));
250 }
251 }
252 }
253
254 fn series(&mut self, s: &Series) {
255 self.i64(s.lo);
256 match s.hi {
257 Bound::Finite(n) => {
258 self.byte(0);
259 self.i64(n);
260 }
261 Bound::Infinite => self.byte(1),
262 }
263 self.bound.push(s.index);
264 self.formula(&s.term.body);
265 self.bound.pop();
266 }
267
268 fn amps(&mut self, amps: &[C64]) {
269 self.u64(amps.len() as u64);
270 for a in amps {
271 self.c64(*a);
272 }
273 }
274
275 fn modal(&mut self, m: &ModalBank) {
276 self.u64(m.modes.len() as u64);
277 for Mode {
278 omega,
279 tau,
280 amp,
281 phase,
282 } in &m.modes
283 {
284 self.f64(*omega);
285 self.f64(*tau);
286 self.f64(*amp);
287 self.f64(*phase);
288 }
289 match m.excite {
290 Excitation::HammerPulse { f0, t0, contact } => {
291 self.byte(0);
292 self.f64(f0);
293 self.f64(t0);
294 self.f64(contact);
295 }
296 Excitation::Impulse { t0 } => {
297 self.byte(1);
298 self.f64(t0);
299 }
300 }
301 }
302
303 fn parts(&mut self, parts: &[Part]) {
304 self.u64(parts.len() as u64);
305 for p in parts {
306 self.child(&p.body);
307 }
308 }
309
310 fn commuting(&mut self, parts: &[Part]) {
311 let [a, b] = parts else {
312 return self.parts(parts);
313 };
314 if !self.merkle {
315 return self.parts(parts);
316 }
317 let mut held = [self.part(&a.body), self.part(&b.body)];
318 either_order(&mut held);
319 self.u64(2);
320 for Hash(x, y) in held {
321 self.u64(x);
322 self.u64(y);
323 }
324 }
325
326 fn child(&mut self, f: &Body) {
327 match self.merkle {
328 true => {
329 let Hash(x, y) = self.part(f);
330 self.u64(x);
331 self.u64(y);
332 }
333 false => self.formula(f),
334 }
335 }
336
337 fn part(&mut self, f: &Body) -> Hash {
338 if let Body::Node(n) = f
339 && let Some(named) = self.node.as_mut()
340 {
341 return named(*n);
342 }
343 let mut sub = Sink {
344 lanes: Lanes::default(),
345 node: self.node.take(),
346 bound: std::mem::take(&mut self.bound),
347 free: self.free,
348 merkle: true,
349 };
350 sub.formula(f);
351 self.node = sub.node.take();
352 self.bound = std::mem::take(&mut sub.bound);
353 sub.finish()
354 }
355
356 fn rational(&mut self, r: &Rational) {
357 self.u64(r.zeros.len() as u64);
358 for z in &r.zeros {
359 self.c64(*z);
360 }
361 self.u64(r.poles.len() as u64);
362 for p in &r.poles {
363 self.c64(*p);
364 }
365 self.c64(r.gain);
366 }
367
368 fn formula(&mut self, f: &Body) {
369 match f {
370 Body::Const(c) => {
371 self.byte(0x10);
372 self.c64(*c);
373 }
374 Body::Line => self.byte(0x11),
375 Body::Index(i) => match self.bound.iter().rev().position(|b| b == i) {
376 Some(depth) => {
377 self.byte(0x12);
378 self.u64(depth as u64);
379 }
380 None => {
381 assert!(self.free, "an index inside the series binding it");
382 self.byte(0x29);
383 self.u64(u64::from(i.0));
384 }
385 },
386 Body::Param(p) => {
387 self.byte(0x13);
388 self.u64(u64::from(p.0));
389 }
390 Body::Node(n) => {
391 self.byte(0x14);
392 match self.node.as_mut().map(|named| named(*n)) {
393 Some(held) => {
394 self.u64(held.0);
395 self.u64(held.1);
396 }
397 None => self.u64(u64::from(n.0)),
398 }
399 }
400 Body::Add(parts) => {
401 self.byte(0x15);
402 self.commuting(parts);
403 }
404 Body::Mul(parts) => {
405 self.byte(0x16);
406 self.commuting(parts);
407 }
408 Body::Div(a, b) => {
409 self.byte(0x17);
410 self.child(&a.body);
411 self.child(&b.body);
412 }
413 Body::Pow(base, n) => {
414 self.byte(0x18);
415 self.child(&base.body);
416 self.i64(i64::from(*n));
417 }
418 Body::Apply(op, arg) => {
419 self.byte(0x19);
420 self.byte(unary_tag(*op));
421 self.child(&arg.body);
422 }
423 Body::Fold(op, args) => {
424 self.byte(0x1a);
425 self.byte(match op {
426 Fold::Max => 0,
427 Fold::Min => 1,
428 Fold::Mod => 2,
429 });
430 self.parts(args);
431 }
432 Body::Delta { at, order } => {
433 self.byte(0x1b);
434 self.child(&at.body);
435 self.u64(u64::from(*order));
436 }
437 Body::Pv(at) => {
438 self.byte(0x1c);
439 self.child(&at.body);
440 }
441 Body::Warp { at, of } => {
442 self.byte(0x27);
443 self.child(&at.body);
444 self.child(&of.body);
445 }
446 Body::Shift { by, of } => {
447 self.byte(0x1d);
448 self.f64(*by);
449 self.child(&of.body);
450 }
451 Body::Deriv { order, of } => {
452 self.byte(0x1e);
453 self.u64(u64::from(*order));
454 self.child(&of.body);
455 }
456 Body::Crop {
457 of,
458 l,
459 r,
460 rise,
461 fall,
462 } => {
463 self.byte(0x1f);
464 self.child(&of.body);
465 self.edge(*l);
466 self.edge(*r);
467 self.f64(*rise);
468 self.f64(*fall);
469 }
470 Body::Join(parts) => {
471 self.byte(0x21);
472 self.parts(parts);
473 }
474 Body::Channel(of, k) => {
475 self.byte(0x22);
476 self.child(&of.body);
477 self.byte(*k);
478 }
479 Body::Rational(r) => {
480 self.byte(0x23);
481 self.rational(r);
482 }
483 Body::Series(s) => {
484 self.byte(0x24);
485 self.series(s);
486 }
487 Body::Modal(m) => {
488 self.byte(0x25);
489 self.modal(m);
490 }
491 Body::Run(run) => {
492 self.byte(0x28);
493 self.f64(run.offset);
494 self.f64(run.step);
495 self.i64(run.first);
496 self.amps(&run.amps);
497 match &run.mirror {
498 Mirror::None => self.byte(0),
499 Mirror::Conjugate => self.byte(1),
500 Mirror::Held(amps) => {
501 self.byte(2);
502 self.amps(amps);
503 }
504 }
505 }
506 Body::Banded(b) => {
507 self.byte(0x29);
508 self.series(&b.series);
509 for sum in [&b.slope, &b.offset] {
510 self.u64(sum.lanes.len() as u64);
511 sum.lanes.iter().for_each(|lane| self.lane(lane));
512 }
513 for x in [b.omega, b.reach, b.dropped_db] {
514 self.f64(x);
515 }
516 self.i64(b.most);
517 self.i64(b.widest);
518 }
519 Body::Keyed { seed, of } => {
520 self.byte(0x26);
521 self.u64(*seed);
522 self.child(&of.body);
523 }
524 }
525 }
526
527 fn finish(&self) -> Hash {
529 let Hash(a, b) = self.lanes.finish();
530 Hash(mix(a), mix(b))
531 }
532}
533
534fn unary_tag(op: Unary) -> u8 {
535 match op {
536 Unary::Sin => 0,
537 Unary::Cos => 1,
538 Unary::Exp => 2,
539 Unary::Tanh => 3,
540 Unary::Sat => 4,
541 Unary::Abs => 5,
542 Unary::Log => 6,
543 Unary::Sqrt => 7,
544 Unary::Step => 8,
545 }
546}
547
548fn mix(mut z: u64) -> u64 {
549 z = (z ^ (z >> 30)).wrapping_mul(0xbf58_476d_1ce4_e5b9);
550 z = (z ^ (z >> 27)).wrapping_mul(0x94d0_49bb_1331_11eb);
551 z ^ (z >> 31)
552}