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::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_under(n: &SpectralSum, table_version: u64) -> Hash {
39 let mut s = Sink::new(0x01, table_version);
40 s.var(n.var);
41 s.u64(n.lanes.len() as u64);
42 for lane in &n.lanes {
43 s.lane(lane);
44 }
45 s.finish()
46}
47
48pub fn hash_closed_form_under(t: &ClosedForm, table_version: u64) -> Hash {
49 let mut s = Sink::new(0x02, table_version);
50 s.var(t.var);
51 s.formula(&t.body);
52 s.finish()
53}
54
55pub fn hash_closed_form_with(t: &ClosedForm, node: &mut dyn FnMut(NodeId) -> Hash) -> Hash {
58 let mut s = Sink::new(0x04, TABLE_VERSION);
59 s.node = Some(node);
60 s.var(t.var);
61 s.formula(&t.body);
62 s.finish()
63}
64
65pub fn draw(seed: u64, step: i64) -> f64 {
67 mix(mix(seed ^ DRAWN) ^ step as u64) as f64 / u64::MAX as f64
68}
69
70const DRAWN: u64 = 0x9e37_79b9_7f4a_7c15;
71
72pub fn draw_nearest(seed: u64, key: f64) -> Option<f64> {
74 let step = key.round_ties_even();
75 let held = step >= i64::MIN as f64 && step < i64::MAX as f64;
76 held.then(|| draw(seed, step as i64))
77}
78
79struct Sink<'a> {
80 lanes: Lanes<0>,
81 node: Option<&'a mut dyn FnMut(NodeId) -> Hash>,
82}
83
84impl<'a> Sink<'a> {
85 fn new(tag: u8, table_version: u64) -> Sink<'a> {
86 let mut s = Sink {
87 lanes: Lanes::default(),
88 node: None,
89 };
90 s.byte(tag);
91 s.u64(table_version);
92 s
93 }
94
95 fn byte(&mut self, b: u8) {
96 self.lanes.word(u64::from(b));
97 }
98
99 fn u64(&mut self, v: u64) {
100 for b in v.to_le_bytes() {
101 self.byte(b);
102 }
103 }
104
105 fn i64(&mut self, v: i64) {
106 self.u64(v as u64);
107 }
108
109 fn f64(&mut self, v: f64) {
110 self.u64(canonical(v));
111 }
112
113 fn c64(&mut self, v: C64) {
114 let (re, im) = v.bits();
115 self.u64(re);
116 self.u64(im);
117 }
118
119 fn var(&mut self, v: Var) {
120 self.byte(match v {
121 Var::T => 0,
122 Var::F => 1,
123 });
124 }
125
126 fn edge(&mut self, e: Edge) {
127 match e {
128 Edge::NegInf => self.byte(0),
129 Edge::At(bits) => {
130 self.byte(1);
131 self.u64(bits);
132 }
133 Edge::PosInf => self.byte(2),
134 }
135 }
136
137 fn lane(&mut self, lane: &Lane) {
138 self.u64(lane.atoms.len() as u64);
139 for a in &lane.atoms {
140 self.atom(a);
141 }
142 self.u64(lane.series.len() as u64);
143 for s in &lane.series {
144 self.series(s);
145 }
146 self.u64(lane.modal.len() as u64);
147 for m in &lane.modal {
148 self.modal(m);
149 }
150 }
151
152 fn atom(&mut self, a: &SpectralAtom) {
154 self.c64(a.c);
155 self.u64(u64::from(a.poly.degree));
156 self.f64(a.poly.at);
157 match a.exp {
158 None => self.byte(0),
159 Some(e) => {
160 self.byte(1);
161 self.f64(e.sigma);
162 self.f64(e.omega);
163 }
164 }
165 match a.gauss {
166 None => self.byte(0),
167 Some(g) => {
168 self.byte(1);
169 self.f64(g.a);
170 self.f64(g.mu);
171 }
172 }
173 match a.ind {
174 None => self.byte(0),
175 Some(i) => {
176 self.byte(1);
177 self.edge(i.l);
178 self.edge(i.r);
179 }
180 }
181 match a.pole {
182 None => self.byte(0),
183 Some(p) => {
184 self.byte(1);
185 self.c64(p.at);
186 self.u64(u64::from(p.order));
187 self.byte(u8::from(p.pv));
188 }
189 }
190 match a.sing {
191 Singular::Regular => self.byte(0),
192 Singular::Delta { at, order } => {
193 self.byte(1);
194 self.f64(at);
195 self.u64(u64::from(order));
196 }
197 }
198 }
199
200 fn series(&mut self, s: &Series) {
201 self.u64(u64::from(s.index.0));
202 self.i64(s.lo);
203 match s.hi {
204 Bound::Finite(n) => {
205 self.byte(0);
206 self.i64(n);
207 }
208 Bound::Infinite => self.byte(1),
209 }
210 self.formula(&s.term.body);
211 }
212
213 fn amps(&mut self, amps: &[C64]) {
214 self.u64(amps.len() as u64);
215 for a in amps {
216 self.c64(*a);
217 }
218 }
219
220 fn modal(&mut self, m: &ModalBank) {
221 self.u64(m.modes.len() as u64);
222 for Mode {
223 omega,
224 tau,
225 amp,
226 phase,
227 } in &m.modes
228 {
229 self.f64(*omega);
230 self.f64(*tau);
231 self.f64(*amp);
232 self.f64(*phase);
233 }
234 match m.excite {
235 Excitation::HammerPulse { f0, t0, contact } => {
236 self.byte(0);
237 self.f64(f0);
238 self.f64(t0);
239 self.f64(contact);
240 }
241 Excitation::Impulse { t0 } => {
242 self.byte(1);
243 self.f64(t0);
244 }
245 }
246 }
247
248 fn parts(&mut self, parts: &[Part]) {
249 self.u64(parts.len() as u64);
250 for p in parts {
251 self.formula(&p.body);
252 }
253 }
254
255 fn rational(&mut self, r: &Rational) {
256 self.u64(r.zeros.len() as u64);
257 for z in &r.zeros {
258 self.c64(*z);
259 }
260 self.u64(r.poles.len() as u64);
261 for p in &r.poles {
262 self.c64(*p);
263 }
264 self.c64(r.gain);
265 }
266
267 fn formula(&mut self, f: &Body) {
268 match f {
269 Body::Const(c) => {
270 self.byte(0x10);
271 self.c64(*c);
272 }
273 Body::Line => self.byte(0x11),
274 Body::Index(i) => {
275 self.byte(0x12);
276 self.u64(u64::from(i.0));
277 }
278 Body::Param(p) => {
279 self.byte(0x13);
280 self.u64(u64::from(p.0));
281 }
282 Body::Node(n) => {
283 self.byte(0x14);
284 match self.node.as_mut().map(|named| named(*n)) {
285 Some(held) => {
286 self.u64(held.0);
287 self.u64(held.1);
288 }
289 None => self.u64(u64::from(n.0)),
290 }
291 }
292 Body::Add(parts) => {
293 self.byte(0x15);
294 self.parts(parts);
295 }
296 Body::Mul(parts) => {
297 self.byte(0x16);
298 self.parts(parts);
299 }
300 Body::Div(a, b) => {
301 self.byte(0x17);
302 self.formula(&a.body);
303 self.formula(&b.body);
304 }
305 Body::Pow(base, n) => {
306 self.byte(0x18);
307 self.formula(&base.body);
308 self.i64(i64::from(*n));
309 }
310 Body::Apply(op, arg) => {
311 self.byte(0x19);
312 self.byte(unary_tag(*op));
313 self.formula(&arg.body);
314 }
315 Body::Fold(op, args) => {
316 self.byte(0x1a);
317 self.byte(match op {
318 Fold::Max => 0,
319 Fold::Min => 1,
320 Fold::Mod => 2,
321 });
322 self.parts(args);
323 }
324 Body::Delta { at, order } => {
325 self.byte(0x1b);
326 self.formula(&at.body);
327 self.u64(u64::from(*order));
328 }
329 Body::Pv(at) => {
330 self.byte(0x1c);
331 self.formula(&at.body);
332 }
333 Body::Warp { at, of } => {
334 self.byte(0x27);
335 self.formula(&at.body);
336 self.formula(&of.body);
337 }
338 Body::Shift { by, of } => {
339 self.byte(0x1d);
340 self.f64(*by);
341 self.formula(&of.body);
342 }
343 Body::Deriv { order, of } => {
344 self.byte(0x1e);
345 self.u64(u64::from(*order));
346 self.formula(&of.body);
347 }
348 Body::Crop {
349 of,
350 l,
351 r,
352 rise,
353 fall,
354 } => {
355 self.byte(0x1f);
356 self.formula(&of.body);
357 self.edge(*l);
358 self.edge(*r);
359 self.f64(*rise);
360 self.f64(*fall);
361 }
362 Body::Join(parts) => {
363 self.byte(0x21);
364 self.parts(parts);
365 }
366 Body::Channel(of, k) => {
367 self.byte(0x22);
368 self.formula(&of.body);
369 self.byte(*k);
370 }
371 Body::Rational(r) => {
372 self.byte(0x23);
373 self.rational(r);
374 }
375 Body::Series(s) => {
376 self.byte(0x24);
377 self.series(s);
378 }
379 Body::Modal(m) => {
380 self.byte(0x25);
381 self.modal(m);
382 }
383 Body::Run(run) => {
384 self.byte(0x28);
385 self.f64(run.offset);
386 self.f64(run.step);
387 self.i64(run.first);
388 self.amps(&run.amps);
389 match &run.mirror {
390 Mirror::None => self.byte(0),
391 Mirror::Conjugate => self.byte(1),
392 Mirror::Held(amps) => {
393 self.byte(2);
394 self.amps(amps);
395 }
396 }
397 }
398 Body::Keyed { seed, of } => {
399 self.byte(0x26);
400 self.u64(*seed);
401 self.formula(&of.body);
402 }
403 }
404 }
405
406 fn finish(&self) -> Hash {
408 let Hash(a, b) = self.lanes.finish();
409 Hash(mix(a), mix(b))
410 }
411}
412
413fn unary_tag(op: Unary) -> u8 {
414 match op {
415 Unary::Sin => 0,
416 Unary::Cos => 1,
417 Unary::Exp => 2,
418 Unary::Tanh => 3,
419 Unary::Sat => 4,
420 Unary::Abs => 5,
421 Unary::Log => 6,
422 Unary::Sqrt => 7,
423 Unary::Step => 8,
424 }
425}
426
427fn mix(mut z: u64) -> u64 {
428 z = (z ^ (z >> 30)).wrapping_mul(0xbf58_476d_1ce4_e5b9);
429 z = (z ^ (z >> 27)).wrapping_mul(0x94d0_49bb_1331_11eb);
430 z ^ (z >> 31)
431}