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