lib.rs
104.2 kB · rust · 2493 lines
1#![allow(non_camel_case_types, non_snake_case, clippy::too_many_arguments)]23mod hand;45use wasm_bindgen::prelude::*;67/// The bilinear form `B(u, v) = (sum u)(sum v) - 2 sum u v` that the reflection preserves.8#[wasm_bindgen]9pub fn apollonian_form(u: JsValue, v: JsValue) -> Result<JsValue, JsValue> {10 let u = hand::array_from_js::<_, 4>(&u, hand::i64_from_js)?;11 let v = hand::array_from_js::<_, 4>(&v, hand::i64_from_js)?;12 let value = mrlyrs::num::apollonian::form(u, v);13 Ok(JsValue::from_str(&value.to_string()))14}1516/// The box the packing is drawn in: one period of the strip, or the box of the circle that contains a bounded packing.17#[wasm_bindgen]18pub fn apollonian_frame(p: JsValue) -> Result<Vec<f64>, JsValue> {19 let p = hand::from_js::<mrlyrs::num::apollonian::Packing>(&p)?;20 let value = mrlyrs::num::apollonian::frame(&p);21 Ok(value.to_vec())22}2324/// Grows the named packing to the curvature cap, one circle per node of the reflection tree and the root quadruple excluded, so `circles.len()` is the census `N(T)`. On the strip only the two root swaps that replace a line are taken, which are exactly the two that stay inside one period.25#[wasm_bindgen]26pub fn apollonian_grow(name: &str, cap: JsValue) -> Result<JsValue, JsValue> {27 let cap = hand::i64_from_js(&cap)?;28 let value = mrlyrs::num::apollonian::grow(name, cap).map_err(hand::throw)?;29 hand::to_js(&value)30}3132/// Whether the circle is the Ford circle over its own tangency point: curvature `2 b^2` and abscissa `2 a b` at the reduced `a/b`.33#[wasm_bindgen]34pub fn apollonian_is_ford(c: &apollonian_Circle) -> Result<bool, JsValue> {35 let value = mrlyrs::num::apollonian::is_ford(c.inner);36 Ok(value)37}3839/// Whether the circle has positive curvature and is tangent to the line `y = 0`, which in these coordinates reads `k > 0` and `k y = 1`: the curvature guard is what excludes the line `y = 1`, which is `(0, 0, 1)`.40#[wasm_bindgen]41pub fn apollonian_on_line(c: &apollonian_Circle) -> Result<bool, JsValue> {42 let value = mrlyrs::num::apollonian::on_line(c.inner);43 Ok(value)44}4546/// Reflects the circle at the seat through the other three, `v' = 2(v_1 + v_2 + v_3) - v` on all three coordinates at once, which is the second root of the Descartes quadratic and needs no square root.47#[wasm_bindgen]48pub fn apollonian_reflect(q: JsValue, at: usize) -> Result<apollonian_Circle, JsValue> {49 let q = hand::array_from_js::<_, 4>(&q, |x1| hand::from_js::<mrlyrs::num::apollonian::Circle>(&hand::plain(x1)?))?;50 let value = mrlyrs::num::apollonian::reflect(&q, at);51 Ok(apollonian_Circle { inner: value })52}5354/// The named root quadruple: `strip` is the two lines a unit apart holding the circles at `0` and `1`, and the rest are bounded packings named by their four curvatures.55#[wasm_bindgen]56pub fn apollonian_root(name: &str) -> Result<JsValue, JsValue> {57 let value = mrlyrs::num::apollonian::root(name).map_err(hand::throw)?;58 hand::list_to_js(&value, |x1| Ok(JsValue::from(apollonian_Circle { inner: *x1 })))59}6061/// Reads the Farey stack of the order against the packing: the nodes lit inside the open period against the tangency points of the line-tangent circles of curvature at most `2 Q^2`, and the brightness `floor(Q/b)` summed on the nodes against `Q(Q + 1)/2`. Off the strip there is no line and every count is zero.62#[wasm_bindgen]63pub fn apollonian_shadow(p: JsValue, order: usize) -> Result<JsValue, JsValue> {64 let p = hand::from_js::<mrlyrs::num::apollonian::Packing>(&p)?;65 let value = mrlyrs::num::apollonian::shadow(&p, order).map_err(hand::throw)?;66 hand::to_js(&value)67}6869/// Whether the quadruple carries all six exact invariants: Descartes `B(k, k) = 0`, the position half `B(k, kx) = B(k, ky) = B(kx, ky) = 0`, and the frame `B(kx, kx) = B(ky, ky) = -4`.70#[wasm_bindgen]71pub fn apollonian_sound(q: JsValue) -> Result<bool, JsValue> {72 let q = hand::array_from_js::<_, 4>(&q, |x1| hand::from_js::<mrlyrs::num::apollonian::Circle>(&hand::plain(x1)?))?;73 let value = mrlyrs::num::apollonian::sound(&q);74 Ok(value)75}7677/// The quadruple with the circle at the seat replaced by its reflection.78#[wasm_bindgen]79pub fn apollonian_swap(q: JsValue, at: usize) -> Result<JsValue, JsValue> {80 let q = hand::array_from_js::<_, 4>(&q, |x1| hand::from_js::<mrlyrs::num::apollonian::Circle>(&hand::plain(x1)?))?;81 let value = mrlyrs::num::apollonian::swap(&q, at);82 hand::list_to_js(&value, |x1| Ok(JsValue::from(apollonian_Circle { inner: *x1 })))83}8485/// The tangency points on the line `y = 0`, ascending: one per circle of the packing with `k y = 1`, the root excluded. Empty off the strip.86#[wasm_bindgen]87pub fn apollonian_touches(p: JsValue) -> Result<JsValue, JsValue> {88 let p = hand::from_js::<mrlyrs::num::apollonian::Packing>(&p)?;89 let value = mrlyrs::num::apollonian::touches(&p);90 hand::to_js(&value)91}9293/// Adds two sequences term by term over their shared length.94#[wasm_bindgen]95pub fn blend_add(a: JsValue, b: JsValue) -> Result<JsValue, JsValue> {96 let a = hand::list_from_js(&a, hand::i128_from_js)?;97 let b = hand::list_from_js(&b, hand::i128_from_js)?;98 let value = mrlyrs::num::blend::add(&a, &b);99 hand::list_to_js(&value, |x1| Ok(JsValue::from_str(&x1.to_string())))100}101102/// Convolves two sequences, keeping the exact prefix their shared length affords.103#[wasm_bindgen]104pub fn blend_cauchy(a: JsValue, b: JsValue) -> Result<JsValue, JsValue> {105 let a = hand::list_from_js(&a, hand::i128_from_js)?;106 let b = hand::list_from_js(&b, hand::i128_from_js)?;107 let value = mrlyrs::num::blend::cauchy(&a, &b).map_err(hand::throw)?;108 hand::list_to_js(&value, |x1| Ok(JsValue::from_str(&x1.to_string())))109}110111/// Returns the monic characteristic polynomial of a recurrence, highest power first.112#[wasm_bindgen]113pub fn blend_characteristic(coefficients: JsValue) -> Result<JsValue, JsValue> {114 let coefficients = hand::list_from_js(&coefficients, |x1| Ok((hand::i128_from_js(&hand::item(x1, 0)?)?, hand::i128_from_js(&hand::item(x1, 1)?)?)))?;115 let value = mrlyrs::num::blend::characteristic(&coefficients);116 hand::list_to_js(&value, |x1| Ok(hand::tuple_to_js(&[JsValue::from_str(&x1.0.to_string()), JsValue::from_str(&x1.1.to_string())])))117}118119/// Keeps every step-th term from the offset onward.120#[wasm_bindgen]121pub fn blend_decimate(a: JsValue, step: usize, offset: usize) -> Result<JsValue, JsValue> {122 let a = hand::list_from_js(&a, hand::i128_from_js)?;123 let value = mrlyrs::num::blend::decimate(&a, step, offset).map_err(hand::throw)?;124 hand::list_to_js(&value, |x1| Ok(JsValue::from_str(&x1.to_string())))125}126127/// Returns the first differences of a sequence, one term shorter.128#[wasm_bindgen]129pub fn blend_delta(a: JsValue) -> Result<JsValue, JsValue> {130 let a = hand::list_from_js(&a, hand::i128_from_js)?;131 let value = mrlyrs::num::blend::delta(&a);132 hand::list_to_js(&value, |x1| Ok(JsValue::from_str(&x1.to_string())))133}134135/// Returns the largest positive real root of a recurrence's characteristic polynomial, the growth rate, or a not-a-number where no real root lands.136#[wasm_bindgen]137pub fn blend_growth(coefficients: JsValue) -> Result<f64, JsValue> {138 let coefficients = hand::list_from_js(&coefficients, |x1| Ok((hand::i128_from_js(&hand::item(x1, 0)?)?, hand::i128_from_js(&hand::item(x1, 1)?)?)))?;139 let value = mrlyrs::num::blend::growth(&coefficients);140 Ok(value)141}142143/// Multiplies two sequences term by term over their shared length.144#[wasm_bindgen]145pub fn blend_hadamard(a: JsValue, b: JsValue) -> Result<JsValue, JsValue> {146 let a = hand::list_from_js(&a, hand::i128_from_js)?;147 let b = hand::list_from_js(&b, hand::i128_from_js)?;148 let value = mrlyrs::num::blend::hadamard(&a, &b);149 hand::list_to_js(&value, |x1| Ok(JsValue::from_str(&x1.to_string())))150}151152/// Finds the smallest linear constant-coefficient recurrence that fits every supplied term.153#[wasm_bindgen]154pub fn blend_recurrence(terms: JsValue) -> Result<JsValue, JsValue> {155 let terms = hand::list_from_js(&terms, hand::i128_from_js)?;156 let value = mrlyrs::num::blend::recurrence(&terms);157 hand::option_to_js(value.as_ref(), |x1| hand::list_to_js(x1, |x2| Ok(hand::tuple_to_js(&[JsValue::from_str(&x2.0.to_string()), JsValue::from_str(&x2.1.to_string())]))))158}159160/// Multiplies every term of a sequence by the factor.161#[wasm_bindgen]162pub fn blend_scale(a: JsValue, factor: JsValue) -> Result<JsValue, JsValue> {163 let a = hand::list_from_js(&a, hand::i128_from_js)?;164 let factor = hand::i128_from_js(&factor)?;165 let value = mrlyrs::num::blend::scale(&a, factor);166 hand::list_to_js(&value, |x1| Ok(JsValue::from_str(&x1.to_string())))167}168169/// Drops the first terms of a sequence.170#[wasm_bindgen]171pub fn blend_shift(a: JsValue, count: usize) -> Result<JsValue, JsValue> {172 let a = hand::list_from_js(&a, hand::i128_from_js)?;173 let value = mrlyrs::num::blend::shift(&a, count);174 hand::list_to_js(&value, |x1| Ok(JsValue::from_str(&x1.to_string())))175}176177/// Returns the partial sums of a sequence.178#[wasm_bindgen]179pub fn blend_sigma(a: JsValue) -> Result<JsValue, JsValue> {180 let a = hand::list_from_js(&a, hand::i128_from_js)?;181 let value = mrlyrs::num::blend::sigma(&a).map_err(hand::throw)?;182 hand::list_to_js(&value, |x1| Ok(JsValue::from_str(&x1.to_string())))183}184185/// Subtracts the second sequence from the first over their shared length.186#[wasm_bindgen]187pub fn blend_sub(a: JsValue, b: JsValue) -> Result<JsValue, JsValue> {188 let a = hand::list_from_js(&a, hand::i128_from_js)?;189 let b = hand::list_from_js(&b, hand::i128_from_js)?;190 let value = mrlyrs::num::blend::sub(&a, &b);191 hand::list_to_js(&value, |x1| Ok(JsValue::from_str(&x1.to_string())))192}193194/// Reports whether the packed function outputs one on exactly half of its inputs.195#[wasm_bindgen]196pub fn boolean_is_balanced(code: JsValue, n: usize) -> Result<bool, JsValue> {197 let code = hand::u128_from_js(&code)?;198 let value = mrlyrs::num::boolean::is_balanced(code, n);199 Ok(value)200}201202/// Returns how far the packed function sits from every affine function, zero when it is one.203#[wasm_bindgen]204pub fn boolean_nonlinearity(code: JsValue, n: usize) -> Result<i64, JsValue> {205 let code = hand::u128_from_js(&code)?;206 let value = mrlyrs::num::boolean::nonlinearity(code, n);207 Ok(value)208}209210/// Returns the mean chance that flipping one input bit flips the output, 0.5 at full avalanche.211#[wasm_bindgen]212pub fn boolean_sac(code: JsValue, n: usize) -> Result<f64, JsValue> {213 let code = hand::u128_from_js(&code)?;214 let value = mrlyrs::num::boolean::sac(code, n);215 Ok(value)216}217218/// Returns the Walsh spectrum of an n-input boolean function packed as a truth-table code.219#[wasm_bindgen]220pub fn boolean_walsh_spectrum(code: JsValue, n: usize) -> Result<Vec<i64>, JsValue> {221 let code = hand::u128_from_js(&code)?;222 let value = mrlyrs::num::boolean::walsh_spectrum(code, n);223 Ok(value)224}225226/// Returns the digits a bitmask names inside the base, ascending.227#[wasm_bindgen]228pub fn design_digits_of(mask: u32, base: JsValue) -> Result<Vec<u64>, JsValue> {229 let base = hand::u64_from_js(&base)?;230 let value = mrlyrs::num::design::digits_of(mask, base);231 Ok(value)232}233234/// Returns the density echo, the sum of mu(n) A_F(n)/n over the whole numbers up to each grid point divided by x to the exponent, sieving the Mobius values to the largest element.235#[wasm_bindgen]236pub fn design_echo_series(values: JsValue, log_x: &[f64], exponent: f64) -> Result<Vec<f64>, JsValue> {237 let values = hand::list_from_js(&values, hand::u64_from_js)?;238 let value = mrlyrs::num::design::echo_series(&values, log_x, exponent);239 Ok(value)240}241242/// Returns the elements of the digit design below the base raised to the depth, ascending: the whole numbers of at most that many base digits, every digit drawn from the set and the leading digit nonzero.243#[wasm_bindgen]244pub fn design_elements(base: JsValue, digits: JsValue, depth: usize) -> Result<Vec<u64>, JsValue> {245 let base = hand::u64_from_js(&base)?;246 let digits = hand::list_from_js(&digits, hand::u64_from_js)?;247 let value = mrlyrs::num::design::elements(base, &digits, depth);248 Ok(value)249}250251/// Returns the log grid uniform over the span of the elements, from the log of the first to the log of the last.252#[wasm_bindgen]253pub fn design_log_grid(values: JsValue, samples: usize) -> Result<Vec<f64>, JsValue> {254 let values = hand::list_from_js(&values, hand::u64_from_js)?;255 let value = mrlyrs::num::design::log_grid(&values, samples);256 Ok(value)257}258259/// Returns the running median of the power over a window of the given width, the window clamped at the ends.260#[wasm_bindgen]261pub fn design_median_floor(power: &[f64], width: usize) -> Result<Vec<f64>, JsValue> {262 let value = mrlyrs::num::design::median_floor(power, width);263 Ok(value)264}265266/// Returns the running design Mobius meter, the partial sums of the Mobius values along the elements.267#[wasm_bindgen]268pub fn design_meter(mu: &[i8]) -> Result<Vec<i64>, JsValue> {269 let value = mrlyrs::num::design::meter(mu);270 Ok(value)271}272273/// Returns the distance from the ordinate to the nearest entry of the list, infinite when the list is empty.274#[wasm_bindgen]275pub fn design_nearest(value: f64, list: &[f64]) -> Result<f64, JsValue> {276 let value = mrlyrs::num::design::nearest(value, list);277 Ok(value)278}279280/// Returns the bins inside the band that rise above both neighbours and clear the score threshold, strongest first.281#[wasm_bindgen]282pub fn design_peaks(gamma: &[f64], score: &[f64], band: JsValue, threshold: f64) -> Result<Vec<usize>, JsValue> {283 let band = hand::from_js::<(f64, f64)>(&band)?;284 let value = mrlyrs::num::design::peaks(gamma, score, band, threshold).map_err(hand::throw)?;285 Ok(value)286}287288/// Returns the design's pole lattice below the top, the ordinates 2 pi j over log q of the poles its Dirichlet series carries.289#[wasm_bindgen]290pub fn design_pole_lattice(base: JsValue, top: f64) -> Result<Vec<f64>, JsValue> {291 let base = hand::u64_from_js(&base)?;292 let value = mrlyrs::num::design::pole_lattice(base, top);293 Ok(value)294}295296/// Reads the running meter at every point of the log grid and divides by x to the exponent.297#[wasm_bindgen]298pub fn design_resample(values: JsValue, running: JsValue, exponent: f64, log_x: &[f64]) -> Result<Vec<f64>, JsValue> {299 let values = hand::list_from_js(&values, hand::u64_from_js)?;300 let running = hand::list_from_js(&running, hand::i64_from_js)?;301 let value = mrlyrs::num::design::resample(&values, &running, exponent, log_x);302 Ok(value)303}304305/// Returns the power over its local median floor, the score a peak is read against.306#[wasm_bindgen]307pub fn design_score(power: &[f64], width: usize) -> Result<Vec<f64>, JsValue> {308 let value = mrlyrs::num::design::score(power, width);309 Ok(value)310}311312/// Returns the count of elements the design holds at the depth, the length [`elements`] returns without building them.313#[wasm_bindgen]314pub fn design_size(digits: JsValue, depth: usize) -> Result<JsValue, JsValue> {315 let digits = hand::list_from_js(&digits, hand::u64_from_js)?;316 let value = mrlyrs::num::design::size(&digits, depth);317 Ok(JsValue::from_str(&value.to_string()))318}319320/// Returns the frequency axis and the power spectrum of the series: the mean removed, a Hann window laid on, a real transform taken, and bin j read as the ordinate 2 pi j over the log range.321#[wasm_bindgen]322pub fn design_spectrum(log_x: &[f64], series: &[f64]) -> Result<JsValue, JsValue> {323 let value = mrlyrs::num::design::spectrum(log_x, series).map_err(hand::throw)?;324 Ok(hand::tuple_to_js(&[hand::typed(&(value.0)[..]), hand::typed(&(value.1)[..])]))325}326327/// Returns the root mean square of the upper half of the series, the size the echo and the meter are compared at.328#[wasm_bindgen]329pub fn design_upper_rms(series: &[f64]) -> Result<f64, JsValue> {330 let value = mrlyrs::num::design::upper_rms(series);331 Ok(value)332}333334/// Returns the sum of the proper divisors of the number, its divisor sum less itself, zero for zero and for one.335#[wasm_bindgen]336pub fn factor_aliquot(number: usize) -> Result<usize, JsValue> {337 let value = mrlyrs::num::factor::aliquot(number);338 Ok(value)339}340341/// Returns whether two numbers share no divisor above one.342#[wasm_bindgen]343pub fn factor_coprime(a: usize, b: usize) -> Result<bool, JsValue> {344 let value = mrlyrs::num::factor::coprime(a, b);345 Ok(value)346}347348/// Builds every divisor of a wide number from its factorization, ascending, empty for zero.349#[wasm_bindgen]350pub fn factor_divisors(number: JsValue) -> Result<Vec<u64>, JsValue> {351 let number = hand::u64_from_js(&number)?;352 let value = mrlyrs::num::factor::divisors(number);353 Ok(value)354}355356/// Returns the factorial of the number, the product of one through it, erring past thirty-four.357#[wasm_bindgen]358pub fn factor_factorial(number: usize) -> Result<JsValue, JsValue> {359 let value = mrlyrs::num::factor::factorial(number).map_err(hand::throw)?;360 Ok(JsValue::from_str(&value.to_string()))361}362363/// Returns the prime and exponent pairs of the number in ascending primes, by trial division on the six-step wheel.364#[wasm_bindgen]365pub fn factor_factorize(number: usize) -> Result<JsValue, JsValue> {366 let value = mrlyrs::num::factor::factorize(number);367 hand::to_js(&value)368}369370/// Returns the prime and exponent pairs of a wide number in ascending primes, by trial division on the six-step wheel.371#[wasm_bindgen]372pub fn factor_factorize_wide(number: JsValue) -> Result<JsValue, JsValue> {373 let number = hand::u64_from_js(&number)?;374 let value = mrlyrs::num::factor::factorize_wide(number);375 hand::list_to_js(&value, |x1| Ok(hand::tuple_to_js(&[JsValue::from(x1.0), hand::to_js(&x1.1)?])))376}377378/// Returns the greatest common divisor of two numbers by the Euclidean algorithm, zero for two zeroes.379#[wasm_bindgen]380pub fn factor_gcd(a: JsValue, b: JsValue) -> Result<JsValue, JsValue> {381 let a = hand::u128_from_js(&a)?;382 let b = hand::u128_from_js(&b)?;383 let value = mrlyrs::num::factor::gcd(a, b);384 Ok(JsValue::from_str(&value.to_string()))385}386387/// Returns the least common multiple of two numbers, zero when either side is zero.388#[wasm_bindgen]389pub fn factor_lcm(a: usize, b: usize) -> Result<usize, JsValue> {390 let value = mrlyrs::num::factor::lcm(a, b);391 Ok(value)392}393394/// Returns the Mobius value of the number: zero for zero or a squared factor, else minus one to the count of primes.395#[wasm_bindgen]396pub fn factor_mobius(number: usize) -> Result<i8, JsValue> {397 let value = mrlyrs::num::factor::mobius(number);398 Ok(value)399}400401/// Sieves the Mobius values of zero through the limit in one pass.402#[wasm_bindgen]403pub fn factor_mobius_sieve(limit: usize) -> Result<Vec<i8>, JsValue> {404 let value = mrlyrs::num::factor::mobius_sieve(limit);405 Ok(value)406}407408/// Returns the radical of the number, the product of its distinct primes, zero for zero and one for one.409#[wasm_bindgen]410pub fn factor_radical(number: usize) -> Result<usize, JsValue> {411 let value = mrlyrs::num::factor::radical(number);412 Ok(value)413}414415/// Reduces a fraction to its lowest terms, a zero numerator and denominator reading as zero over one.416#[wasm_bindgen]417pub fn factor_reduce(numerator: JsValue, denominator: JsValue) -> Result<JsValue, JsValue> {418 let numerator = hand::u128_from_js(&numerator)?;419 let denominator = hand::u128_from_js(&denominator)?;420 let value = mrlyrs::num::factor::reduce(numerator, denominator);421 Ok(hand::tuple_to_js(&[JsValue::from_str(&value.0.to_string()), JsValue::from_str(&value.1.to_string())]))422}423424/// Returns the sum of every divisor of the number raised to the power, so power zero counts them.425#[wasm_bindgen]426pub fn factor_sigma(number: usize, power: u32) -> Result<JsValue, JsValue> {427 let value = mrlyrs::num::factor::sigma(number, power);428 Ok(JsValue::from_str(&value.to_string()))429}430431/// Returns whether no prime squares into the number, true for one and false for zero.432#[wasm_bindgen]433pub fn factor_squarefree(number: usize) -> Result<bool, JsValue> {434 let value = mrlyrs::num::factor::squarefree(number);435 Ok(value)436}437438/// Returns the Euler totient of the number from its factorization, zero for zero and one for one.439#[wasm_bindgen]440pub fn factor_totient(number: usize) -> Result<usize, JsValue> {441 let value = mrlyrs::num::factor::totient(number);442 Ok(value)443}444445/// Sieves the Euler totients of zero through n in one pass, the run beside the single value.446#[wasm_bindgen]447pub fn factor_totients(n: usize) -> Result<Vec<u64>, JsValue> {448 let value = mrlyrs::num::factor::totients(n);449 Ok(value)450}451452/// Returns the divisor sum with a periodic rhythm painted on each divisor, zero for zero and for an empty rhythm.453#[wasm_bindgen]454pub fn factor_twisted(number: usize, rhythm: &[i8]) -> Result<i64, JsValue> {455 let value = mrlyrs::num::factor::twisted(number, rhythm);456 Ok(value)457}458459/// Circularly convolves a size-square field on the torus by a kernel of the same shape through fft2 both ways.460#[wasm_bindgen]461pub fn fft_convolve(field: &[f64], kernel: &[f64], size: usize) -> Result<Vec<f64>, JsValue> {462 let value = mrlyrs::num::fft::convolve(field, kernel, size).map_err(hand::throw)?;463 Ok(value)464}465466/// Convolves a size-square field on the torus by a kernel already transformed by fft2, the inverse scaled back by size squared.467#[wasm_bindgen]468pub fn fft_convolve_with(field: &[f64], kernel_re: &[f64], kernel_im: &[f64], size: usize) -> Result<Vec<f64>, JsValue> {469 let value = mrlyrs::num::fft::convolve_with(field, kernel_re, kernel_im, size).map_err(hand::throw)?;470 Ok(value)471}472473/// Lays an odd-side mask into a size-square kernel with the mask centre at index (0, 0) and negative offsets wrapped; the cell at offset (dr, dc) lands at (-dr, -dc) modulo size, so convolving a field by the kernel reads at every site the mask-weighted sum over its neighbours, the neighbour count the life step counts.474#[wasm_bindgen]475pub fn fft_embed_kernel(mask: &[u8], side: usize, size: usize) -> Result<Vec<f64>, JsValue> {476 let value = mrlyrs::num::fft::embed_kernel(mask, side, size).map_err(hand::throw)?;477 Ok(value)478}479480/// Returns the centred magnitude spectrum of a size-square field through log(1 + magnitude), the DC bin included at the centre.481#[wasm_bindgen]482pub fn fft_log_spectrum(field: &[f64], size: usize) -> Result<Vec<f64>, JsValue> {483 let value = mrlyrs::num::fft::log_spectrum(field, size).map_err(hand::throw)?;484 Ok(value)485}486487/// Returns the magnitudes of a square field's transform, shifted so zero frequency sits at the centre.488#[wasm_bindgen]489pub fn fft_magnitude_spectrum(field: &[f64], size: usize) -> Result<Vec<f64>, JsValue> {490 let value = mrlyrs::num::fft::magnitude_spectrum(field, size).map_err(hand::throw)?;491 Ok(value)492}493494/// Finds the ring past the centre where a radial profile peaks, a tie broken at the smaller ring; zero when the profile holds no ring past ring 0.495#[wasm_bindgen]496pub fn fft_peak_ring(profile: &[f64]) -> Result<usize, JsValue> {497 let value = mrlyrs::num::fft::peak_ring(profile);498 Ok(value)499}500501/// Reads the wavelength in cells at a radial profile's peak, size over the peak ring with a tie broken at the smaller ring; zero when the profile holds no ring past ring 0.502#[wasm_bindgen]503pub fn fft_peak_wavelength(profile: &[f64], size: usize) -> Result<f64, JsValue> {504 let value = mrlyrs::num::fft::peak_wavelength(profile, size);505 Ok(value)506}507508/// Averages a centred size-square spectrum over rings of integer radius from the centre bin, a bin joining the ring its distance rounds to, rings 0 through size over two; ring k holds the frequencies near k cycles per field.509#[wasm_bindgen]510pub fn fft_radial_profile(spectrum: &[f64], size: usize) -> Result<Vec<f64>, JsValue> {511 let value = mrlyrs::num::fft::radial_profile(spectrum, size).map_err(hand::throw)?;512 Ok(value)513}514515/// Transforms a real size-square field forward by fft2, returning the real and imaginary parts.516#[wasm_bindgen]517pub fn fft_transform(field: &[f64], size: usize) -> Result<JsValue, JsValue> {518 let value = mrlyrs::num::fft::transform(field, size).map_err(hand::throw)?;519 Ok(hand::tuple_to_js(&[hand::typed(&(value.0)[..]), hand::typed(&(value.1)[..])]))520}521522/// Lists one point per associate class of the nonzero points of norm at most the bound: canonical associates, in order of norm and then of coordinates.523#[wasm_bindgen]524pub fn gauss_classes(ring: JsValue, bound: JsValue) -> Result<JsValue, JsValue> {525 let ring = hand::from_js::<mrlyrs::num::gauss::Ring>(&ring)?;526 let bound = hand::u64_from_js(&bound)?;527 let value = mrlyrs::num::gauss::classes(ring, bound);528 hand::list_to_js(&value, |x1| Ok(hand::tuple_to_js(&[JsValue::from(x1.0), JsValue::from(x1.1)])))529}530531/// Returns the norm from one through the limit with the most points and that count, the earliest on a tie.532#[wasm_bindgen]533pub fn gauss_peak(ring: JsValue, limit: usize) -> Result<JsValue, JsValue> {534 let ring = hand::from_js::<mrlyrs::num::gauss::Ring>(&ring)?;535 let value = mrlyrs::num::gauss::peak(ring, limit);536 hand::to_js(&value)537}538539/// Counts the points of every norm from zero through the limit, by enumeration: the ring weights of the lattice.540#[wasm_bindgen]541pub fn gauss_shells(ring: JsValue, limit: usize) -> Result<Vec<u32>, JsValue> {542 let ring = hand::from_js::<mrlyrs::num::gauss::Ring>(&ring)?;543 let value = mrlyrs::num::gauss::shells(ring, limit);544 Ok(value)545}546547/// Returns the Lyndon cofactor `Z(s) = zeta_F(s) (1 - k q^(-s))` and the bound it is known to.548#[wasm_bindgen]549pub fn ladder_cofactor(design: &ladder_Design, s: &zeta_Complex, tolerance: f64) -> Result<JsValue, JsValue> {550 let value = mrlyrs::num::ladder::cofactor(&design.inner, s.inner, tolerance).map_err(hand::throw)?;551 Ok(hand::tuple_to_js(&[JsValue::from(zeta_Complex { inner: value.0 }), hand::to_js(&value.1)?]))552}553554/// Returns the residue of `zeta_F` at `s_(m,j) = alpha - m + 2 pi i j / log q` and the bound it is known to.555#[wasm_bindgen]556pub fn ladder_residue(design: &ladder_Design, m: usize, j: JsValue, tolerance: f64) -> Result<JsValue, JsValue> {557 let j = hand::i64_from_js(&j)?;558 let value = mrlyrs::num::ladder::residue(&design.inner, m, j, tolerance).map_err(hand::throw)?;559 Ok(hand::tuple_to_js(&[JsValue::from(zeta_Complex { inner: value.0 }), hand::to_js(&value.1)?]))560}561562/// Returns `zeta_F(s)` and the bound it is known to.563#[wasm_bindgen]564pub fn ladder_zeta(design: &ladder_Design, s: &zeta_Complex, tolerance: f64) -> Result<JsValue, JsValue> {565 let value = mrlyrs::num::ladder::zeta(&design.inner, s.inner, tolerance).map_err(hand::throw)?;566 Ok(hand::tuple_to_js(&[JsValue::from(zeta_Complex { inner: value.0 }), hand::to_js(&value.1)?]))567}568569/// Counts the ordered pairs of coprime coordinates between one and n: twice the totient sum less one.570#[wasm_bindgen]571pub fn lattice_coprime_pairs(n: usize) -> Result<u64, JsValue> {572 let value = mrlyrs::num::lattice::coprime_pairs(n);573 Ok(value)574}575576/// Walks the Farey sequence of the order by the Stern-Brocot mediant recurrence from zero over one to one over one: every reduced fraction with denominator at most the order, ascending.577#[wasm_bindgen]578pub fn lattice_farey(order: usize) -> Result<JsValue, JsValue> {579 let value = mrlyrs::num::lattice::farey(order);580 hand::to_js(&value)581}582583/// Lists the grid crossings of a window's nodes, row-major over the ascending axis nodes.584#[wasm_bindgen]585pub fn lattice_grid(n: usize) -> Result<JsValue, JsValue> {586 let value = mrlyrs::num::lattice::grid(n);587 hand::to_js(&value)588}589590/// Counts the nodes window n lights that window n minus one lacked: two at window one, phi of n after.591#[wasm_bindgen]592pub fn lattice_new_nodes(n: usize) -> Result<u64, JsValue> {593 let value = mrlyrs::num::lattice::new_nodes(n);594 Ok(value)595}596597/// Estimates pi from visibility: the density of coprime pairs in the n-by-n window tends to six over pi squared.598#[wasm_bindgen]599pub fn lattice_pi_estimate(n: usize) -> Result<f64, JsValue> {600 let value = mrlyrs::num::lattice::pi_estimate(n);601 Ok(value)602}603604/// Recovers the constant the dimension hides from the visible count of the window, pi at an even dimension and zeta of the dimension at an odd one.605#[wasm_bindgen]606pub fn lattice_recovered(n: usize, dimension: u32) -> Result<f64, JsValue> {607 let value = mrlyrs::num::lattice::recovered(n, dimension).map_err(hand::throw)?;608 Ok(value)609}610611/// The density the visible count of a window in the dimension walks to, one over zeta of the dimension.612#[wasm_bindgen]613pub fn lattice_visible_density(dimension: u32) -> Result<f64, JsValue> {614 let value = mrlyrs::num::lattice::visible_density(dimension).map_err(hand::throw)?;615 Ok(value)616}617618/// The rational factor r with zeta of the dimension equal to r times pi to the dimension, read off the Bernoulli fraction; none at an odd dimension or past twelve.619#[wasm_bindgen]620pub fn lattice_zeta_factor(dimension: u32) -> Result<JsValue, JsValue> {621 let value = mrlyrs::num::lattice::zeta_factor(dimension);622 hand::to_js(&value)623}624625/// The value zeta takes at a whole argument above one, the exact Bernoulli form at an even one and the Euler-Maclaurin sum at an odd one.626#[wasm_bindgen]627pub fn lattice_zeta_whole(s: u32) -> Result<f64, JsValue> {628 let value = mrlyrs::num::lattice::zeta_whole(s).map_err(hand::throw)?;629 Ok(value)630}631632/// Returns the count of allowed windows `card W`, the bits the code sets inside its window range.633#[wasm_bindgen]634pub fn memory_allowed_windows(rule: &memory_Rule) -> Result<usize, JsValue> {635 let value = mrlyrs::num::memory::allowed_windows(&rule.inner);636 Ok(value)637}638639/// Returns the accepted words of the level as cell indices of the `2^L` grid, `x` from bit `0` of every digit, `y` from bit `1`, `z` from bit `2`, coarsest digit first.640#[wasm_bindgen]641pub fn memory_cells(rule: &memory_Rule, level: usize) -> Result<Vec<u64>, JsValue> {642 let value = mrlyrs::num::memory::cells(&rule.inner, level);643 Ok(value)644}645646/// Returns `N_W(L)`, the count of accepted words, for `L = 1 ..= levels`, and stops early on the level whose count overruns a `u64`.647#[wasm_bindgen]648pub fn memory_counts(rule: &memory_Rule, levels: usize) -> Result<Vec<u64>, JsValue> {649 let value = mrlyrs::num::memory::counts(&rule.inner, levels);650 Ok(value)651}652653/// Returns the growth exponent `log_2 rho`, the growth per digit of the accepted word count.654#[wasm_bindgen]655pub fn memory_exponent(rule: &memory_Rule) -> Result<f64, JsValue> {656 let value = mrlyrs::num::memory::exponent(&rule.inner);657 Ok(value)658}659660/// Returns the memory number `kappa(W) = log_2(card W) / k - log_2 rho`, the bits a digit spends on memory.661#[wasm_bindgen]662pub fn memory_kappa(rule: &memory_Rule) -> Result<f64, JsValue> {663 let value = mrlyrs::num::memory::kappa(&rule.inner);664 Ok(value)665}666667/// Returns the Perron root of the transfer matrix, the count's growth per level.668#[wasm_bindgen]669pub fn memory_perron(rule: &memory_Rule) -> Result<f64, JsValue> {670 let value = mrlyrs::num::memory::perron(&rule.inner);671 Ok(value)672}673674/// Returns the transfer matrix on the `(k - 1)`-windows: entry `(s, t)` is one when the window that overlaps state `s` onto state `t` is allowed.675#[wasm_bindgen]676pub fn memory_transfer(rule: &memory_Rule) -> Result<JsValue, JsValue> {677 let value = mrlyrs::num::memory::transfer(&rule.inner);678 hand::list_to_js(&value, |x1| Ok(hand::typed(&(*x1)[..])))679}680681/// Returns the run-boundary word, one wherever a letter differs from the next.682#[wasm_bindgen]683pub fn morse_boundary(word: &[u8]) -> Result<Vec<u8>, JsValue> {684 let value = mrlyrs::num::morse::boundary(word);685 Ok(value)686}687688/// Exclusive-ors two grids of the same length, site by site.689#[wasm_bindgen]690pub fn morse_difference(a: &[u8], b: &[u8]) -> Result<Vec<u8>, JsValue> {691 let value = mrlyrs::num::morse::difference(a, b);692 Ok(value)693}694695/// Builds the first letters of the Thue-Morse word by the digit rule.696#[wasm_bindgen]697pub fn morse_digits(length: usize) -> Result<Vec<u8>, JsValue> {698 let value = mrlyrs::num::morse::digits(length);699 Ok(value)700}701702/// Builds the period-doubling word by the substitution `1 -> 10`, `0 -> 11`, from the seed 1.703#[wasm_bindgen]704pub fn morse_doubling(length: usize) -> Result<Vec<u8>, JsValue> {705 let value = mrlyrs::num::morse::doubling(length);706 Ok(value)707}708709/// Counts the sites where two grids of the same length differ.710#[wasm_bindgen]711pub fn morse_faults(a: &[u8], b: &[u8]) -> Result<usize, JsValue> {712 let value = mrlyrs::num::morse::faults(a, b);713 Ok(value)714}715716/// Tests a grid against the Kronecker power of its own corner tile.717#[wasm_bindgen]718pub fn morse_fold(grid: &[u8], side: usize, number: usize) -> Result<JsValue, JsValue> {719 let value = mrlyrs::num::morse::fold(grid, side, number).map_err(hand::throw)?;720 hand::to_js(&value)721}722723/// Returns the Thue-Morse letter at the place, the parity of its binary digit sum.724#[wasm_bindgen]725pub fn morse_letter(place: JsValue) -> Result<u8, JsValue> {726 let place = hand::u64_from_js(&place)?;727 let value = mrlyrs::num::morse::letter(place);728 Ok(value)729}730731/// Builds a lift as a row-major sign grid of the side, zero for plus one and one for minus one.732#[wasm_bindgen]733pub fn morse_lift(kind: JsValue, side: usize) -> Result<Vec<u8>, JsValue> {734 let kind = hand::from_js::<mrlyrs::num::morse::Lift>(&kind)?;735 let value = mrlyrs::num::morse::lift(kind, side);736 Ok(value)737}738739/// Folds a tile of the side into its Kronecker power at the level, one bit per site.740#[wasm_bindgen]741pub fn morse_power(tile: &[u8], number: usize, level: usize) -> Result<Vec<u8>, JsValue> {742 let value = mrlyrs::num::morse::power(tile, number, level).map_err(hand::throw)?;743 Ok(value)744}745746/// Repeats a tile until it fills a grid of the side.747#[wasm_bindgen]748pub fn morse_repeat(tile: &[u8], number: usize, side: usize) -> Result<Vec<u8>, JsValue> {749 let value = mrlyrs::num::morse::repeat(tile, number, side);750 Ok(value)751}752753/// Returns the lengths of the maximal blocks of one repeated letter, in order.754#[wasm_bindgen]755pub fn morse_runs(word: &[u8]) -> Result<Vec<usize>, JsValue> {756 let value = mrlyrs::num::morse::runs(word);757 Ok(value)758}759760/// Returns the substitution stage after the rounds, a word of length two to the rounds.761#[wasm_bindgen]762pub fn morse_stage(rounds: usize) -> Result<Vec<u8>, JsValue> {763 let value = mrlyrs::num::morse::stage(rounds);764 Ok(value)765}766767/// Builds the first letters of the Thue-Morse word by the substitution `0 -> 01`, `1 -> 10`.768#[wasm_bindgen]769pub fn morse_substitution(length: usize) -> Result<Vec<u8>, JsValue> {770 let value = mrlyrs::num::morse::substitution(length);771 Ok(value)772}773774/// Blows a grid up by the scale, every site becoming a scale-by-scale block.775#[wasm_bindgen]776pub fn morse_upsample(grid: &[u8], side: usize, scale: usize) -> Result<Vec<u8>, JsValue> {777 let value = mrlyrs::num::morse::upsample(grid, side, scale);778 Ok(value)779}780781/// Reads the prime count against x over ln x and li at evenly spaced points from two up to the top, at most the given count of them, the top always last.782#[wasm_bindgen]783pub fn prime_chart(top: usize, bins: usize) -> Result<JsValue, JsValue> {784 let value = mrlyrs::num::prime::chart(top, bins);785 hand::to_js(&value)786}787788/// Returns whether every number from zero through the limit is prime, the finished sieve read flag by flag.789#[wasm_bindgen]790pub fn prime_flags(limit: usize) -> Result<JsValue, JsValue> {791 let value = mrlyrs::num::prime::flags(limit);792 hand::to_js(&value)793}794795/// Returns the count of unordered pairs of primes summing to the number, zero below four.796#[wasm_bindgen]797pub fn prime_goldbach(number: usize) -> Result<usize, JsValue> {798 let value = mrlyrs::num::prime::goldbach(number);799 Ok(value)800}801802/// Returns the count of prime pairs at every even number from four up to the top, one entry per even number.803#[wasm_bindgen]804pub fn prime_goldbach_record(top: usize) -> Result<Vec<usize>, JsValue> {805 let value = mrlyrs::num::prime::goldbach_record(top);806 Ok(value)807}808809/// Returns whether the number is prime, by trial division on the six-step wheel.810#[wasm_bindgen]811pub fn prime_is_prime(number: usize) -> Result<bool, JsValue> {812 let value = mrlyrs::num::prime::is_prime(number);813 Ok(value)814}815816/// Reads a wide number as a pile of stones, its rectangles built from the divisors of its factorization.817#[wasm_bindgen]818pub fn prime_pile(number: JsValue) -> Result<JsValue, JsValue> {819 let number = hand::u64_from_js(&number)?;820 let value = mrlyrs::num::prime::pile(number);821 hand::to_js(&value)822}823824/// Returns the count of primes at or below n.825#[wasm_bindgen]826pub fn prime_prime_count(n: usize) -> Result<usize, JsValue> {827 let value = mrlyrs::num::prime::prime_count(n);828 Ok(value)829}830831/// Returns the smallest prime at or above the number.832#[wasm_bindgen]833pub fn prime_prime_from(number: usize) -> Result<usize, JsValue> {834 let value = mrlyrs::num::prime::prime_from(number);835 Ok(value)836}837838/// Returns the primes up to the limit, the finished sieve read as a list.839#[wasm_bindgen]840pub fn prime_primes(limit: usize) -> Result<Vec<usize>, JsValue> {841 let value = mrlyrs::num::prime::primes(limit);842 Ok(value)843}844845/// Returns every rectangle of the number as a pair of sides, the shorter first, ascending: the divisors at or below the root.846#[wasm_bindgen]847pub fn prime_rectangles(number: usize) -> Result<JsValue, JsValue> {848 let value = mrlyrs::num::prime::rectangles(number);849 hand::to_js(&value)850}851852/// Returns every pair of primes summing to the number, odd numbers included, the smaller first, ascending.853#[wasm_bindgen]854pub fn prime_splits(number: usize) -> Result<JsValue, JsValue> {855 let value = mrlyrs::num::prime::splits(number);856 hand::to_js(&value)857}858859/// Returns the smallest pair of positive sides whose squares sum to the number, when one exists.860#[wasm_bindgen]861pub fn prime_squares(number: usize) -> Result<JsValue, JsValue> {862 let value = mrlyrs::num::prime::squares(number);863 hand::to_js(&value)864}865866/// Returns one prime object for every prime up to and including the limit.867#[wasm_bindgen]868pub fn prime_study(limit: usize) -> Result<JsValue, JsValue> {869 let value = mrlyrs::num::prime::study(limit);870 hand::to_js(&value)871}872873/// Returns the flowsnake as a radix design: base `3 + omega` of norm seven on the hexagonal lattice, the full residue system, code `127`.874#[wasm_bindgen]875pub fn radix_flowsnake() -> Result<radix_Radix, JsValue> {876 let value = mrlyrs::num::radix::flowsnake().map_err(hand::throw)?;877 Ok(radix_Radix { inner: value })878}879880/// Returns the Sierpinski gasket as a radix design: base `2` on the hexagonal lattice, three of the four residues, code `7`.881#[wasm_bindgen]882pub fn radix_gasket() -> Result<radix_Radix, JsValue> {883 let value = mrlyrs::num::radix::gasket().map_err(hand::throw)?;884 Ok(radix_Radix { inner: value })885}886887/// Returns the Koch curve as a radix design: base `3` on the hexagonal lattice, digits `0, 1, 2 + omega, 2`, twists `1, e^(i pi/3), e^(-i pi/3), 1`.888#[wasm_bindgen]889pub fn radix_koch() -> Result<radix_Radix, JsValue> {890 let value = mrlyrs::num::radix::koch().map_err(hand::throw)?;891 Ok(radix_Radix { inner: value })892}893894/// Returns the terdragon as a radix design: base `2 + omega` on the hexagonal lattice, the full residue system, code `7`, twisted by `1, omega, 1`.895#[wasm_bindgen]896pub fn radix_terdragon() -> Result<radix_Radix, JsValue> {897 let value = mrlyrs::num::radix::terdragon().map_err(hand::throw)?;898 Ok(radix_Radix { inner: value })899}900901/// Returns the plane design of a cell code as a radix design: base the rational integer `m`, of norm `m^2`, on the square lattice, no twist, digits the box residues `{x + y i : 0 <= x, y < m}`.902#[wasm_bindgen]903pub fn radix_tile(m: JsValue, code: JsValue) -> Result<radix_Radix, JsValue> {904 let m = hand::u64_from_js(&m)?;905 let code = hand::u128_from_js(&code)?;906 let value = mrlyrs::num::radix::tile(m, code).map_err(hand::throw)?;907 Ok(radix_Radix { inner: value })908}909910/// Returns the twindragon as a radix design: base `1 + i` on the square lattice, the full residue system, code `3`.911#[wasm_bindgen]912pub fn radix_twindragon() -> Result<radix_Radix, JsValue> {913 let value = mrlyrs::num::radix::twindragon().map_err(hand::throw)?;914 Ok(radix_Radix { inner: value })915}916917/// Returns the Basel sum of the reciprocal squares over n terms, walking to pi squared over six.918#[wasm_bindgen]919pub fn series_basel(n: usize) -> Result<f64, JsValue> {920 let value = mrlyrs::num::series::basel(n);921 Ok(value)922}923924/// Builds the first Bernoulli numbers as exact reduced fractions on the minus one half convention.925#[wasm_bindgen]926pub fn series_bernoulli(count: usize) -> Result<JsValue, JsValue> {927 let value = mrlyrs::num::series::bernoulli(count).map_err(hand::throw)?;928 hand::list_to_js(&value, |x1| Ok(hand::tuple_to_js(&[JsValue::from_str(&x1.0.to_string()), JsValue::from_str(&x1.1.to_string())])))929}930931/// Returns the Dirichlet beta value, the alternating odd-denominator sum averaged over its last two partial sums.932#[wasm_bindgen]933pub fn series_beta(s: f64, terms: usize) -> Result<f64, JsValue> {934 let value = mrlyrs::num::series::beta(s, terms);935 Ok(value)936}937938/// Returns the powers of two up to the limit.939#[wasm_bindgen]940pub fn series_binary(limit: usize) -> Result<Vec<usize>, JsValue> {941 let value = mrlyrs::num::series::binary(limit);942 Ok(value)943}944945/// Returns the distinct Catalan numbers up to the limit.946#[wasm_bindgen]947pub fn series_catalan(limit: usize) -> Result<Vec<usize>, JsValue> {948 let value = mrlyrs::num::series::catalan(limit);949 Ok(value)950}951952/// Returns the mod-three rhythm of the number: zero, one, minus one.953#[wasm_bindgen]954pub fn series_chi3(number: usize) -> Result<i8, JsValue> {955 let value = mrlyrs::num::series::chi3(number);956 Ok(value)957}958959/// Returns the mod-four rhythm of the number: zero, one, zero, minus one.960#[wasm_bindgen]961pub fn series_chi4(number: usize) -> Result<i8, JsValue> {962 let value = mrlyrs::num::series::chi4(number);963 Ok(value)964}965966/// Returns the mod-eight rhythm of the number, the discriminant minus-eight character: one on one and three, minus one on five and seven, zero on the evens.967#[wasm_bindgen]968pub fn series_chi8(number: usize) -> Result<i8, JsValue> {969 let value = mrlyrs::num::series::chi8(number);970 Ok(value)971}972973/// Returns the L-series partial sum with a periodic rhythm painted on the terms.974#[wasm_bindgen]975pub fn series_dirichlet(s: f64, rhythm: &[i8], terms: usize) -> Result<f64, JsValue> {976 let value = mrlyrs::num::series::dirichlet(s, rhythm, terms);977 Ok(value)978}979980/// Returns one plus one over n raised to the n, walking to the natural base.981#[wasm_bindgen]982pub fn series_e_partial(n: usize) -> Result<f64, JsValue> {983 let value = mrlyrs::num::series::e_partial(n);984 Ok(value)985}986987/// Returns the harmonic sum of n terms less the logarithm of n, walking to the Euler-Mascheroni constant.988#[wasm_bindgen]989pub fn series_euler_gamma_partial(n: usize) -> Result<f64, JsValue> {990 let value = mrlyrs::num::series::euler_gamma_partial(n);991 Ok(value)992}993994/// Returns the Euler product of zeta, one over one minus p to the minus s over the primes up to the limit.995#[wasm_bindgen]996pub fn series_euler_product(s: f64, limit: usize) -> Result<f64, JsValue> {997 let value = mrlyrs::num::series::euler_product(s, limit);998 Ok(value)999}10001001/// Returns the even numbers up to the limit.1002#[wasm_bindgen]1003pub fn series_evens(limit: usize) -> Result<Vec<usize>, JsValue> {1004 let value = mrlyrs::num::series::evens(limit);1005 Ok(value)1006}10071008/// Returns the distinct Fibonacci numbers up to the limit.1009#[wasm_bindgen]1010pub fn series_fibonacci(limit: usize) -> Result<Vec<usize>, JsValue> {1011 let value = mrlyrs::num::series::fibonacci(limit);1012 Ok(value)1013}10141015/// Returns the partial harmonic sum, the reciprocals of one through the term count.1016#[wasm_bindgen]1017pub fn series_harmonic(terms: usize) -> Result<f64, JsValue> {1018 let value = mrlyrs::num::series::harmonic(terms);1019 Ok(value)1020}10211022/// Returns the Dirichlet lambda value, one minus two to the minus s times zeta.1023#[wasm_bindgen]1024pub fn series_lambda(s: f64, terms: usize) -> Result<f64, JsValue> {1025 let value = mrlyrs::num::series::lambda(s, terms).map_err(hand::throw)?;1026 Ok(value)1027}10281029/// Returns the Leibniz alternating sum of the odd reciprocals over n terms, walking to pi over four.1030#[wasm_bindgen]1031pub fn series_leibniz(n: usize) -> Result<f64, JsValue> {1032 let value = mrlyrs::num::series::leibniz(n);1033 Ok(value)1034}10351036/// Returns the logarithmic integral of a positive x by the Ramanujan series, the smooth count of the primes below x.1037#[wasm_bindgen]1038pub fn series_li(x: f64) -> Result<f64, JsValue> {1039 let value = mrlyrs::num::series::li(x);1040 Ok(value)1041}10421043/// Returns the Mertens function at n, the Mobius values of one through n summed.1044#[wasm_bindgen]1045pub fn series_mertens(n: usize) -> Result<i64, JsValue> {1046 let value = mrlyrs::num::series::mertens(n);1047 Ok(value)1048}10491050/// Returns the odd numbers up to the limit.1051#[wasm_bindgen]1052pub fn series_odds(limit: usize) -> Result<Vec<usize>, JsValue> {1053 let value = mrlyrs::num::series::odds(limit);1054 Ok(value)1055}10561057/// Counts the lattice points of the dimension-cube of the limit whose coordinates share no divisor, by Mobius inversion.1058#[wasm_bindgen]1059pub fn series_visible(limit: usize, dimension: u32) -> Result<JsValue, JsValue> {1060 let value = mrlyrs::num::series::visible(limit, dimension).map_err(hand::throw)?;1061 Ok(JsValue::from_str(&value.to_string()))1062}10631064/// Returns the Wallis product taken to n paired factors, four k squared over four k squared less one, walking to pi over two.1065#[wasm_bindgen]1066pub fn series_wallis_half_pi(n: usize) -> Result<f64, JsValue> {1067 let value = mrlyrs::num::series::wallis_half_pi(n);1068 Ok(value)1069}10701071/// Returns the Wallis product of one minus one over the odd squares taken to n factors, walking to pi over four.1072#[wasm_bindgen]1073pub fn series_wallis_quarter_pi(factors: usize) -> Result<f64, JsValue> {1074 let value = mrlyrs::num::series::wallis_quarter_pi(factors);1075 Ok(value)1076}10771078/// Returns the zeta value above one, the partial sum closed by its Euler-Maclaurin tail.1079#[wasm_bindgen]1080pub fn series_zeta(s: f64, terms: usize) -> Result<f64, JsValue> {1081 let value = mrlyrs::num::series::zeta(s, terms).map_err(hand::throw)?;1082 Ok(value)1083}10841085/// Returns the cells the word leaves, the product of its letters' fills, one punctured tile a letter.1086#[wasm_bindgen]1087pub fn sieve_cells(word: JsValue, dimension: u32) -> Result<JsValue, JsValue> {1088 let word = hand::list_from_js(&word, hand::u64_from_js)?;1089 let value = mrlyrs::num::sieve::cells(&word, dimension).map_err(hand::throw)?;1090 Ok(JsValue::from_str(&value.to_string()))1091}10921093/// Returns the box exponent the word reads at its own scale, the logarithm of its cells over the logarithm of its side, which walks up to the dimension on a schedule of distinct growing letters and stands still on any schedule that reuses its letters.1094#[wasm_bindgen]1095pub fn sieve_exponent(word: JsValue, dimension: u32) -> Result<f64, JsValue> {1096 let word = hand::list_from_js(&word, hand::u64_from_js)?;1097 let value = mrlyrs::num::sieve::exponent(&word, dimension).map_err(hand::throw)?;1098 Ok(value)1099}11001101/// Returns the constant schedule, one odd side repeated to the count of levels, whose limit set is the fixed-ratio carpet.1102#[wasm_bindgen]1103pub fn sieve_flat_word(side: JsValue, levels: usize) -> Result<Vec<u64>, JsValue> {1104 let side = hand::u64_from_js(&side)?;1105 let value = mrlyrs::num::sieve::flat_word(side, levels);1106 Ok(value)1107}11081109/// Returns the punctures the word makes, one per surviving cell at every level.1110#[wasm_bindgen]1111pub fn sieve_holes(word: JsValue, dimension: u32) -> Result<JsValue, JsValue> {1112 let word = hand::list_from_js(&word, hand::u64_from_js)?;1113 let value = mrlyrs::num::sieve::holes(&word, dimension).map_err(hand::throw)?;1114 Ok(JsValue::from_str(&value.to_string()))1115}11161117/// Returns the limit the word's schedule walks to in the given dimension, when the word names a schedule at all.1118#[wasm_bindgen]1119pub fn sieve_limit(word: JsValue, dimension: u32) -> Result<JsValue, JsValue> {1120 let word = hand::list_from_js(&word, hand::u64_from_js)?;1121 let value = mrlyrs::num::sieve::limit(&word, dimension).map_err(hand::throw)?;1122 hand::to_js(&value)1123}11241125/// Returns the classical Wallis schedule, the odd sides three, five, seven and on, to the count of levels.1126#[wasm_bindgen]1127pub fn sieve_odd_word(levels: usize) -> Result<Vec<u64>, JsValue> {1128 let value = mrlyrs::num::sieve::odd_word(levels);1129 Ok(value)1130}11311132/// Lists every puncture the word makes in the given dimension: its corner along each axis and then its side, all in units of the word's finest cell, so a level-one hole is the widest block in the list.1133#[wasm_bindgen]1134pub fn sieve_punctures(word: JsValue, dimension: u32) -> Result<Vec<u64>, JsValue> {1135 let word = hand::list_from_js(&word, hand::u64_from_js)?;1136 let value = mrlyrs::num::sieve::punctures(&word, dimension).map_err(hand::throw)?;1137 Ok(value)1138}11391140/// Builds the plane sieve the word spells as a raster: its side, then one byte a site, row by row, one where the site survives and zero where a level punched it out.1141#[wasm_bindgen]1142pub fn sieve_raster(word: JsValue) -> Result<JsValue, JsValue> {1143 let word = hand::list_from_js(&word, hand::u64_from_js)?;1144 let value = mrlyrs::num::sieve::raster(&word).map_err(hand::throw)?;1145 Ok(hand::tuple_to_js(&[hand::to_js(&value.0)?, hand::typed(&(value.1)[..])]))1146}11471148/// Returns the share of the whole the word leaves, the product of one minus the inverse of each letter's site count, exact as a product of the letters' fills.1149#[wasm_bindgen]1150pub fn sieve_ratio(word: JsValue, dimension: u32) -> Result<f64, JsValue> {1151 let word = hand::list_from_js(&word, hand::u64_from_js)?;1152 let value = mrlyrs::num::sieve::ratio(&word, dimension).map_err(hand::throw)?;1153 Ok(value)1154}11551156/// Returns the side of the word, the product of its letters' sides.1157#[wasm_bindgen]1158pub fn sieve_side(word: JsValue) -> Result<JsValue, JsValue> {1159 let word = hand::list_from_js(&word, hand::u64_from_js)?;1160 let value = mrlyrs::num::sieve::side(&word).map_err(hand::throw)?;1161 Ok(JsValue::from_str(&value.to_string()))1162}11631164/// Returns the limit of the solid Wallis sieve's surviving volume, the product of one minus n to the minus three over the odd n from three, in closed form.1165#[wasm_bindgen]1166pub fn sieve_solid_limit() -> Result<f64, JsValue> {1167 let value = mrlyrs::num::sieve::solid_limit();1168 Ok(value)1169}11701171/// Reads the quadratic a k^2 + b k + c, a at least one, over the sheet the odd side wide: every value from one through the top, its cell, the prime hits and the opening streak.1172#[wasm_bindgen]1173pub fn spiral_diagonal(lattice: JsValue, side: usize, a: JsValue, b: JsValue, c: JsValue) -> Result<JsValue, JsValue> {1174 let lattice = hand::from_js::<mrlyrs::num::spiral::Lattice>(&lattice)?;1175 let a = hand::i64_from_js(&a)?;1176 let b = hand::i64_from_js(&b)?;1177 let c = hand::i64_from_js(&c)?;1178 let value = mrlyrs::num::spiral::diagonal(lattice, side, a, b, c);1179 hand::to_js(&value)1180}11811182/// Returns the level of a number in a base, the count of its digits less one, so zero below the base and one at the base itself.1183#[wasm_bindgen]1184pub fn spiral_level_of(n: JsValue, base: JsValue) -> Result<u32, JsValue> {1185 let n = hand::u64_from_js(&n)?;1186 let base = hand::u64_from_js(&base)?;1187 let value = mrlyrs::num::spiral::level_of(n, base);1188 Ok(value)1189}11901191/// Marks every number from zero through the limit: one when marked, minus one for a Mobius value of minus one, else zero.1192#[wasm_bindgen]1193pub fn spiral_marks(mark: JsValue, limit: usize) -> Result<Vec<i8>, JsValue> {1194 let mark = hand::from_js::<mrlyrs::num::spiral::Mark>(&mark)?;1195 let value = mrlyrs::num::spiral::marks(mark, limit);1196 Ok(value)1197}11981199/// Winds one to the top on the square spiral and lays a square tile on every cell, the snail.1200#[wasm_bindgen]1201pub fn spiral_snail(base: JsValue, top: JsValue, growth: JsValue) -> Result<JsValue, JsValue> {1202 let base = hand::u64_from_js(&base)?;1203 let top = hand::u64_from_js(&top)?;1204 let growth = hand::from_js::<mrlyrs::num::spiral::Growth>(&growth)?;1205 let value = mrlyrs::num::spiral::snail(base, top, growth);1206 hand::to_js(&value)1207}12081209/// The smooth window on [1, 2]: exp(4 - 1/((u - 1)(2 - u))) inside, zero outside, every derivative vanishing at the ends and a peak of one at u = 3/2.1210#[wasm_bindgen]1211pub fn zeta_bump(u: f64) -> Result<f64, JsValue> {1212 let value = mrlyrs::num::zeta::bump(u);1213 Ok(value)1214}12151216/// Returns the first four Riemann-Siegel corrections at the fractional part p: the kernel and its derivatives by central differences with one Richardson step.1217#[wasm_bindgen]1218pub fn zeta_corrections(p: f64) -> Result<Vec<f64>, JsValue> {1219 let value = mrlyrs::num::zeta::corrections(p);1220 Ok(value.to_vec())1221}12221223/// Returns the Riemann-Siegel kernel, the cosine ratio that leads the remainder, in the form that stays finite at its removable points.1224#[wasm_bindgen]1225pub fn zeta_kernel(p: f64) -> Result<f64, JsValue> {1226 let value = mrlyrs::num::zeta::kernel(p);1227 Ok(value)1228}12291230/// Returns the Mellin transform of the bump at a complex s, the integral of bump(u) u^(s - 1) over [1, 2], by a 4096-node midpoint rule.1231#[wasm_bindgen]1232pub fn zeta_mellin(s: &zeta_Complex) -> Result<zeta_Complex, JsValue> {1233 let value = mrlyrs::num::zeta::mellin(s.inner);1234 Ok(zeta_Complex { inner: value })1235}12361237/// Returns the main term of the smoothed novelty: six over pi squared times the bump's transform at two.1238#[wasm_bindgen]1239pub fn zeta_novelty_main() -> Result<f64, JsValue> {1240 let value = mrlyrs::num::zeta::novelty_main();1241 Ok(value)1242}12431244/// Sums the waves of the zeros at log y: twice the real part of the coefficients times y to the minus i gamma, the smoothed error over y to the three halves that the zeros predict.1245#[wasm_bindgen]1246pub fn zeta_novelty_wave(gammas: &[f64], coef: JsValue, log_y: f64) -> Result<f64, JsValue> {1247 let coef = hand::list_from_js(&coef, |x1| hand::from_js::<mrlyrs::num::zeta::Complex>(&hand::plain(x1)?))?;1248 let value = mrlyrs::num::zeta::novelty_wave(gammas, &coef, log_y);1249 Ok(value)1250}12511252/// Returns the von Mangoldt explicit formula at x over the zeros at the given ordinates and their mirrors: x less the sum of x to the rho over rho, less ln two pi, less half the ln of one minus x to the minus two.1253#[wasm_bindgen]1254pub fn zeta_psi_formula(x: f64, gammas: &[f64]) -> Result<f64, JsValue> {1255 let value = mrlyrs::num::zeta::psi_formula(x, gammas);1256 Ok(value)1257}12581259/// Returns the Chebyshev staircase at every whole number from one to x: the sum of ln p over the prime powers up to each.1260#[wasm_bindgen]1261pub fn zeta_psi_stair(x: usize) -> Result<Vec<f64>, JsValue> {1262 let value = mrlyrs::num::zeta::psi_stair(x);1263 Ok(value)1264}12651266/// Returns a positive real base raised to a complex exponent.1267#[wasm_bindgen]1268pub fn zeta_raise(base: f64, exponent: &zeta_Complex) -> Result<zeta_Complex, JsValue> {1269 let value = mrlyrs::num::zeta::raise(base, exponent.inner);1270 Ok(zeta_Complex { inner: value })1271}12721273/// Returns the sharp novelty error at y: y squared times the totient sum over the scales from 1 over y to 2 over y, both ends in, less nine over pi squared, from the prefix sums of the totients, which must reach 2 over y.1274#[wasm_bindgen]1275pub fn zeta_sharp_novelty(prefix: JsValue, y: f64) -> Result<f64, JsValue> {1276 let prefix = hand::list_from_js(&prefix, hand::u64_from_js)?;1277 let value = mrlyrs::num::zeta::sharp_novelty(&prefix, y);1278 Ok(value)1279}12801281/// Returns the smoothed novelty error at y: y squared times the totients weighed by the bump at n y, less the main term given; the totients must reach 2 over y.1282#[wasm_bindgen]1283pub fn zeta_smoothed_novelty(phi: JsValue, y: f64, main: f64) -> Result<f64, JsValue> {1284 let phi = hand::list_from_js(&phi, hand::u64_from_js)?;1285 let value = mrlyrs::num::zeta::smoothed_novelty(&phi, y, main);1286 Ok(value)1287}12881289/// The most circles one growth makes before it gives up.1290#[wasm_bindgen]1291pub fn apollonian_CIRCLE_CAP() -> Result<usize, JsValue> {1292 let value = mrlyrs::num::apollonian::CIRCLE_CAP;1293 Ok(value)1294}12951296/// The largest curvature a packing is grown to.1297#[wasm_bindgen]1298pub fn apollonian_CURVATURE_CAP() -> Result<i64, JsValue> {1299 let value = mrlyrs::num::apollonian::CURVATURE_CAP;1300 Ok(value)1301}13021303/// The deepest the Farey stack is read against a packing.1304#[wasm_bindgen]1305pub fn apollonian_ORDER_CAP() -> Result<usize, JsValue> {1306 let value = mrlyrs::num::apollonian::ORDER_CAP;1307 Ok(value)1308}13091310/// The root quadruples on offer: the strip first, then the bounded packings named by their curvatures.1311#[wasm_bindgen]1312pub fn apollonian_ROOTS() -> Result<JsValue, JsValue> {1313 let value = mrlyrs::num::apollonian::ROOTS;1314 hand::to_js(&value)1315}13161317/// The relative rounding allowance the double-precision matrix ladder charges against the scale it carries.1318#[wasm_bindgen]1319pub fn automaton_ROUNDING() -> Result<f64, JsValue> {1320 let value = mrlyrs::num::automaton::ROUNDING;1321 Ok(value)1322}13231324/// The ordinates of the first fourteen nontrivial zeros of the Riemann zeta function, the imaginary parts of the zeros on the critical line in ascending order.1325#[wasm_bindgen]1326pub fn design_ZETA_ORDINATES() -> Result<Vec<f64>, JsValue> {1327 let value = mrlyrs::num::design::ZETA_ORDINATES;1328 Ok(value.to_vec())1329}13301331/// The relative rounding allowance the double-precision ladder charges against the scale it carries.1332#[wasm_bindgen]1333pub fn ladder_ROUNDING() -> Result<f64, JsValue> {1334 let value = mrlyrs::num::ladder::ROUNDING;1335 Ok(value)1336}13371338/// The largest digit span a rule may read, so its code fits a `u64`.1339#[wasm_bindgen]1340pub fn memory_SPAN() -> Result<usize, JsValue> {1341 let value = mrlyrs::num::memory::SPAN;1342 Ok(value)1343}13441345/// The sweep cap of the power iteration.1346#[wasm_bindgen]1347pub fn memory_SWEEPS() -> Result<usize, JsValue> {1348 let value = mrlyrs::num::memory::SWEEPS;1349 Ok(value)1350}13511352/// The absolute `l^1` move of the normalised iterate that stops the power iteration, counted only when it holds over three consecutive sweeps.1353#[wasm_bindgen]1354pub fn memory_TOLERANCE() -> Result<f64, JsValue> {1355 let value = mrlyrs::num::memory::TOLERANCE;1356 Ok(value)1357}13581359/// Lists the lifts in the order the gallery draws them.1360#[wasm_bindgen]1361pub fn morse_LIFTS() -> Result<JsValue, JsValue> {1362 let value = mrlyrs::num::morse::LIFTS;1363 hand::to_js(&value)1364}13651366/// The Apery constant, the value zeta takes at three.1367#[wasm_bindgen]1368pub fn series_APERY() -> Result<f64, JsValue> {1369 let value = mrlyrs::num::series::APERY;1370 Ok(value)1371}13721373/// The Basel constant, pi squared over six, the value zeta takes at two.1374#[wasm_bindgen]1375pub fn series_BASEL() -> Result<f64, JsValue> {1376 let value = mrlyrs::num::series::BASEL;1377 Ok(value)1378}13791380/// The Catalan constant, the value the Dirichlet beta function takes at two.1381#[wasm_bindgen]1382pub fn series_CATALAN() -> Result<f64, JsValue> {1383 let value = mrlyrs::num::series::CATALAN;1384 Ok(value)1385}13861387/// The Euler constant, the limit of the harmonic sum less the logarithm.1388#[wasm_bindgen]1389pub fn series_EULER() -> Result<f64, JsValue> {1390 let value = mrlyrs::num::series::EULER;1391 Ok(value)1392}13931394/// The visible density, six over pi squared, the share of lattice pairs that are coprime.1395#[wasm_bindgen]1396pub fn series_VISIBLE() -> Result<f64, JsValue> {1397 let value = mrlyrs::num::series::VISIBLE;1398 Ok(value)1399}14001401/// The limit of the plane Wallis sieve's surviving area, pi over four.1402#[wasm_bindgen]1403pub fn sieve_PLANE_LIMIT() -> Result<f64, JsValue> {1404 let value = mrlyrs::num::sieve::PLANE_LIMIT;1405 Ok(value)1406}14071408/// The t where the walk hands over from Euler-Maclaurin to Riemann-Siegel.1409#[wasm_bindgen]1410pub fn zeta_JOIN() -> Result<f64, JsValue> {1411 let value = mrlyrs::num::zeta::JOIN;1412 Ok(value)1413}14141415/// A circle in the integer coordinates `(k, k x, k y)`: a line is `k = 0` with `(k x, k y)` its outward unit normal, and the curvature is negative on the circle that contains a bounded packing.1416#[wasm_bindgen]1417pub struct apollonian_Circle {1418 inner: mrlyrs::num::apollonian::Circle,1419}14201421#[wasm_bindgen]1422impl apollonian_Circle {1423 /// Reads the Circle from its plain data.1424 #[wasm_bindgen(js_name = "from")]1425 pub fn from_plain(data: JsValue) -> Result<apollonian_Circle, JsValue> {1426 Ok(apollonian_Circle { inner: hand::from_js(&data)? })1427 }1428 /// Writes the Circle as plain data.1429 #[wasm_bindgen(js_name = "toJSON")]1430 pub fn to_plain(&self) -> Result<JsValue, JsValue> {1431 hand::to_js(&self.inner)1432 }1433 /// The curvature.1434 #[wasm_bindgen(getter)]1435 pub fn k(&self) -> Result<i64, JsValue> {1436 let value = self.inner.k;1437 Ok(value)1438 }1439 #[wasm_bindgen(setter)]1440 pub fn set_k(&mut self, value: JsValue) -> Result<(), JsValue> {1441 let value = hand::i64_from_js(&value)?;1442 self.inner.k = value;1443 Ok(())1444 }1445 /// The curvature times the centre's abscissa.1446 #[wasm_bindgen(getter)]1447 pub fn x(&self) -> Result<i64, JsValue> {1448 let value = self.inner.x;1449 Ok(value)1450 }1451 #[wasm_bindgen(setter)]1452 pub fn set_x(&mut self, value: JsValue) -> Result<(), JsValue> {1453 let value = hand::i64_from_js(&value)?;1454 self.inner.x = value;1455 Ok(())1456 }1457 /// The curvature times the centre's ordinate.1458 #[wasm_bindgen(getter)]1459 pub fn y(&self) -> Result<i64, JsValue> {1460 let value = self.inner.y;1461 Ok(value)1462 }1463 #[wasm_bindgen(setter)]1464 pub fn set_y(&mut self, value: JsValue) -> Result<(), JsValue> {1465 let value = hand::i64_from_js(&value)?;1466 self.inner.y = value;1467 Ok(())1468 }1469 /// The centre, none on a line.1470 pub fn centre(&self) -> Result<JsValue, JsValue> {1471 let value = self.inner.centre();1472 hand::to_js(&value)1473 }1474 /// Whether the circle is a line.1475 pub fn is_line(&self) -> Result<bool, JsValue> {1476 let value = self.inner.is_line();1477 Ok(value)1478 }1479 /// The radius, none on a line.1480 pub fn radius(&self) -> Result<JsValue, JsValue> {1481 let value = self.inner.radius();1482 hand::to_js(&value)1483 }1484}14851486/// A memory design read as a matrix ladder: the rule, the transfer matrix on its `(k-1)`-window states, and the peel depth its Dirichlet series is continued from.1487#[wasm_bindgen]1488pub struct automaton_Automaton {1489 inner: mrlyrs::num::automaton::Automaton,1490}14911492#[wasm_bindgen]1493impl automaton_Automaton {1494 /// Reads the Automaton from its plain data.1495 #[wasm_bindgen(js_name = "from")]1496 pub fn from_plain(data: JsValue) -> Result<automaton_Automaton, JsValue> {1497 Ok(automaton_Automaton { inner: hand::from_js(&data)? })1498 }1499 /// Writes the Automaton as plain data.1500 #[wasm_bindgen(js_name = "toJSON")]1501 pub fn to_plain(&self) -> Result<JsValue, JsValue> {1502 hand::to_js(&self.inner)1503 }1504 /// Returns the abscissa `alpha = log_q rho`, with `rho` the exact Perron root of [`crate::num::memory::perron`].1505 pub fn abscissa(&self) -> Result<f64, JsValue> {1506 let value = self.inner.abscissa();1507 Ok(value)1508 }1509 /// Returns the base `q = 2^D`.1510 pub fn base(&self) -> Result<u64, JsValue> {1511 let value = self.inner.base();1512 Ok(value)1513 }1514 /// Returns the matrix Lyndon cofactor `Z_W(s) = det(I - q^(-s) T) zeta_W(s)` and the bound it is known to.1515 pub fn cofactor(&self, s: &zeta_Complex, tolerance: f64) -> Result<JsValue, JsValue> {1516 let value = self.inner.cofactor(s.inner, tolerance).map_err(hand::throw)?;1517 Ok(hand::tuple_to_js(&[JsValue::from(zeta_Complex { inner: value.0 }), hand::to_js(&value.1)?]))1518 }1519 /// Returns the coefficients `c_0 .. c_n` of `det(I - x T) = sum c_i x^i`, the ladder denominator read as a polynomial in `x = q^(-s)`.1520 pub fn denominator(&self) -> Result<Vec<f64>, JsValue> {1521 let value = self.inner.denominator();1522 Ok(value)1523 }1524 /// Returns the transfer matrix `T = Gamma_0` the ladder runs on, the transpose of [`crate::num::memory::transfer`], entry `(u', u)` counting the letters carrying `u` to `u'`.1525 pub fn matrix(&self) -> Result<JsValue, JsValue> {1526 let value = self.inner.matrix();1527 hand::list_to_js(&value, |x1| Ok(hand::typed(&(*x1)[..])))1528 }1529 /// Builds the ladder of a rule, choosing the peel depth.1530 #[wasm_bindgen(constructor)]1531 pub fn new(rule: &memory_Rule) -> Result<automaton_Automaton, JsValue> {1532 let value = mrlyrs::num::automaton::Automaton::new(&rule.inner).map_err(hand::throw)?;1533 Ok(automaton_Automaton { inner: value })1534 }1535 /// Returns the peel depth `P`.1536 pub fn peel(&self) -> Result<usize, JsValue> {1537 let value = self.inner.peel();1538 Ok(value)1539 }1540 /// Returns the pole spacing `2 pi / log q`.1541 pub fn period(&self) -> Result<f64, JsValue> {1542 let value = self.inner.period();1543 Ok(value)1544 }1545 /// Returns the Collatz-Wielandt bracket `(low, high)` of the Perron root of the transfer matrix, the ratios the ladder divides with.1546 pub fn perron(&self) -> Result<JsValue, JsValue> {1547 let value = self.inner.perron();1548 hand::to_js(&value)1549 }1550 /// Returns the residue of `zeta_W` at a simple pole `w0` of the resolvent and the bound it is known to.1551 pub fn residue(&self, w0: &zeta_Complex, tolerance: f64) -> Result<JsValue, JsValue> {1552 let value = self.inner.residue(w0.inner, tolerance).map_err(hand::throw)?;1553 Ok(hand::tuple_to_js(&[JsValue::from(zeta_Complex { inner: value.0 }), hand::to_js(&value.1)?]))1554 }1555 /// Returns the rule.1556 pub fn rule(&self) -> Result<memory_Rule, JsValue> {1557 let value = self.inner.rule();1558 Ok(memory_Rule { inner: value })1559 }1560 /// Returns the state count `q^(k-1)`.1561 pub fn states(&self) -> Result<usize, JsValue> {1562 let value = self.inner.states();1563 Ok(value)1564 }1565 /// Builds the ladder at an explicit peel depth, at least the rule width and at least two.1566 pub fn with_peel(rule: &memory_Rule, peel: usize) -> Result<automaton_Automaton, JsValue> {1567 let value = mrlyrs::num::automaton::Automaton::with_peel(&rule.inner, peel).map_err(hand::throw)?;1568 Ok(automaton_Automaton { inner: value })1569 }1570 /// Returns `zeta_W(s)` and the bound it is known to.1571 pub fn zeta(&self, s: &zeta_Complex, tolerance: f64) -> Result<JsValue, JsValue> {1572 let value = self.inner.zeta(s.inner, tolerance).map_err(hand::throw)?;1573 Ok(hand::tuple_to_js(&[JsValue::from(zeta_Complex { inner: value.0 }), hand::to_js(&value.1)?]))1574 }1575}15761577/// The symmetric window of one ring: every point within a reach, with the norms sieved once.1578#[wasm_bindgen]1579pub struct gauss_Window {1580 inner: mrlyrs::num::gauss::Window,1581}15821583#[wasm_bindgen]1584impl gauss_Window {1585 /// Reads the Window from its plain data.1586 #[wasm_bindgen(js_name = "from")]1587 pub fn from_plain(data: JsValue) -> Result<gauss_Window, JsValue> {1588 Ok(gauss_Window { inner: hand::from_js(&data)? })1589 }1590 /// Writes the Window as plain data.1591 #[wasm_bindgen(js_name = "toJSON")]1592 pub fn to_plain(&self) -> Result<JsValue, JsValue> {1593 hand::to_js(&self.inner)1594 }1595 /// Counts every class inside.1596 pub fn census(&self) -> Result<JsValue, JsValue> {1597 let value = self.inner.census();1598 hand::to_js(&value)1599 }1600 /// Classifies a point: prime when its norm is a rational prime, or when it is a unit times a rational prime that stays prime.1601 pub fn class(&self, a: JsValue, b: JsValue) -> Result<JsValue, JsValue> {1602 let a = hand::i64_from_js(&a)?;1603 let b = hand::i64_from_js(&b)?;1604 let value = self.inner.class(a, b);1605 hand::to_js(&value)1606 }1607 /// Returns whether a point lies inside.1608 pub fn holds(&self, a: JsValue, b: JsValue) -> Result<bool, JsValue> {1609 let a = hand::i64_from_js(&a)?;1610 let b = hand::i64_from_js(&b)?;1611 let value = self.inner.holds(a, b);1612 Ok(value)1613 }1614 /// Opens the window of a ring out to a reach, sieving every norm inside it.1615 #[wasm_bindgen(constructor)]1616 pub fn new(ring: JsValue, radius: JsValue) -> Result<gauss_Window, JsValue> {1617 let ring = hand::from_js::<mrlyrs::num::gauss::Ring>(&ring)?;1618 let radius = hand::u64_from_js(&radius)?;1619 let value = mrlyrs::num::gauss::Window::new(ring, radius);1620 Ok(gauss_Window { inner: value })1621 }1622 /// Lists every point inside, row by row from the bottom left of the bounding square.1623 pub fn points(&self) -> Result<JsValue, JsValue> {1624 let value = self.inner.points();1625 hand::list_to_js(&value, |x1| Ok(hand::tuple_to_js(&[JsValue::from(x1.0), JsValue::from(x1.1)])))1626 }1627 /// Returns the reach.1628 pub fn radius(&self) -> Result<u64, JsValue> {1629 let value = self.inner.radius();1630 Ok(value)1631 }1632 /// Returns the ring.1633 pub fn ring(&self) -> Result<JsValue, JsValue> {1634 let value = self.inner.ring();1635 hand::to_js(&value)1636 }1637}16381639/// A digit design: the base `q`, the digit set `F` its elements are written with, and the peel depth `P` its ladder starts at.1640#[wasm_bindgen]1641pub struct ladder_Design {1642 inner: mrlyrs::num::ladder::Design,1643}16441645#[wasm_bindgen]1646impl ladder_Design {1647 /// Reads the Design from its plain data.1648 #[wasm_bindgen(js_name = "from")]1649 pub fn from_plain(data: JsValue) -> Result<ladder_Design, JsValue> {1650 Ok(ladder_Design { inner: hand::from_js(&data)? })1651 }1652 /// Writes the Design as plain data.1653 #[wasm_bindgen(js_name = "toJSON")]1654 pub fn to_plain(&self) -> Result<JsValue, JsValue> {1655 hand::to_js(&self.inner)1656 }1657 /// Returns the abscissa `alpha = log_q k`.1658 pub fn abscissa(&self) -> Result<f64, JsValue> {1659 let value = self.inner.abscissa();1660 Ok(value)1661 }1662 /// Returns the base.1663 pub fn base(&self) -> Result<u64, JsValue> {1664 let value = self.inner.base();1665 Ok(value)1666 }1667 /// Returns the digit set, ascending.1668 pub fn digits(&self) -> Result<Vec<u64>, JsValue> {1669 let value = self.inner.digits();1670 Ok(value.to_vec())1671 }1672 /// Builds a design on the base and the digit set, choosing the peel depth.1673 #[wasm_bindgen(constructor)]1674 pub fn new(base: JsValue, digits: JsValue) -> Result<ladder_Design, JsValue> {1675 let base = hand::u64_from_js(&base)?;1676 let digits = hand::list_from_js(&digits, hand::u64_from_js)?;1677 let value = mrlyrs::num::ladder::Design::new(base, &digits).map_err(hand::throw)?;1678 Ok(ladder_Design { inner: value })1679 }1680 /// Returns the peel depth.1681 pub fn peel(&self) -> Result<usize, JsValue> {1682 let value = self.inner.peel();1683 Ok(value)1684 }1685 /// Returns the pole spacing `2 pi / log q`.1686 pub fn period(&self) -> Result<f64, JsValue> {1687 let value = self.inner.period();1688 Ok(value)1689 }1690 /// Returns the pole `s_(m,j) = alpha - m + 2 pi i j / log q`.1691 pub fn pole(&self, m: usize, j: JsValue) -> Result<zeta_Complex, JsValue> {1692 let j = hand::i64_from_js(&j)?;1693 let value = self.inner.pole(m, j);1694 Ok(zeta_Complex { inner: value })1695 }1696 /// Builds a design at an explicit peel depth, at least two.1697 pub fn with_peel(base: JsValue, digits: JsValue, peel: usize) -> Result<ladder_Design, JsValue> {1698 let base = hand::u64_from_js(&base)?;1699 let digits = hand::list_from_js(&digits, hand::u64_from_js)?;1700 let value = mrlyrs::num::ladder::Design::with_peel(base, &digits, peel).map_err(hand::throw)?;1701 Ok(ladder_Design { inner: value })1702 }1703}17041705/// A rule on `k` consecutive digits of a design word.1706#[wasm_bindgen]1707pub struct memory_Rule {1708 inner: mrlyrs::num::memory::Rule,1709}17101711#[wasm_bindgen]1712impl memory_Rule {1713 /// Reads the Rule from its plain data.1714 #[wasm_bindgen(js_name = "from")]1715 pub fn from_plain(data: JsValue) -> Result<memory_Rule, JsValue> {1716 Ok(memory_Rule { inner: hand::from_js(&data)? })1717 }1718 /// Writes the Rule as plain data.1719 #[wasm_bindgen(js_name = "toJSON")]1720 pub fn to_plain(&self) -> Result<JsValue, JsValue> {1721 hand::to_js(&self.inner)1722 }1723 /// The dimension `D`, one to three.1724 #[wasm_bindgen(getter)]1725 pub fn dimension(&self) -> Result<usize, JsValue> {1726 let value = self.inner.dimension;1727 Ok(value)1728 }1729 #[wasm_bindgen(setter)]1730 pub fn set_dimension(&mut self, value: usize) -> Result<(), JsValue> {1731 self.inner.dimension = value;1732 Ok(())1733 }1734 /// The window width `k`, at least one.1735 #[wasm_bindgen(getter)]1736 pub fn width(&self) -> Result<usize, JsValue> {1737 let value = self.inner.width;1738 Ok(value)1739 }1740 #[wasm_bindgen(setter)]1741 pub fn set_width(&mut self, value: usize) -> Result<(), JsValue> {1742 self.inner.width = value;1743 Ok(())1744 }1745 /// The window code, bit `w` set when window `w` is allowed.1746 #[wasm_bindgen(getter)]1747 pub fn code(&self) -> Result<u64, JsValue> {1748 let value = self.inner.code;1749 Ok(value)1750 }1751 #[wasm_bindgen(setter)]1752 pub fn set_code(&mut self, value: JsValue) -> Result<(), JsValue> {1753 let value = hand::u64_from_js(&value)?;1754 self.inner.code = value;1755 Ok(())1756 }1757 /// Returns whether a word, coarsest digit first, is accepted.1758 pub fn accepts(&self, word: &[usize]) -> Result<bool, JsValue> {1759 let value = self.inner.accepts(word);1760 Ok(value)1761 }1762 /// Returns whether the window is allowed, and false for any window out of range.1763 pub fn allowed(&self, window: usize) -> Result<bool, JsValue> {1764 let value = self.inner.allowed(window);1765 Ok(value)1766 }1767 /// Returns the letters that stand in at least one allowed window.1768 pub fn alphabet(&self) -> Result<Vec<usize>, JsValue> {1769 let value = self.inner.alphabet();1770 Ok(value)1771 }1772 /// Returns the count of rules of this shape, `2^(2^(k D))`.1773 pub fn codes(&self) -> Result<JsValue, JsValue> {1774 let value = self.inner.codes();1775 Ok(JsValue::from_str(&value.to_string()))1776 }1777 /// Returns the rule that allows every window.1778 pub fn full(dimension: usize, width: usize) -> Result<memory_Rule, JsValue> {1779 let value = mrlyrs::num::memory::Rule::full(dimension, width).map_err(hand::throw)?;1780 Ok(memory_Rule { inner: value })1781 }1782 /// Returns the letter count `2^D`, the digit vectors of the cube's corners.1783 pub fn letters(&self) -> Result<usize, JsValue> {1784 let value = self.inner.letters();1785 Ok(value)1786 }1787 /// Builds a rule from its dimension, its width and its code.1788 #[wasm_bindgen(constructor)]1789 pub fn new(dimension: usize, width: usize, code: JsValue) -> Result<memory_Rule, JsValue> {1790 let code = hand::u64_from_js(&code)?;1791 let value = mrlyrs::num::memory::Rule::new(dimension, width, code).map_err(hand::throw)?;1792 Ok(memory_Rule { inner: value })1793 }1794 /// Returns the state count `2^((k - 1) D)`, the windows of one digit less that the transfer matrix runs on.1795 pub fn states(&self) -> Result<usize, JsValue> {1796 let value = self.inner.states();1797 Ok(value)1798 }1799 /// Returns the window count `2^(k D)`.1800 pub fn windows(&self) -> Result<usize, JsValue> {1801 let value = self.inner.windows();1802 Ok(value)1803 }1804}18051806/// The sieve of Eratosthenes taken one prime at a time, each number remembering which prime struck it.1807#[wasm_bindgen]1808pub struct prime_Sieve {1809 inner: mrlyrs::num::prime::Sieve,1810}18111812#[wasm_bindgen]1813impl prime_Sieve {1814 /// Reads the Sieve from its plain data.1815 #[wasm_bindgen(js_name = "from")]1816 pub fn from_plain(data: JsValue) -> Result<prime_Sieve, JsValue> {1817 Ok(prime_Sieve { inner: hand::from_js(&data)? })1818 }1819 /// Writes the Sieve as plain data.1820 #[wasm_bindgen(js_name = "toJSON")]1821 pub fn to_plain(&self) -> Result<JsValue, JsValue> {1822 hand::to_js(&self.inner)1823 }1824 /// Returns the count of numbers marked prime so far.1825 pub fn count(&self) -> Result<usize, JsValue> {1826 let value = self.inner.count();1827 Ok(value)1828 }1829 /// Returns whether every number is settled.1830 pub fn done(&self) -> Result<bool, JsValue> {1831 let value = self.inner.done();1832 Ok(value)1833 }1834 /// Runs the sieve to the end.1835 pub fn finish(&mut self) -> Result<(), JsValue> {1836 self.inner.finish();1837 Ok(())1838 }1839 /// Starts a sieve over zero through the limit with every number untouched; it is done at once when no prime has its square inside.1840 #[wasm_bindgen(constructor)]1841 pub fn new(limit: usize) -> Result<prime_Sieve, JsValue> {1842 let value = mrlyrs::num::prime::Sieve::new(limit);1843 Ok(prime_Sieve { inner: value })1844 }1845 /// Returns the count of primes used so far.1846 pub fn rank(&self) -> Result<usize, JsValue> {1847 let value = self.inner.rank();1848 Ok(value)1849 }1850 /// Uses the next prime: marks it prime, strikes its untouched multiples from its square with its rank plus one, and returns it; zero once done.1851 pub fn step(&mut self) -> Result<usize, JsValue> {1852 let value = self.inner.step();1853 Ok(value)1854 }1855 /// Returns the count of numbers the last step struck.1856 pub fn struck(&self) -> Result<usize, JsValue> {1857 let value = self.inner.struck();1858 Ok(value)1859 }1860 /// Returns the type of every number from zero: zero untouched, one prime, and one past the rank of the prime that struck it.1861 pub fn types(&self) -> Result<Vec<u8>, JsValue> {1862 let value = self.inner.types();1863 Ok(value.to_vec())1864 }1865}18661867/// The base of a radix design: a ring and an element of norm at least two, the scale every word is read against.1868#[wasm_bindgen]1869pub struct radix_Base {1870 inner: mrlyrs::num::radix::Base,1871}18721873#[wasm_bindgen]1874impl radix_Base {1875 /// Reads the Base from its plain data.1876 #[wasm_bindgen(js_name = "from")]1877 pub fn from_plain(data: JsValue) -> Result<radix_Base, JsValue> {1878 Ok(radix_Base { inner: hand::from_js(&data)? })1879 }1880 /// Writes the Base as plain data.1881 #[wasm_bindgen(js_name = "toJSON")]1882 pub fn to_plain(&self) -> Result<JsValue, JsValue> {1883 hand::to_js(&self.inner)1884 }1885 /// Returns the index in the canonical residue system of the class of a point.1886 pub fn class(&self, z: JsValue) -> Result<usize, JsValue> {1887 let z = (hand::i64_from_js(&hand::item(&z, 0)?)?, hand::i64_from_js(&hand::item(&z, 1)?)?);1888 let value = self.inner.class(z).map_err(hand::throw)?;1889 Ok(value)1890 }1891 /// Returns whether two points are congruent modulo the base.1892 pub fn congruent(&self, z: JsValue, w: JsValue) -> Result<bool, JsValue> {1893 let z = (hand::i64_from_js(&hand::item(&z, 0)?)?, hand::i64_from_js(&hand::item(&z, 1)?)?);1894 let w = (hand::i64_from_js(&hand::item(&w, 0)?)?, hand::i64_from_js(&hand::item(&w, 1)?)?);1895 let value = self.inner.congruent(z, w);1896 Ok(value)1897 }1898 /// Returns the symmetry group of the base as permutations of the canonical residue indices: every unit multiplication, and every unit times conjugation when the conjugate of the base is an associate of the base.1899 pub fn group(&self) -> Result<JsValue, JsValue> {1900 let value = self.inner.group().map_err(hand::throw)?;1901 hand::list_to_js(&value, |x1| Ok(hand::typed(&(*x1)[..])))1902 }1903 /// Returns whether the conjugate of the base is an associate of the base, which is when the mirror joins the symmetry group.1904 pub fn mirrored(&self) -> Result<bool, JsValue> {1905 let value = self.inner.mirrored();1906 Ok(value)1907 }1908 /// Fixes a base in a ring.1909 #[wasm_bindgen(constructor)]1910 pub fn new(ring: JsValue, value: JsValue) -> Result<radix_Base, JsValue> {1911 let ring = hand::from_js::<mrlyrs::num::gauss::Ring>(&ring)?;1912 let value = (hand::i64_from_js(&hand::item(&value, 0)?)?, hand::i64_from_js(&hand::item(&value, 1)?)?);1913 let value = mrlyrs::num::radix::Base::new(ring, value).map_err(hand::throw)?;1914 Ok(radix_Base { inner: value })1915 }1916 /// Returns the norm `q` of the base: the count of residue classes and the square of the scale.1917 pub fn norm(&self) -> Result<u64, JsValue> {1918 let value = self.inner.norm();1919 Ok(value)1920 }1921 /// Returns the base raised to a level.1922 pub fn power(&self, level: usize) -> Result<JsValue, JsValue> {1923 let value = self.inner.power(level);1924 Ok(hand::tuple_to_js(&[JsValue::from(value.0), JsValue::from(value.1)]))1925 }1926 /// Returns the canonical complete residue system modulo the base: the `q` representatives of least norm, ties broken by argument in `[0, 2 pi)`.1927 pub fn residues(&self) -> Result<JsValue, JsValue> {1928 let value = self.inner.residues().map_err(hand::throw)?;1929 hand::list_to_js(&value, |x1| Ok(hand::tuple_to_js(&[JsValue::from(x1.0), JsValue::from(x1.1)])))1930 }1931 /// Returns the ring.1932 pub fn ring(&self) -> Result<JsValue, JsValue> {1933 let value = self.inner.ring();1934 hand::to_js(&value)1935 }1936 /// Returns the base element.1937 pub fn value(&self) -> Result<JsValue, JsValue> {1938 let value = self.inner.value();1939 Ok(hand::tuple_to_js(&[JsValue::from(value.0), JsValue::from(value.1)]))1940 }1941}19421943/// A radix design: a digit set inside one ring, placed by a base with a unit twist per digit.1944#[wasm_bindgen]1945pub struct radix_Radix {1946 inner: mrlyrs::num::radix::Radix,1947}19481949#[wasm_bindgen]1950impl radix_Radix {1951 /// Reads the Radix from its plain data.1952 #[wasm_bindgen(js_name = "from")]1953 pub fn from_plain(data: JsValue) -> Result<radix_Radix, JsValue> {1954 Ok(radix_Radix { inner: hand::from_js(&data)? })1955 }1956 /// Writes the Radix as plain data.1957 #[wasm_bindgen(js_name = "toJSON")]1958 pub fn to_plain(&self) -> Result<JsValue, JsValue> {1959 hand::to_js(&self.inner)1960 }1961 /// Returns the base.1962 pub fn base(&self) -> Result<radix_Base, JsValue> {1963 let value = self.inner.base();1964 Ok(radix_Base { inner: value })1965 }1966 /// Returns whether every digit is the canonical representative of its class.1967 pub fn canonical(&self) -> Result<bool, JsValue> {1968 let value = self.inner.canonical().map_err(hand::throw)?;1969 Ok(value)1970 }1971 /// Returns the code of the classes the digits occupy, which names the design only when the digits are the canonical representatives.1972 pub fn code(&self) -> Result<JsValue, JsValue> {1973 let value = self.inner.code().map_err(hand::throw)?;1974 Ok(JsValue::from_str(&value.to_string()))1975 }1976 /// Returns the digits.1977 pub fn digits(&self) -> Result<JsValue, JsValue> {1978 let value = self.inner.digits();1979 hand::list_to_js(value, |x1| Ok(hand::tuple_to_js(&[JsValue::from(x1.0), JsValue::from(x1.1)])))1980 }1981 /// Returns the similarity dimension `log |F| / log sqrt(q)`, the ratio of the digit count to the scale of the base.1982 pub fn dimension(&self) -> Result<f64, JsValue> {1983 let value = self.inner.dimension();1984 Ok(value)1985 }1986 /// Returns the count of distinct level-`L` points: the glue count, which is the fill exactly when no two words name one point.1987 pub fn distinct(&self, level: usize) -> Result<usize, JsValue> {1988 let value = self.inner.distinct(level);1989 Ok(value)1990 }1991 /// Returns the count of words of a level, `|F|^L`.1992 pub fn fill(&self, level: usize) -> Result<JsValue, JsValue> {1993 let value = self.inner.fill(level);1994 Ok(JsValue::from_str(&value.to_string()))1995 }1996 /// Builds an untwisted design from a code over the canonical residue system, bit `i` of the code selecting residue `i`.1997 pub fn from_code(base: &radix_Base, code: JsValue) -> Result<radix_Radix, JsValue> {1998 let code = hand::u128_from_js(&code)?;1999 let value = mrlyrs::num::radix::Radix::from_code(base.inner, code).map_err(hand::throw)?;2000 Ok(radix_Radix { inner: value })2001 }2002 /// Builds a design from a base, a digit list and a unit twist per digit.2003 #[wasm_bindgen(constructor)]2004 pub fn new(base: &radix_Base, digits: JsValue, twists: JsValue) -> Result<radix_Radix, JsValue> {2005 let digits = hand::list_from_js(&digits, |x1| Ok((hand::i64_from_js(&hand::item(x1, 0)?)?, hand::i64_from_js(&hand::item(x1, 1)?)?)))?;2006 let twists = hand::list_from_js(&twists, |x1| Ok((hand::i64_from_js(&hand::item(x1, 0)?)?, hand::i64_from_js(&hand::item(x1, 1)?)?)))?;2007 let value = mrlyrs::num::radix::Radix::new(base.inner, digits, twists).map_err(hand::throw)?;2008 Ok(radix_Radix { inner: value })2009 }2010 /// Returns the level-`L` points in the plane, the scaled words divided by `b^L`.2011 pub fn plane(&self, level: usize) -> Result<JsValue, JsValue> {2012 let value = self.inner.plane(level);2013 hand::to_js(&value)2014 }2015 /// Returns the ring.2016 pub fn ring(&self) -> Result<JsValue, JsValue> {2017 let value = self.inner.ring();2018 hand::to_js(&value)2019 }2020 /// Returns the digit count `|F|`.2021 pub fn size(&self) -> Result<usize, JsValue> {2022 let value = self.inner.size();2023 Ok(value)2024 }2025 /// Returns the twists.2026 pub fn twists(&self) -> Result<JsValue, JsValue> {2027 let value = self.inner.twists();2028 hand::list_to_js(value, |x1| Ok(hand::tuple_to_js(&[JsValue::from(x1.0), JsValue::from(x1.1)])))2029 }2030 /// Returns the design with the twists named by their index in the unit list, the units in turning order from one.2031 pub fn with_twists(&self, units: &[usize]) -> Result<radix_Radix, JsValue> {2032 let value = self.inner.clone().with_twists(units).map_err(hand::throw)?;2033 Ok(radix_Radix { inner: value })2034 }2035 /// Returns the level-`L` points in exact ring coordinates scaled by `b^L`.2036 pub fn words(&self, level: usize) -> Result<JsValue, JsValue> {2037 let value = self.inner.words(level);2038 hand::list_to_js(&value, |x1| Ok(hand::tuple_to_js(&[JsValue::from(x1.0), JsValue::from(x1.1)])))2039 }2040}20412042/// A complex number: a real and an imaginary part.2043#[wasm_bindgen]2044pub struct zeta_Complex {2045 inner: mrlyrs::num::zeta::Complex,2046}20472048#[wasm_bindgen]2049impl zeta_Complex {2050 /// Reads the Complex from its plain data.2051 #[wasm_bindgen(js_name = "from")]2052 pub fn from_plain(data: JsValue) -> Result<zeta_Complex, JsValue> {2053 Ok(zeta_Complex { inner: hand::from_js(&data)? })2054 }2055 /// Writes the Complex as plain data.2056 #[wasm_bindgen(js_name = "toJSON")]2057 pub fn to_plain(&self) -> Result<JsValue, JsValue> {2058 hand::to_js(&self.inner)2059 }2060 /// The real part.2061 #[wasm_bindgen(getter)]2062 pub fn re(&self) -> Result<f64, JsValue> {2063 let value = self.inner.re;2064 Ok(value)2065 }2066 #[wasm_bindgen(setter)]2067 pub fn set_re(&mut self, value: f64) -> Result<(), JsValue> {2068 self.inner.re = value;2069 Ok(())2070 }2071 /// The imaginary part.2072 #[wasm_bindgen(getter)]2073 pub fn im(&self) -> Result<f64, JsValue> {2074 let value = self.inner.im;2075 Ok(value)2076 }2077 #[wasm_bindgen(setter)]2078 pub fn set_im(&mut self, value: f64) -> Result<(), JsValue> {2079 self.inner.im = value;2080 Ok(())2081 }2082 /// Returns the modulus.2083 pub fn abs(&self) -> Result<f64, JsValue> {2084 let value = self.inner.abs();2085 Ok(value)2086 }2087 /// Returns the principal argument.2088 pub fn arg(&self) -> Result<f64, JsValue> {2089 let value = self.inner.arg();2090 Ok(value)2091 }2092 /// Returns the default Complex.2093 #[wasm_bindgen(js_name = "default")]2094 pub fn default_() -> Result<zeta_Complex, JsValue> {2095 let value = mrlyrs::num::zeta::Complex::default();2096 Ok(zeta_Complex { inner: value })2097 }2098 /// Returns the exponential.2099 pub fn exp(&self) -> Result<zeta_Complex, JsValue> {2100 let value = self.inner.exp();2101 Ok(zeta_Complex { inner: value })2102 }2103 /// Returns the principal logarithm.2104 pub fn ln(&self) -> Result<zeta_Complex, JsValue> {2105 let value = self.inner.ln();2106 Ok(zeta_Complex { inner: value })2107 }2108 /// Builds a complex number from its parts.2109 #[wasm_bindgen(constructor)]2110 pub fn new(re: f64, im: f64) -> Result<zeta_Complex, JsValue> {2111 let value = mrlyrs::num::zeta::Complex::new(re, im);2112 Ok(zeta_Complex { inner: value })2113 }2114 /// Returns a unit complex number at the given angle.2115 pub fn turn(angle: f64) -> Result<zeta_Complex, JsValue> {2116 let value = mrlyrs::num::zeta::Complex::turn(angle);2117 Ok(zeta_Complex { inner: value })2118 }2119}21202121/// The critical line: the Bernoulli numbers and the Euler-Maclaurin weights the two engines share, built once.2122#[wasm_bindgen]2123pub struct zeta_Line {2124 inner: mrlyrs::num::zeta::Line,2125}21262127#[wasm_bindgen]2128impl zeta_Line {2129 /// Reads the Line from its plain data.2130 #[wasm_bindgen(js_name = "from")]2131 pub fn from_plain(data: JsValue) -> Result<zeta_Line, JsValue> {2132 Ok(zeta_Line { inner: hand::from_js(&data)? })2133 }2134 /// Writes the Line as plain data.2135 #[wasm_bindgen(js_name = "toJSON")]2136 pub fn to_plain(&self) -> Result<JsValue, JsValue> {2137 hand::to_js(&self.inner)2138 }2139 /// Counts the zeros on the line below t.2140 pub fn count(&self, t: f64) -> Result<usize, JsValue> {2141 let value = self.inner.count(t);2142 Ok(value)2143 }2144 /// Returns the default Line.2145 #[wasm_bindgen(js_name = "default")]2146 pub fn default_() -> Result<zeta_Line, JsValue> {2147 let value = mrlyrs::num::zeta::Line::default();2148 Ok(zeta_Line { inner: value })2149 }2150 /// Returns Z(t) from the Euler-Maclaurin value turned onto the real axis.2151 pub fn exact(&self, t: f64) -> Result<f64, JsValue> {2152 let value = self.inner.exact(t);2153 Ok(value)2154 }2155 /// Returns the n-th Gram point, where theta is n pi, by Newton from the right.2156 pub fn gram(&self, n: JsValue) -> Result<f64, JsValue> {2157 let n = hand::i64_from_js(&n)?;2158 let value = self.inner.gram(n);2159 Ok(value)2160 }2161 /// Returns zeta at one half plus i t by the complex Euler-Maclaurin sum: t plus ten terms and seven Bernoulli corrections.2162 pub fn maclaurin(&self, t: f64) -> Result<zeta_Complex, JsValue> {2163 let value = self.inner.maclaurin(t);2164 Ok(zeta_Complex { inner: value })2165 }2166 /// Builds the line: the even Bernoulli numbers through the fourteenth and their Euler-Maclaurin weights.2167 #[wasm_bindgen(constructor)]2168 pub fn new() -> Result<zeta_Line, JsValue> {2169 let value = mrlyrs::num::zeta::Line::new();2170 Ok(zeta_Line { inner: value })2171 }2172 /// Returns the wave coefficient of every zero at the given ordinates: F(rho) zeta(rho - 1) over zeta'(rho) at rho one half plus i gamma, F the Mellin transform of the bump.2173 pub fn novelty_coefficients(&self, gammas: &[f64]) -> Result<JsValue, JsValue> {2174 let value = self.inner.novelty_coefficients(gammas);2175 hand::list_to_js(&value, |x1| Ok(JsValue::from(zeta_Complex { inner: *x1 })))2176 }2177 /// Returns zeta and its derivative together at any complex s but one, by the same Euler-Maclaurin sum: the modulus of t plus ten terms and seven Bernoulli corrections, each term differentiated in s.2178 pub fn pair(&self, s: &zeta_Complex) -> Result<JsValue, JsValue> {2179 let value = self.inner.pair(s.inner);2180 Ok(hand::tuple_to_js(&[JsValue::from(zeta_Complex { inner: value.0 }), JsValue::from(zeta_Complex { inner: value.1 })]))2181 }2182 /// Returns zeta on the line and Z(t) together, from the engine that serves the t.2183 pub fn point(&self, t: f64) -> Result<JsValue, JsValue> {2184 let value = self.inner.point(t);2185 Ok(hand::tuple_to_js(&[JsValue::from(zeta_Complex { inner: value.0 }), hand::to_js(&value.1)?]))2186 }2187 /// Returns the largest gap between the two engines over the t range on a grid.2188 pub fn seam(&self, t0: f64, t1: f64, steps: usize) -> Result<f64, JsValue> {2189 let value = self.inner.seam(t0, t1, steps);2190 Ok(value)2191 }2192 /// Returns Z(t) by the Riemann-Siegel formula: the main sum and the first four corrections.2193 pub fn siegel(&self, t: f64) -> Result<f64, JsValue> {2194 let value = self.inner.siegel(t);2195 Ok(value)2196 }2197 /// Returns the Riemann-Siegel theta: the argument of gamma at one quarter plus i t over two, less t ln pi over two, by Stirling's series after a shift of ten.2198 pub fn theta(&self, t: f64) -> Result<f64, JsValue> {2199 let value = self.inner.theta(t);2200 Ok(value)2201 }2202 /// Returns Z(t): Euler-Maclaurin below the join, Riemann-Siegel above.2203 pub fn z(&self, t: f64) -> Result<f64, JsValue> {2204 let value = self.inner.z(t);2205 Ok(value)2206 }2207 /// Returns the first zeros on the line: sign changes of Z between Gram points, refined by bisection on Euler-Maclaurin to a billionth.2208 pub fn zeros(&self, count: usize) -> Result<Vec<f64>, JsValue> {2209 let value = self.inner.zeros(count);2210 Ok(value)2211 }2212}22132214/// What a point of the ring is.2215#[wasm_bindgen]2216pub struct gauss_Class {}22172218#[wasm_bindgen]2219impl gauss_Class {2220 /// Returns whether the class is prime.2221 pub fn prime(class_: JsValue) -> Result<bool, JsValue> {2222 let class_ = hand::from_js::<mrlyrs::num::gauss::Class>(&class_)?;2223 let value = class_.prime();2224 Ok(value)2225 }2226 /// Returns the class as a word.2227 pub fn word(class_: JsValue) -> Result<String, JsValue> {2228 let class_ = hand::from_js::<mrlyrs::num::gauss::Class>(&class_)?;2229 let value = class_.word();2230 Ok(value)2231 }2232}22332234/// The two rings of whole numbers in the plane, each a pair (a, b) on its own lattice.2235#[wasm_bindgen]2236pub struct gauss_Ring {}22372238#[wasm_bindgen]2239impl gauss_Ring {2240 /// Returns the unit multiples of a point, the point first, turning anticlockwise.2241 pub fn associates(ring: JsValue, a: JsValue, b: JsValue) -> Result<JsValue, JsValue> {2242 let ring = hand::from_js::<mrlyrs::num::gauss::Ring>(&ring)?;2243 let a = hand::i64_from_js(&a)?;2244 let b = hand::i64_from_js(&b)?;2245 let value = ring.associates(a, b);2246 hand::list_to_js(&value, |x1| Ok(hand::tuple_to_js(&[JsValue::from(x1.0), JsValue::from(x1.1)])))2247 }2248 /// Returns the canonical associate of a point: the one with `a > 0` and `b >= 0` on the square lattice, the one with `a > 0` and `0 <= b < a` on the hexagonal, the origin for the origin.2249 pub fn canon(ring: JsValue, a: JsValue, b: JsValue) -> Result<JsValue, JsValue> {2250 let ring = hand::from_js::<mrlyrs::num::gauss::Ring>(&ring)?;2251 let a = hand::i64_from_js(&a)?;2252 let b = hand::i64_from_js(&b)?;2253 let value = ring.canon(a, b);2254 Ok(hand::tuple_to_js(&[JsValue::from(value.0), JsValue::from(value.1)]))2255 }2256 /// Returns the conjugate: the mirror image in the real axis.2257 pub fn conjugate(ring: JsValue, a: JsValue, b: JsValue) -> Result<JsValue, JsValue> {2258 let ring = hand::from_js::<mrlyrs::num::gauss::Ring>(&ring)?;2259 let a = hand::i64_from_js(&a)?;2260 let b = hand::i64_from_js(&b)?;2261 let value = ring.conjugate(a, b);2262 Ok(hand::tuple_to_js(&[JsValue::from(value.0), JsValue::from(value.1)]))2263 }2264 /// Returns the count of points within the reach: the square or the hexagon.2265 pub fn count(ring: JsValue, radius: JsValue) -> Result<usize, JsValue> {2266 let ring = hand::from_js::<mrlyrs::num::gauss::Ring>(&ring)?;2267 let radius = hand::u64_from_js(&radius)?;2268 let value = ring.count(radius);2269 Ok(value)2270 }2271 /// Returns the quotient and the remainder of a point by a nonzero point: `z = q w + r` with the norm of `r` below the norm of `w`.2272 pub fn div_rem(ring: JsValue, z: JsValue, w: JsValue) -> Result<JsValue, JsValue> {2273 let ring = hand::from_js::<mrlyrs::num::gauss::Ring>(&ring)?;2274 let z = (hand::i64_from_js(&hand::item(&z, 0)?)?, hand::i64_from_js(&hand::item(&z, 1)?)?);2275 let w = (hand::i64_from_js(&hand::item(&w, 0)?)?, hand::i64_from_js(&hand::item(&w, 1)?)?);2276 let value = ring.div_rem(z, w);2277 Ok(hand::tuple_to_js(&[hand::tuple_to_js(&[JsValue::from(value.0.0), JsValue::from(value.0.1)]), hand::tuple_to_js(&[JsValue::from(value.1.0), JsValue::from(value.1.1)])]))2278 }2279 /// Returns the fate of a whole number as a prime of the ring: split, inert or ramified, unit for one, zero for zero, composite otherwise.2280 pub fn fate(ring: JsValue, n: JsValue) -> Result<JsValue, JsValue> {2281 let ring = hand::from_js::<mrlyrs::num::gauss::Ring>(&ring)?;2282 let n = hand::u64_from_js(&n)?;2283 let value = ring.fate(n);2284 hand::to_js(&value)2285 }2286 /// Returns the greatest common divisor of two points as its canonical associate, by the nearest-point Euclidean algorithm, the origin for two origins.2287 pub fn gaussian_gcd(ring: JsValue, z: JsValue, w: JsValue) -> Result<JsValue, JsValue> {2288 let ring = hand::from_js::<mrlyrs::num::gauss::Ring>(&ring)?;2289 let z = (hand::i64_from_js(&hand::item(&z, 0)?)?, hand::i64_from_js(&hand::item(&z, 1)?)?);2290 let w = (hand::i64_from_js(&hand::item(&w, 0)?)?, hand::i64_from_js(&hand::item(&w, 1)?)?);2291 let value = ring.gaussian_gcd(z, w);2292 Ok(hand::tuple_to_js(&[JsValue::from(value.0), JsValue::from(value.1)]))2293 }2294 /// Returns whether a rational prime stays prime in the ring: 3 mod 4, or 2 mod 3.2295 pub fn inert(ring: JsValue, p: JsValue) -> Result<bool, JsValue> {2296 let ring = hand::from_js::<mrlyrs::num::gauss::Ring>(&ring)?;2297 let p = hand::u64_from_js(&p)?;2298 let value = ring.inert(p);2299 Ok(value)2300 }2301 /// Returns the product of two points.2302 pub fn mul(ring: JsValue, arg1: JsValue, arg2: JsValue) -> Result<JsValue, JsValue> {2303 let ring = hand::from_js::<mrlyrs::num::gauss::Ring>(&ring)?;2304 let arg1 = (hand::i64_from_js(&hand::item(&arg1, 0)?)?, hand::i64_from_js(&hand::item(&arg1, 1)?)?);2305 let arg2 = (hand::i64_from_js(&hand::item(&arg2, 0)?)?, hand::i64_from_js(&hand::item(&arg2, 1)?)?);2306 let value = ring.mul(arg1, arg2);2307 Ok(hand::tuple_to_js(&[JsValue::from(value.0), JsValue::from(value.1)]))2308 }2309 /// Reads a ring from its name.2310 pub fn named(name: &str) -> Result<JsValue, JsValue> {2311 let value = mrlyrs::num::gauss::Ring::named(name);2312 hand::to_js(&value)2313 }2314 /// Returns the point nearest a place in the plane.2315 pub fn nearest(ring: JsValue, x: f64, y: f64) -> Result<JsValue, JsValue> {2316 let ring = hand::from_js::<mrlyrs::num::gauss::Ring>(&ring)?;2317 let value = ring.nearest(x, y);2318 Ok(hand::tuple_to_js(&[JsValue::from(value.0), JsValue::from(value.1)]))2319 }2320 /// Returns the norm of a point: its squared length.2321 pub fn norm(ring: JsValue, a: JsValue, b: JsValue) -> Result<u64, JsValue> {2322 let ring = hand::from_js::<mrlyrs::num::gauss::Ring>(&ring)?;2323 let a = hand::i64_from_js(&a)?;2324 let b = hand::i64_from_js(&b)?;2325 let value = ring.norm(a, b);2326 Ok(value)2327 }2328 /// Returns the place of a point in the plane, x right and y up, one unit between neighbours.2329 pub fn place(ring: JsValue, a: JsValue, b: JsValue) -> Result<JsValue, JsValue> {2330 let ring = hand::from_js::<mrlyrs::num::gauss::Ring>(&ring)?;2331 let a = hand::i64_from_js(&a)?;2332 let b = hand::i64_from_js(&b)?;2333 let value = ring.place(a, b);2334 hand::to_js(&value)2335 }2336 /// Returns the one rational prime that ramifies: 2 or 3.2337 pub fn ramified(ring: JsValue) -> Result<u64, JsValue> {2338 let ring = hand::from_js::<mrlyrs::num::gauss::Ring>(&ring)?;2339 let value = ring.ramified();2340 Ok(value)2341 }2342 /// Returns the reach of a point: the ring of the window it sits on, the Chebyshev distance or the hex distance.2343 pub fn reach(ring: JsValue, a: JsValue, b: JsValue) -> Result<u64, JsValue> {2344 let ring = hand::from_js::<mrlyrs::num::gauss::Ring>(&ring)?;2345 let a = hand::i64_from_js(&a)?;2346 let b = hand::i64_from_js(&b)?;2347 let value = ring.reach(a, b);2348 Ok(value)2349 }2350 /// Returns the order of the symmetry of the picture, the units and the mirror: 8 or 12.2351 pub fn symmetry(ring: JsValue) -> Result<usize, JsValue> {2352 let ring = hand::from_js::<mrlyrs::num::gauss::Ring>(&ring)?;2353 let value = ring.symmetry();2354 Ok(value)2355 }2356 /// Returns the largest norm within the reach: 2 r^2 at the square's corner, r^2 at the hexagon's.2357 pub fn top(ring: JsValue, radius: JsValue) -> Result<u64, JsValue> {2358 let ring = hand::from_js::<mrlyrs::num::gauss::Ring>(&ring)?;2359 let radius = hand::u64_from_js(&radius)?;2360 let value = ring.top(radius);2361 Ok(value)2362 }2363 /// Returns the point turned anticlockwise by one unit: a quarter turn or a sixth.2364 pub fn turn(ring: JsValue, a: JsValue, b: JsValue) -> Result<JsValue, JsValue> {2365 let ring = hand::from_js::<mrlyrs::num::gauss::Ring>(&ring)?;2366 let a = hand::i64_from_js(&a)?;2367 let b = hand::i64_from_js(&b)?;2368 let value = ring.turn(a, b);2369 Ok(hand::tuple_to_js(&[JsValue::from(value.0), JsValue::from(value.1)]))2370 }2371 /// Returns the count of units: 4 or 6.2372 pub fn units(ring: JsValue) -> Result<usize, JsValue> {2373 let ring = hand::from_js::<mrlyrs::num::gauss::Ring>(&ring)?;2374 let value = ring.units();2375 Ok(value)2376 }2377 /// Returns the whole number an associate of the point lies on, when one lies on the positive real axis.2378 pub fn whole(ring: JsValue, a: JsValue, b: JsValue) -> Result<JsValue, JsValue> {2379 let ring = hand::from_js::<mrlyrs::num::gauss::Ring>(&ring)?;2380 let a = hand::i64_from_js(&a)?;2381 let b = hand::i64_from_js(&b)?;2382 let value = ring.whole(a, b);2383 hand::option_to_js(value.as_ref(), |x1| Ok(JsValue::from(*x1)))2384 }2385}23862387/// The four ways the word lifts from a line to the plane, one sign at every site.2388#[wasm_bindgen]2389pub struct morse_Lift {}23902391#[wasm_bindgen]2392impl morse_Lift {2393 /// Returns every Lift in canonical order.2394 pub fn all() -> Result<JsValue, JsValue> {2395 let value = mrlyrs::num::morse::Lift::all();2396 hand::to_js(&value)2397 }2398 /// Returns the sign at a site, zero for plus one and one for minus one.2399 pub fn at(lift: JsValue, i: JsValue, j: JsValue) -> Result<u8, JsValue> {2400 let lift = hand::from_js::<mrlyrs::num::morse::Lift>(&lift)?;2401 let i = hand::u64_from_js(&i)?;2402 let j = hand::u64_from_js(&j)?;2403 let value = lift.at(i, j);2404 Ok(value)2405 }2406 /// Returns the lift's formula, written the way the page prints it.2407 pub fn formula(lift: JsValue) -> Result<String, JsValue> {2408 let lift = hand::from_js::<mrlyrs::num::morse::Lift>(&lift)?;2409 let value = lift.formula();2410 Ok(value)2411 }2412}24132414/// Which cells of the square winding grow into a tile.2415#[wasm_bindgen]2416pub struct spiral_Growth {}24172418#[wasm_bindgen]2419impl spiral_Growth {2420 /// Returns every Growth in canonical order.2421 pub fn all() -> Result<JsValue, JsValue> {2422 let value = mrlyrs::num::spiral::Growth::all();2423 hand::to_js(&value)2424 }2425}24262427/// The two lattices a spiral of the whole numbers is wound on, one at the centre and two to its right.2428#[wasm_bindgen]2429pub struct spiral_Lattice {}24302431#[wasm_bindgen]2432impl spiral_Lattice {2433 /// Returns every Lattice in canonical order.2434 pub fn all() -> Result<JsValue, JsValue> {2435 let value = mrlyrs::num::spiral::Lattice::all();2436 hand::to_js(&value)2437 }2438 /// Returns the count of numbers a sheet the odd side wide holds: the side squared, or the hexagon of that many cells across.2439 pub fn count(lattice: JsValue, side: usize) -> Result<usize, JsValue> {2440 let lattice = hand::from_js::<mrlyrs::num::spiral::Lattice>(&lattice)?;2441 let value = lattice.count(side);2442 Ok(value)2443 }2444 /// Returns the number at a cell, one at the origin.2445 pub fn n(lattice: JsValue, x: JsValue, y: JsValue) -> Result<u64, JsValue> {2446 let lattice = hand::from_js::<mrlyrs::num::spiral::Lattice>(&lattice)?;2447 let x = hand::i64_from_js(&x)?;2448 let y = hand::i64_from_js(&y)?;2449 let value = lattice.n(x, y);2450 Ok(value)2451 }2452 /// Returns the outermost ring of a sheet the odd side wide, half the side rounded down.2453 pub fn radius(lattice: JsValue, side: usize) -> Result<usize, JsValue> {2454 let lattice = hand::from_js::<mrlyrs::num::spiral::Lattice>(&lattice)?;2455 let value = lattice.radius(side);2456 Ok(value)2457 }2458 /// Returns the ring a number sits on, zero for one.2459 pub fn ring(lattice: JsValue, n: JsValue) -> Result<u64, JsValue> {2460 let lattice = hand::from_js::<mrlyrs::num::spiral::Lattice>(&lattice)?;2461 let n = hand::u64_from_js(&n)?;2462 let value = lattice.ring(n);2463 Ok(value)2464 }2465 /// Returns the ring of a cell: the larger of the coordinates on the square, the hex distance on the hexagon.2466 pub fn ring_of(lattice: JsValue, x: JsValue, y: JsValue) -> Result<u64, JsValue> {2467 let lattice = hand::from_js::<mrlyrs::num::spiral::Lattice>(&lattice)?;2468 let x = hand::i64_from_js(&x)?;2469 let y = hand::i64_from_js(&y)?;2470 let value = lattice.ring_of(x, y);2471 Ok(value)2472 }2473 /// Returns the cell of a number: x right and y up on the square, axial q and r on the hexagon.2474 pub fn xy(lattice: JsValue, n: JsValue) -> Result<JsValue, JsValue> {2475 let lattice = hand::from_js::<mrlyrs::num::spiral::Lattice>(&lattice)?;2476 let n = hand::u64_from_js(&n)?;2477 let value = lattice.xy(n);2478 Ok(hand::tuple_to_js(&[JsValue::from(value.0), JsValue::from(value.1)]))2479 }2480}24812482/// What a cell is painted for.2483#[wasm_bindgen]2484pub struct spiral_Mark {}24852486#[wasm_bindgen]2487impl spiral_Mark {2488 /// Returns every Mark in canonical order.2489 pub fn all() -> Result<JsValue, JsValue> {2490 let value = mrlyrs::num::spiral::Mark::all();2491 hand::to_js(&value)2492 }2493}