diff --git a/front/error/src/error.rs b/front/error/src/error.rs index e73534fc..dafcd63c 100644 --- a/front/error/src/error.rs +++ b/front/error/src/error.rs @@ -399,19 +399,21 @@ impl WaveError { let width = (end + 1).to_string().len().max(2); for (i, source_line) in lines.iter().enumerate().take(end + 1).skip(start) { + let rendered = + utils::display_width::diagnostic_line(source_line, col, self.span_len); let ln = i + 1; let ln_str = format!("{:>width$}", ln, width = width); eprintln!( " {} {} {}", ln_str.color("38,139,235").bold(), pipe, - source_line + rendered.text ); if ln == line { let pad = " ".repeat(width); - let spaces = " ".repeat(col.saturating_sub(1)); + let spaces = " ".repeat(rendered.caret_offset); let marks = "^" - .repeat(self.span_len.max(1)) + .repeat(rendered.caret_width) .color(self.severity_color()) .bold(); match &self.label { @@ -427,19 +429,20 @@ impl WaveError { } if let Some(source_line) = &self.source { + let rendered = utils::display_width::diagnostic_line(source_line, col, self.span_len); let width = line.to_string().len().max(2); let ln_str = format!("{:>width$}", line, width = width); eprintln!( " {} {} {}", ln_str.color("38,139,235").bold(), pipe, - source_line + rendered.text ); let pad = " ".repeat(width); - let spaces = " ".repeat(col.saturating_sub(1)); + let spaces = " ".repeat(rendered.caret_offset); let marks = "^" - .repeat(self.span_len.max(1)) + .repeat(rendered.caret_width) .color(self.severity_color()) .bold(); match &self.label { diff --git a/front/parser/src/async_intrinsics.rs b/front/parser/src/async_intrinsics.rs index dd2439f2..d1010a3b 100644 --- a/front/parser/src/async_intrinsics.rs +++ b/front/parser/src/async_intrinsics.rs @@ -109,7 +109,7 @@ pub fn signature( } "__wave_async_sleep" => { no_types()?; - (vec![Int(64)], future(Void)) + (vec![Int(64)], future(Int(32))) } "__wave_async_cancel_join" => { no_types()?; diff --git a/front/parser/src/import.rs b/front/parser/src/import.rs index 823f746c..a0d21782 100644 --- a/front/parser/src/import.rs +++ b/front/parser/src/import.rs @@ -28,7 +28,7 @@ use std::path::{Path, PathBuf}; /// Compiler/standard-library syntax contract understood by this parser. /// Bump this together with std/manifest.json when compatibility is broken. -pub const STD_COMPATIBILITY_REVISION: u64 = 4; +pub const STD_COMPATIBILITY_REVISION: u64 = 5; #[derive(Debug, Clone, Default)] pub struct TargetConditionContext { diff --git a/llvm/src/codegen/wasm_runtime/mod.rs b/llvm/src/codegen/arithmetic_runtime/mod.rs similarity index 62% rename from llvm/src/codegen/wasm_runtime/mod.rs rename to llvm/src/codegen/arithmetic_runtime/mod.rs index 654acac8..bfe1f154 100644 --- a/llvm/src/codegen/wasm_runtime/mod.rs +++ b/llvm/src/codegen/arithmetic_runtime/mod.rs @@ -1,19 +1,24 @@ // This file is part of the Wave language project. // SPDX-License-Identifier: MPL-2.0 //! Freestanding arithmetic legalization. Helpers contain no host calls and use -//! only operations that WebAssembly can lower without a runtime SDK. +//! only operations the selected target can lower without a runtime SDK. mod templates; +use super::target::CodegenTarget; use inkwell::{ context::Context, memory_buffer::MemoryBuffer, module::{Linkage, Module}, - values::{BasicValue, InstructionOpcode, InstructionValue}, + values::{AnyValue, BasicValue, InstructionOpcode, InstructionValue}, }; use std::collections::HashMap; /// Run after optimization so unused operations never pull in runtime support. /// Functions are private and cached by operation, independently of user symbols. -pub(super) fn lower<'ctx>(context: &'ctx Context, module: &Module<'ctx>) -> Result<(), String> { +pub(super) fn lower<'ctx>( + context: &'ctx Context, + module: &Module<'ctx>, + target: CodegenTarget, +) -> Result<(), String> { let builder = context.create_builder(); let mut helpers = HashMap::new(); loop { @@ -21,13 +26,13 @@ pub(super) fn lower<'ctx>(context: &'ctx Context, module: &Module<'ctx>) -> Resu .get_functions() .flat_map(|f| f.get_basic_blocks()) .flat_map(|b| b.get_instructions()) - .filter(|i| operation(*i).is_some()) + .filter(|i| operation(*i, target).is_some()) .collect(); if instructions.is_empty() { break; } for instruction in instructions { - let Some(key) = operation(instruction) else { + let Some(key) = operation(instruction, target) else { continue; }; let function = if let Some(function) = helpers.get(&key) { @@ -76,7 +81,7 @@ pub(super) fn lower<'ctx>(context: &'ctx Context, module: &Module<'ctx>) -> Resu module.verify().map_err(|e| e.to_string()) } -fn operation(instruction: InstructionValue<'_>) -> Option { +fn operation(instruction: InstructionValue<'_>, target: CodegenTarget) -> Option { use InstructionOpcode::*; if !matches!( instruction.get_opcode(), @@ -84,6 +89,43 @@ fn operation(instruction: InstructionValue<'_>) -> Option { ) { return None; } + // LLVM's 64-bit native targets expand i128 multiply and shifts into native + // instructions. WebAssembly requires explicit limb legalization for these. + let wasm = matches!( + target, + CodegenTarget::Wasm32Unknown | CodegenTarget::Wasm32WasiP1 | CodegenTarget::Wasm64Unknown + ); + if !wasm && matches!(instruction.get_opcode(), Mul | Shl | LShr | AShr) { + return None; + } + if !wasm && matches!(instruction.get_opcode(), UDiv | SDiv | URem | SRem) { + // LLVM's native DAG lowering expands power-of-two divisors into + // shifts/masks (with signed rounding adjustments), even at O0. + if let Some(divisor) = instruction + .get_operand(1) + .and_then(|v| v.value()) + .filter(|v| v.is_int_value()) + { + let divisor = divisor.into_int_value(); + if divisor.is_const() { + let text = divisor.print_to_string().to_string(); + if let Some(value) = text + .split_whitespace() + .last() + .and_then(|s| s.parse::().ok()) + { + let magnitude = if matches!(instruction.get_opcode(), SDiv | SRem) { + value.unsigned_abs() + } else { + value as u128 + }; + if magnitude.is_power_of_two() { + return None; + } + } + } + } + } let source = instruction .get_operand(0)? .value()? @@ -120,3 +162,21 @@ fn operation(instruction: InstructionValue<'_>) -> Option { }; Some(format!("{opcode}.{source}.{target}")) } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn preserves_vector_division_created_by_the_optimizer() { + let context = Context::create(); + let module = context.create_module_from_ir(MemoryBuffer::create_from_memory_range_copy( + b"define <16 x i16> @vector(<16 x i16> %a) { %result = udiv <16 x i16> %a, splat (i16 251)\n ret <16 x i16> %result }", + "vector-runtime-regression", + )).unwrap(); + lower(&context, &module, CodegenTarget::FreeBsdX86_64).unwrap(); + let ir = module.print_to_string().to_string(); + assert!(ir.contains("udiv <16 x i16>")); + assert!(!ir.contains("__wave.runtime.")); + } +} diff --git a/llvm/src/codegen/wasm_runtime/templates.rs b/llvm/src/codegen/arithmetic_runtime/templates.rs similarity index 100% rename from llvm/src/codegen/wasm_runtime/templates.rs rename to llvm/src/codegen/arithmetic_runtime/templates.rs diff --git a/llvm/src/codegen/ir.rs b/llvm/src/codegen/ir.rs index 193c1070..71a5ee5c 100644 --- a/llvm/src/codegen/ir.rs +++ b/llvm/src/codegen/ir.rs @@ -1486,11 +1486,8 @@ fn build_module( codegen_trace("skip optimization passes"); } - if abi_target == CodegenTarget::Wasm64Unknown { - super::wasm_runtime::lower(context, module).map_err(|e| { - CodegenError::new(CodegenPhase::Lowering, "lower wasm arithmetic runtime", e) - })?; - } + super::arithmetic_runtime::lower(context, module, abi_target) + .map_err(|e| CodegenError::new(CodegenPhase::Lowering, "lower arithmetic runtime", e))?; codegen_trace("finish module"); Ok(GeneratedModule { diff --git a/llvm/src/codegen/mod.rs b/llvm/src/codegen/mod.rs index d4ebf1dc..82885ea4 100644 --- a/llvm/src/codegen/mod.rs +++ b/llvm/src/codegen/mod.rs @@ -41,4 +41,4 @@ mod validation; pub(crate) mod conversions; -mod wasm_runtime; +mod arithmetic_runtime; diff --git a/src/cli.rs b/src/cli.rs index 0e43e80f..7c30a5b9 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -2460,7 +2460,7 @@ fn link_objects( let stdout = String::from_utf8_lossy(&out.stdout).trim().to_string(); let hint = if llvm::backend::is_windows_msvc_target(&target) { - "\nMSVC output requires matching Windows SDK (UM/UCRT) and VC runtime libraries; run a Developer Command Prompt for the target architecture or supply their directories with -L. Arithmetic builtins such as __udivti3 require the target-matched LLVM 21 compiler-rt library; set WAVE_LLVM_HOME to that SDK." + "\nMSVC output requires matching Windows SDK (UM/UCRT) and VC runtime libraries; run a Developer Command Prompt for the target architecture or supply their directories with -L." } else { "" }; diff --git a/src/link_validation/elf.rs b/src/link_validation/elf.rs index f6bb74bf..611d1d92 100644 --- a/src/link_validation/elf.rs +++ b/src/link_validation/elf.rs @@ -21,6 +21,7 @@ use std::fs; use std::path::{Path, PathBuf}; const ELF_MAGIC: &[u8; 4] = b"\x7fELF"; +const THIN_MAGIC: &[u8; 8] = b"!\n"; const AR_MAGIC: &[u8; 8] = b"!\n"; #[derive(Debug)] @@ -81,7 +82,7 @@ pub(super) fn inspect_link_inputs( input: path.to_path_buf(), source, })?; - inspect_input(path, &bytes, &mut metadata)?; + inspect_input(path, &bytes, &mut metadata, 0)?; } Ok(metadata) } @@ -90,11 +91,18 @@ fn inspect_input( path: &Path, bytes: &[u8], metadata: &mut Vec, + depth: usize, ) -> Result<(), LinkInputInspectionError> { + if depth > 64 { + return Err(malformed( + &path.display().to_string(), + "archive nesting limit exceeded (possible cycle)", + )); + } if bytes.starts_with(ELF_MAGIC) { metadata.push(read_elf(&path.display().to_string(), bytes)?); - } else if bytes.starts_with(AR_MAGIC) { - inspect_archive(path, bytes, metadata)?; + } else if bytes.starts_with(AR_MAGIC) || bytes.starts_with(THIN_MAGIC) { + inspect_archive(path, bytes, metadata, depth, None)?; } // LLVM bitcode and linker scripts do not carry ELF e_flags. They remain // valid linker inputs and are intentionally ignored by metadata validation. @@ -130,81 +138,177 @@ fn inspect_archive( path: &Path, bytes: &[u8], metadata: &mut Vec, + depth: usize, + selected: Option, ) -> Result<(), LinkInputInspectionError> { let display = path.display().to_string(); + let thin = bytes.starts_with(THIN_MAGIC); let mut offset = AR_MAGIC.len(); let mut long_names: Option<&[u8]> = None; while offset < bytes.len() { - let Some(header) = bytes.get(offset..offset + 60) else { - return Err(malformed(&display, "truncated archive header")); - }; + let header_end = offset + .checked_add(60) + .ok_or_else(|| malformed(&display, "archive header offset overflow"))?; + let header = bytes + .get(offset..header_end) + .ok_or_else(|| malformed(&display, "truncated archive header"))?; if &header[58..60] != b"`\n" { return Err(malformed(&display, "invalid archive member header")); } - let size_text = std::str::from_utf8(&header[48..58]) - .map_err(|_| malformed(&display, "invalid archive member size"))?; - let size = size_text - .trim() - .parse::() - .map_err(|_| malformed(&display, "invalid archive member size"))?; - let data_start = offset + 60; - let Some(member_data) = bytes.get(data_start..data_start + size) else { - return Err(malformed(&display, "truncated archive member")); - }; + let size = archive_number(&display, &header[48..58], "invalid archive member size")?; let raw_name = std::str::from_utf8(&header[..16]) .map_err(|_| malformed(&display, "invalid archive member name"))? .trim(); - - let (name, payload) = if raw_name == "//" { + let special = matches!(raw_name, "//" | "/" | "/SYM64/"); + // Thin members have a size describing the external object, but no + // embedded bytes or padding. Only symbol/name tables remain embedded. + let stored_size = if thin && !special { 0 } else { size }; + let data_end = header_end + .checked_add(stored_size) + .ok_or_else(|| malformed(&display, "archive member size overflow"))?; + let member_data = bytes + .get(header_end..data_end) + .ok_or_else(|| malformed(&display, "truncated archive member"))?; + if raw_name == "//" { long_names = Some(member_data); - (None, member_data) - } else if raw_name == "/" || raw_name == "/SYM64/" { - (None, member_data) - } else if let Some(length) = raw_name.strip_prefix("#1/") { - let length = length - .parse::() - .map_err(|_| malformed(&display, "invalid BSD archive member name"))?; - let Some(name_bytes) = member_data.get(..length) else { - return Err(malformed(&display, "truncated BSD archive member name")); - }; - let name = String::from_utf8_lossy(name_bytes) - .trim_end_matches('\0') - .to_string(); - (Some(name), &member_data[length..]) - } else if let Some(name_offset) = raw_name.strip_prefix('/') { - let name_offset = name_offset - .parse::() - .map_err(|_| malformed(&display, "invalid GNU archive name offset"))?; - let table = long_names - .ok_or_else(|| malformed(&display, "archive long-name table is missing"))?; - let tail = table - .get(name_offset..) - .ok_or_else(|| malformed(&display, "archive long-name offset is out of range"))?; - let end = tail - .windows(2) - .position(|window| window == b"/\n") - .unwrap_or(tail.len()); - ( - Some(String::from_utf8_lossy(&tail[..end]).into_owned()), - member_data, - ) - } else { - ( - Some(raw_name.trim_end_matches('/').to_string()), - member_data, - ) - }; - - if let Some(name) = name { - if payload.starts_with(ELF_MAGIC) { - metadata.push(read_elf(&format!("{}({})", path.display(), name), payload)?); + } else if !special && selected.is_none_or(|wanted| wanted == offset) { + let (name, payload, origin) = + archive_member(&display, raw_name, member_data, long_names, thin)?; + let member_display = format!("{display}({name})"); + if thin { + let member_path = path.parent().unwrap_or_else(|| Path::new(".")).join(&name); + let external = fs::read(&member_path).map_err(|source| { + malformed( + &member_display, + &format!( + "failed to read thin archive member '{}': {source}", + member_path.display() + ), + ) + })?; + if let Some(origin) = origin { + if !external.starts_with(AR_MAGIC) { + return Err(malformed( + &member_display, + "nested thin member does not reference a regular archive", + )); + } + // GNU ar may refer to one member of an existing regular + // archive as /name_offset:header_offset. Inspect only it. + inspect_archive(&member_path, &external, metadata, depth + 1, Some(origin))?; + } else { + let before = metadata.len(); + inspect_input(&member_path, &external, metadata, depth + 1)?; + for item in &mut metadata[before..] { + item.input = format!("{member_display}: {}", item.input); + } + } + } else if payload.starts_with(ELF_MAGIC) { + metadata.push(read_elf(&member_display, payload)?); } + if selected.is_some() { + return Ok(()); + } + } + offset = data_end + .checked_add(stored_size & 1) + .ok_or_else(|| malformed(&display, "archive padding offset overflow"))?; + if offset > bytes.len() { + return Err(malformed(&display, "truncated archive padding")); } - offset = data_start + size + (size & 1); + } + if selected.is_some() { + return Err(malformed( + &display, + "nested archive member offset is not a member header", + )); } Ok(()) } +fn archive_number( + display: &str, + text: &[u8], + reason: &str, +) -> Result { + let text = std::str::from_utf8(text) + .map_err(|_| malformed(display, reason))? + .trim(); + if text.is_empty() || !text.bytes().all(|c| c.is_ascii_digit()) { + return Err(malformed(display, reason)); + } + text.parse().map_err(|_| malformed(display, reason)) +} + +fn archive_member<'a>( + display: &str, + raw_name: &str, + data: &'a [u8], + long_names: Option<&[u8]>, + thin: bool, +) -> Result<(String, &'a [u8], Option), LinkInputInspectionError> { + if let Some(length) = raw_name.strip_prefix("#1/") { + if thin { + return Err(malformed( + display, + "BSD extended names are invalid in GNU thin archives", + )); + } + let length = archive_number( + display, + length.as_bytes(), + "invalid BSD archive member name", + )?; + let name = data + .get(..length) + .ok_or_else(|| malformed(display, "truncated BSD archive member name"))?; + return Ok(( + String::from_utf8_lossy(name) + .trim_end_matches('\0') + .to_string(), + &data[length..], + None, + )); + } + if let Some(reference) = raw_name.strip_prefix('/') { + let (name_offset, origin) = match reference.split_once(':') { + Some((name, origin)) if thin => ( + name, + Some(archive_number( + display, + origin.as_bytes(), + "invalid nested archive member offset", + )?), + ), + _ => (reference, None), + }; + let offset = archive_number( + display, + name_offset.as_bytes(), + "invalid GNU archive name offset", + )?; + let table = + long_names.ok_or_else(|| malformed(display, "archive long-name table is missing"))?; + let tail = table + .get(offset..) + .ok_or_else(|| malformed(display, "archive long-name offset is out of range"))?; + let end = tail + .windows(2) + .position(|w| w == b"/\n") + .ok_or_else(|| malformed(display, "unterminated archive long name"))?; + let name = String::from_utf8_lossy(&tail[..end]).into_owned(); + if name.is_empty() { + return Err(malformed(display, "empty archive member name")); + } + return Ok((name, data, origin)); + } + let name = raw_name.trim_end_matches('/'); + if name.is_empty() { + return Err(malformed(display, "empty archive member name")); + } + Ok((name.to_string(), data, None)) +} + fn malformed(input: &str, reason: &str) -> LinkInputInspectionError { LinkInputInspectionError::Malformed { input: input.to_string(), @@ -257,10 +361,141 @@ mod tests { archive.extend(elf); let mut metadata = Vec::new(); - inspect_archive(Path::new("libmixed.a"), &archive, &mut metadata).unwrap(); + inspect_archive(Path::new("libmixed.a"), &archive, &mut metadata, 0, None).unwrap(); assert_eq!(metadata.len(), 1); assert_eq!(metadata[0].input, "libmixed.a(main.o)"); assert_eq!(metadata[0].machine, 243); assert_eq!(metadata[0].flags, 2); } + + struct Fixture(PathBuf); + impl Fixture { + fn new() -> Self { + use std::sync::atomic::{AtomicU64, Ordering}; + static NEXT: AtomicU64 = AtomicU64::new(0); + let path = std::env::temp_dir().join(format!( + "wave-thin-{}-{}", + std::process::id(), + NEXT.fetch_add(1, Ordering::Relaxed) + )); + fs::create_dir_all(path.join("objects")).unwrap(); + Self(path) + } + fn inspect(&self, bytes: &[u8]) -> Result, LinkInputInspectionError> { + let path = self.0.join("lib.a"); + fs::write(&path, bytes).unwrap(); + inspect_link_inputs(&[path.display().to_string()]) + } + } + impl Drop for Fixture { + fn drop(&mut self) { + let _ = fs::remove_dir_all(&self.0); + } + } + + fn elf(flags: u32) -> Vec { + let mut bytes = vec![0; 64]; + bytes[..4].copy_from_slice(ELF_MAGIC); + bytes[4] = 2; + bytes[5] = 1; + bytes[18..20].copy_from_slice(&243u16.to_le_bytes()); + bytes[48..52].copy_from_slice(&flags.to_le_bytes()); + bytes + } + fn thin(names: &[u8], members: &[(&str, usize)]) -> Vec { + let mut bytes = THIN_MAGIC.to_vec(); + bytes.extend(archive_header("/", 4)); + bytes.extend([0; 4]); + bytes.extend(archive_header("//", names.len())); + bytes.extend(names); + if names.len() % 2 != 0 { + bytes.push(b'\n'); + } + for (name, size) in members { + bytes.extend(archive_header(name, *size)); + } + bytes + } + + #[test] + fn thin_paths_are_relative_to_the_archive_and_validate_each_member_abi() { + let fixture = Fixture::new(); + fs::write(fixture.0.join("objects/long_member_name.o"), elf(4)).unwrap(); + fs::write(fixture.0.join("other.o"), elf(2)).unwrap(); + let names = b"objects/long_member_name.o/\nother.o/\n"; + let offset = names.windows(8).position(|w| w == b"other.o/").unwrap(); + let bytes = thin(names, &[("/0", 64), (&format!("/{offset}"), 64)]); + let metadata = fixture.inspect(&bytes).unwrap(); + assert_eq!(metadata.iter().map(|m| m.flags).collect::>(), [4, 2]); + let error = super::super::riscv::validate_riscv_link_inputs( + super::super::riscv::RiscvFloatAbi::Lp64d, + &[fixture.0.join("lib.a").display().to_string()], + ) + .unwrap_err() + .to_string(); + assert!( + error.contains("other.o") && error.contains("LP64F"), + "{error}" + ); + } + + #[test] + fn gnu_name_offsets_may_reference_a_shared_suffix() { + let fixture = Fixture::new(); + fs::write(fixture.0.join("member.o"), elf(4)).unwrap(); + // GNU offsets identify bytes in the string table, not entry indices. + let bytes = thin(b"prefix_member.o/\n", &[("/7", 64)]); + let metadata = fixture.inspect(&bytes).unwrap(); + assert_eq!(metadata.len(), 1); + assert_eq!(metadata[0].flags, 4); + } + + #[test] + fn thin_nested_regular_archive_selects_only_the_referenced_member() { + let fixture = Fixture::new(); + let mut nested = AR_MAGIC.to_vec(); + nested.extend(archive_header("bad.o/", 64)); + nested.extend(elf(2)); + let origin = nested.len(); + nested.extend(archive_header("good.o/", 64)); + nested.extend(elf(4)); + fs::write(fixture.0.join("nested.a"), nested).unwrap(); + let bytes = thin(b"nested.a/\n", &[(&format!("/0:{origin}"), 64)]); + let metadata = fixture.inspect(&bytes).unwrap(); + assert_eq!(metadata.len(), 1); + assert_eq!(metadata[0].flags, 4); + let bad = thin(b"nested.a/\n", &[("/0:9", 64)]); + assert!(fixture + .inspect(&bad) + .unwrap_err() + .to_string() + .contains("not a member header")); + } + + #[test] + fn thin_missing_members_and_malformed_headers_are_diagnostics() { + let fixture = Fixture::new(); + let valid = thin(b"missing.o/\n", &[("/0", 64)]); + assert!(fixture + .inspect(&valid) + .unwrap_err() + .to_string() + .contains("missing.o")); + for bytes in [ + thin(b"missing.o/\n", &[("/999", 64)]), + thin(b"missing.o/\n", &[("/1", 64)]), + thin(b"missing.o", &[("/0", 64)]), + thin(b"missing.o/\n", &[("/0:no", 64)]), + [THIN_MAGIC.as_slice(), b"truncated"].concat(), + [AR_MAGIC.as_slice(), &archive_header("//", 9_999_999_999)].concat(), + ] { + assert!(fixture.inspect(&bytes).is_err()); + } + let cycle = thin(b"lib.a/\n", &[("/0", 64)]); + assert!(fixture + .inspect(&cycle) + .unwrap_err() + .to_string() + .contains("nesting limit")); + } } diff --git a/std/manifest.json b/std/manifest.json index 5b14b69a..87a9a143 100644 --- a/std/manifest.json +++ b/std/manifest.json @@ -1,7 +1,7 @@ { "name": "std", "format": 1, - "compatibility_revision": 4, + "compatibility_revision": 5, "license": "Apache-2.0", "modules": ["string", "math", "sys", "net", "libc", "time", "env", "path", "mem", "buffer", "io", "fs", "bytes", "process", "debug", "random"] } diff --git a/std/math/trig.wave b/std/math/trig.wave index 51c775e6..68ad9d48 100644 --- a/std/math/trig.wave +++ b/std/math/trig.wave @@ -35,6 +35,8 @@ pub import("std::math::float")::{ nan_f64, }; +import("std::math::trig_reduction")::{ReducedAngle, reduce_angle_f64}; + pub struct SinCosF32 { sin: f32; cos: f32; @@ -51,16 +53,13 @@ pub fun wrap_angle_pi_f64(value: f64) -> f64 { return nan_f64(); } - // Floating remainder keeps the intermediate bounded even when value is far - // too large for quotient-based range reduction to retain useful bits. - var reduced: f64 = value % MATH_TWO_PI_F64; - if (reduced > MATH_PI_F64) { - reduced -= MATH_TWO_PI_F64; - } - if (reduced < -MATH_PI_F64) { - reduced += MATH_TWO_PI_F64; - } - return reduced; + var angle: ReducedAngle = reduce_angle_f64(value); + var r: f64 = angle.remainder; + if (angle.quadrant == 0) { return r; } + if (angle.quadrant == 1) { return MATH_HALF_PI_F64 + r; } + if (angle.quadrant == 3) { return -MATH_HALF_PI_F64 + r; } + if (r <= 0.0) { return MATH_PI_F64 + r; } + return -MATH_PI_F64 + r; } pub fun wrap_angle_pi_f32(value: f32) -> f32 { @@ -103,32 +102,16 @@ fun cos_polynomial_f64(value: f64) -> f64 { } pub fun sin_f64(value: f64) -> f64 { - var reduced: f64 = wrap_angle_pi_f64(value); - if (reduced > MATH_HALF_PI_F64) { - reduced = MATH_PI_F64 - reduced; - } - if (reduced < -MATH_HALF_PI_F64) { - reduced = -MATH_PI_F64 - reduced; - } - return sin_polynomial_f64(reduced); + return sin_cos_f64(value).sin; } pub fun cos_f64(value: f64) -> f64 { - var reduced: f64 = wrap_angle_pi_f64(value); - var sign: f64 = 1.0; - if (reduced > MATH_HALF_PI_F64) { - reduced = MATH_PI_F64 - reduced; - sign = -1.0; - } - if (reduced < -MATH_HALF_PI_F64) { - reduced = -MATH_PI_F64 - reduced; - sign = -1.0; - } - return sign * cos_polynomial_f64(reduced); + return sin_cos_f64(value).cos; } pub fun tan_f64(value: f64) -> f64 { - return sin_f64(value) / cos_f64(value); + var result: SinCosF64 = sin_cos_f64(value); + return result.sin / result.cos; } pub fun sin_f32(value: f32) -> f32 { @@ -144,11 +127,25 @@ pub fun tan_f32(value: f32) -> f32 { } pub fun sin_cos_f64(value: f64) -> SinCosF64 { - return SinCosF64 { sin: sin_f64(value), cos: cos_f64(value) }; + if (!is_finite_f64(value)) { + return SinCosF64 { sin: nan_f64(), cos: nan_f64() }; + } + // Avoid cancellation of -0 in the polynomial, and unnecessary underflow. + if (abs_f64(value) < 0.000000007450580596923828125) { + return SinCosF64 { sin: value, cos: 1.0 }; + } + var angle: ReducedAngle = reduce_angle_f64(value); + var s: f64 = sin_polynomial_f64(angle.remainder); + var c: f64 = cos_polynomial_f64(angle.remainder); + if (angle.quadrant == 0) { return SinCosF64 { sin: s, cos: c }; } + if (angle.quadrant == 1) { return SinCosF64 { sin: c, cos: -s }; } + if (angle.quadrant == 2) { return SinCosF64 { sin: -s, cos: -c }; } + return SinCosF64 { sin: -c, cos: s }; } pub fun sin_cos_f32(value: f32) -> SinCosF32 { - return SinCosF32 { sin: sin_f32(value), cos: cos_f32(value) }; + var result: SinCosF64 = sin_cos_f64(value as f64); + return SinCosF32 { sin: result.sin as f32, cos: result.cos as f32 }; } pub fun radians_f64(degrees: f64) -> f64 { diff --git a/std/math/trig_reduction.wave b/std/math/trig_reduction.wave new file mode 100644 index 00000000..68bf2915 --- /dev/null +++ b/std/math/trig_reduction.wave @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: Apache-2.0 +// Payne-Hanek reduction with a 2048-bit fixed-point 2/pi. Only u32/u64 +// operations are needed; there is no host math/runtime dependency. +// Limbs are little endian: floor((2/pi) * 2^2048). Generated independently +// with tools/generate_trig_vectors.py; the extra bits cover all finite f64. +import("std::math::float")::{abs_f64, float_to_bits_f64, float_from_bits_f64}; + +const TWO_OVER_PI: array = [ + 3404889885, 2671386421, 1797152504, 3275564783, + 2553445819, 851631695, 1065235432, 2784954117, + 1461257534, 3719251153, 2341870758, 2203698294, + 3706194218, 432236493, 2355840964, 1625455552, + 3396577481, 101061974, 1299392305, 2382354560, + 346056768, 1704559967, 1592138504, 2850263393, + 2599695901, 4040145952, 4235946923, 1443049542, + 529358088, 1811636145, 2320667370, 1023883767, + 3957715323, 1965537991, 2657085997, 1330003814, + 667617719, 1832287951, 1510632735, 4012839307, + 3724908559, 536385535, 3187222587, 2625920907, + 2203269620, 965858873, 3026157121, 3919343654, + 784024708, 3900847605, 2972297022, 4263373596, + 164729372, 105459434, 1112396512, 3072618042, + 3736847713, 4266746795, 1011060801, 3680671129, + 4113882560, 4230436817, 1313084713, 2734261102 +]; + +pub struct ReducedAngle { quadrant: i32; remainder: f64; } + +// The caller handles NaN/infinity; small angles also preserve signed zero. +pub fun reduce_angle_f64(value: f64) -> ReducedAngle { + if (abs_f64(value) <= 0.7853981633974483) { + return ReducedAngle { quadrant: 0, remainder: value }; + } + var bits: u64 = float_to_bits_f64(value); + var exponent: i32 = ((bits >> 52) & 2047) as i32 - 1023; + var significand: u64 = (bits & 4503599627370495) | 4503599627370496; + var low: u64 = significand & 4294967295; + var high: u64 = significand >> 32; + // Materialize the value array once, rather than copying it per limb. + var coefficients: array = TWO_OVER_PI; + var product: array; + var carry: u64 = 0; + var i: i32 = 0; + while (i < 64) { + var part: u64 = coefficients[i] as u64 * low + carry; + product[i] = part as u32; + carry = part >> 32; + i += 1; + } + product[64] = carry as u32; + product[65] = 0; + carry = 0; + i = 0; + while (i < 64) { + var part: u64 = coefficients[i] as u64 * high + product[i + 1] as u64 + carry; + product[i + 1] = part as u32; + carry = part >> 32; + i += 1; + } + product[65] = carry as u32; + + // x * 2/pi = product / 2^binary_point. Extract the integer modulo four + // and round to the nearest quadrant before converting the fraction. + var binary_point: i32 = 2100 - exponent; + var word: i32 = binary_point / 32; + var bit: i32 = binary_point % 32; + var quadrant: i32 = ((product[word] >> bit) & 1) as i32; + var next: i32 = binary_point + 1; + quadrant = quadrant | (((product[next / 32] >> (next % 32)) & 1) as i32) << 1; + var half: i32 = binary_point - 1; + var round_up: bool = ((product[half / 32] >> (half % 32)) & 1) != 0; + if (bit == 0) { + product[word] = 0; + } else { + product[word] = product[word] & ((1 as u32) << bit) - 1; + } + if (round_up) { + quadrant = (quadrant + 1) & 3; + // Complement the fixed-point fraction before converting to f64. + // Subtracting an already rounded float from 1 would lose pole bits. + carry = 1; + i = 0; + while (i <= word) { + var part: u64 = (product[i] ^ (4294967295 as u32)) as u64 + carry; + product[i] = part as u32; + carry = part >> 32; + i += 1; + } + if (bit == 0) { product[word] = 0; } + else { product[word] = product[word] & ((1 as u32) << bit) - 1; } + } + while (word > 0 && product[word] == 0) { word -= 1; } + // Four significant limbs retain at least 96 fractional bits, even when + // the remainder is very close to zero, without subtractive cancellation. + var scale_exponent: i32 = word * 32 - binary_point; + var scale: f64 = float_from_bits_f64(((1023 + scale_exponent) as u64) << 52); + var fraction: f64 = 0.0; + i = 0; + while (i < 4 && word >= 0) { + fraction += product[word] as f64 * scale; + scale *= 0.00000000023283064365386962890625; + word -= 1; + i += 1; + } + var remainder: f64 = fraction * 1.5707963267948966; + if (round_up) { remainder = -remainder; } + if (value < 0.0) { remainder = -remainder; quadrant = (4 - quadrant) & 3; } + return ReducedAngle { quadrant: quadrant, remainder: remainder }; +} diff --git a/std/net/error.wave b/std/net/error.wave index 810e8ccb..7fdc430d 100644 --- a/std/net/error.wave +++ b/std/net/error.wave @@ -50,37 +50,91 @@ pub fun net_error_from_native(native_code: i64) -> NetError { return net_error_none(); } - var code: i64 = -native_code; + return net_error(classify_native_error(native_code), native_code); +} - if (code == 22 || code == 10022) { - return net_error(NET_ERROR_INVALID, native_code); - } - if (code == 4 || code == 10004) { - return net_error(NET_ERROR_INTERRUPTED, native_code); - } - if (code == 11 || code == 35 || code == 10035) { - return net_error(NET_ERROR_WOULD_BLOCK, native_code); - } - if (code == 60 || code == 110 || code == 10060) { - return net_error(NET_ERROR_TIMED_OUT, native_code); - } - if (code == 61 || code == 111 || code == 10061) { - return net_error(NET_ERROR_REFUSED, native_code); - } - if (code == 54 || code == 104 || code == 10054) { - return net_error(NET_ERROR_RESET, native_code); - } - if (code == 48 || code == 98 || code == 10048) { - return net_error(NET_ERROR_ADDRESS_IN_USE, native_code); - } - if (code == 57 || code == 107 || code == 10057) { - return net_error(NET_ERROR_NOT_CONNECTED, native_code); - } - if (code == 38 || code == 45 || code == 95 || code == 10045) { - return net_error(NET_ERROR_UNSUPPORTED, native_code); - } +// Compare negative codes directly: negating i64::MIN would overflow. These are +// target errno tables, not a union of numbers that happen to mean the same thing. + +#[target(os="linux")] +fun classify_native_error(code: i64) -> i32 { + if (code == -22) { return NET_ERROR_INVALID; } + if (code == -4) { return NET_ERROR_INTERRUPTED; } + if (code == -11) { return NET_ERROR_WOULD_BLOCK; } + if (code == -110) { return NET_ERROR_TIMED_OUT; } + if (code == -111) { return NET_ERROR_REFUSED; } + if (code == -104) { return NET_ERROR_RESET; } + if (code == -98) { return NET_ERROR_ADDRESS_IN_USE; } + if (code == -107) { return NET_ERROR_NOT_CONNECTED; } + if (code == -38 || code == -95) { return NET_ERROR_UNSUPPORTED; } + return NET_ERROR_OTHER; +} + +#[target(os="macos")] +fun classify_native_error(code: i64) -> i32 { + if (code == -22) { return NET_ERROR_INVALID; } + if (code == -4) { return NET_ERROR_INTERRUPTED; } + if (code == -35) { return NET_ERROR_WOULD_BLOCK; } + if (code == -60) { return NET_ERROR_TIMED_OUT; } + if (code == -61) { return NET_ERROR_REFUSED; } + if (code == -54) { return NET_ERROR_RESET; } + if (code == -48) { return NET_ERROR_ADDRESS_IN_USE; } + if (code == -57) { return NET_ERROR_NOT_CONNECTED; } + if (code == -45 || code == -78 || code == -102) { return NET_ERROR_UNSUPPORTED; } + return NET_ERROR_OTHER; +} + +#[target(os="freebsd")] +fun classify_native_error(code: i64) -> i32 { + if (code == -22) { return NET_ERROR_INVALID; } + if (code == -4) { return NET_ERROR_INTERRUPTED; } + if (code == -35) { return NET_ERROR_WOULD_BLOCK; } + if (code == -60) { return NET_ERROR_TIMED_OUT; } + if (code == -61) { return NET_ERROR_REFUSED; } + if (code == -54) { return NET_ERROR_RESET; } + if (code == -48) { return NET_ERROR_ADDRESS_IN_USE; } + if (code == -57) { return NET_ERROR_NOT_CONNECTED; } + if (code == -45 || code == -78) { return NET_ERROR_UNSUPPORTED; } + return NET_ERROR_OTHER; +} + +#[target(os="windows")] +fun classify_native_error(code: i64) -> i32 { + // -22/-95 are explicit Wave validation/unsupported results, not Winsock aliases. + if (code == -22 || code == -10022) { return NET_ERROR_INVALID; } + if (code == -10004) { return NET_ERROR_INTERRUPTED; } + if (code == -10035) { return NET_ERROR_WOULD_BLOCK; } + if (code == -10060) { return NET_ERROR_TIMED_OUT; } + if (code == -10061) { return NET_ERROR_REFUSED; } + if (code == -10054) { return NET_ERROR_RESET; } + if (code == -10048) { return NET_ERROR_ADDRESS_IN_USE; } + if (code == -10057) { return NET_ERROR_NOT_CONNECTED; } + if (code == -95 || code == -10045) { return NET_ERROR_UNSUPPORTED; } + return NET_ERROR_OTHER; +} + +#[target(os="none")] +fun classify_native_error(code: i64) -> i32 { + // No socket provider on these targets; only Wave-generated errors apply. + if (code == -22) { return NET_ERROR_INVALID; } + if (code == -95) { return NET_ERROR_UNSUPPORTED; } + return NET_ERROR_OTHER; +} + +#[target(os="unknown")] +fun classify_native_error(code: i64) -> i32 { + // Bare WebAssembly has no native socket errno namespace. + if (code == -22) { return NET_ERROR_INVALID; } + if (code == -95) { return NET_ERROR_UNSUPPORTED; } + return NET_ERROR_OTHER; +} - return net_error(NET_ERROR_OTHER, native_code); +#[target(os="wasi")] +fun classify_native_error(code: i64) -> i32 { + // No socket provider on these targets; only Wave-generated errors apply. + if (code == -22) { return NET_ERROR_INVALID; } + if (code == -95) { return NET_ERROR_UNSUPPORTED; } + return NET_ERROR_OTHER; } pub fun net_result_ok(value: T) -> NetResult { diff --git a/std/net/posix_timeout.wave b/std/net/posix_timeout.wave index 1d252bcf..5fff7920 100644 --- a/std/net/posix_timeout.wave +++ b/std/net/posix_timeout.wave @@ -12,7 +12,8 @@ import("std::sys::socket")::{MSG_DONTWAIT}; import("std::net::poll")::{net_wait_readable, net_wait_writable}; import("std::net::error")::{ NetIoResult, NetError, net_io_ok, net_io_eof, net_io_error, - net_error_from_native, NET_ERROR_INTERRUPTED, NET_ERROR_WOULD_BLOCK, + net_error, net_error_from_native, NET_ERROR_INTERRUPTED, NET_ERROR_WOULD_BLOCK, + NET_ERROR_TIMED_OUT, }; import("std::time::clock")::{time_now_monotonic_ns}; @@ -69,7 +70,7 @@ fun _net_io_timeout(fd: i64, buffer: ptr, size: i64, timeout_ms: i32, writin } var elapsed: i64 = now - start; if (elapsed >= budget) { - return net_io_error(0, -110); + return _net_io_timed_out(); } remaining = ((budget - elapsed + 999999) / 1000000) as i32; } @@ -80,7 +81,7 @@ fun _net_io_timeout(fd: i64, buffer: ptr, size: i64, timeout_ms: i32, writin ready = net_wait_readable(fd, remaining); } if (ready == 0) { - return net_io_error(0, -110); + return _net_io_timed_out(); } if (ready < 0) { error = net_error_from_native(ready); @@ -92,3 +93,8 @@ fun _net_io_timeout(fd: i64, buffer: ptr, size: i64, timeout_ms: i32, writin } return net_io_error(0, -5); } + +fun _net_io_timed_out() -> NetIoResult { + // A local deadline or poll timeout has no native errno to preserve. + return NetIoResult { count: 0, eof: false, error: net_error(NET_ERROR_TIMED_OUT, 0) }; +} diff --git a/std/task.wave b/std/task.wave index 41d2aa31..e785a4e5 100644 --- a/std/task.wave +++ b/std/task.wave @@ -384,7 +384,8 @@ export(c, "__wave_task_close_fd") fun _close_fd(fd: i64) { // Ready bits: readable=1, writable=2, error=4, hangup=8; failures are negative. // Waiters on the same descriptor share a native watch; cancellation affects only that waiter. pub fun wait_fd(fd: i64, flags: i32, timeout_ms: i64) -> Future { return __wave_async_interest(fd, flags, timeout_ms); } -pub fun sleep_ms(milliseconds: i64) -> Future { return __wave_async_sleep(milliseconds); } +// Returns 0 on completion; negative durations and deadline overflow return -22. +pub fun sleep_ms(milliseconds: i64) -> Future { return __wave_async_sleep(milliseconds); } pub fun closing_fd(fd: i64) { __wave_async_close_fd(fd); } #[target(os="linux")] diff --git a/tests/fixtures/io/tcp_read.wave b/tests/fixtures/io/tcp_read.wave index e7e07d4c..af4cb9ad 100644 --- a/tests/fixtures/io/tcp_read.wave +++ b/tests/fixtures/io/tcp_read.wave @@ -7,6 +7,15 @@ import("std::net::address")::{SocketAddrV4}; import("std::net::error")::{NetResult, NetIoResult, NET_ERROR_TIMED_OUT}; import("std::time::clock")::{time_now_monotonic_ns}; +#[target(os="linux")] +const TIMEOUT_NATIVE_CODE: i64 = 0; +#[target(os="macos")] +const TIMEOUT_NATIVE_CODE: i64 = 0; +#[target(os="freebsd")] +const TIMEOUT_NATIVE_CODE: i64 = 0; +#[target(os="windows")] +const TIMEOUT_NATIVE_CODE: i64 = -10060; + #[target(os="windows")] import("std::sys::windows::completion_port")::{ completion_port_associate, completion_port_handle, completion_port_release_executor, @@ -86,7 +95,7 @@ fun exercise(nonblocking: bool) -> i32 { var start: i64 = time_now_monotonic_ns(); while (index < 16) { var empty: NetIoResult = tcp_read_timeout(client.value, &data[0], 8, 5); - if (empty.error.kind != NET_ERROR_TIMED_OUT || empty.count != 0 || empty.eof) { + if (empty.error.kind != NET_ERROR_TIMED_OUT || empty.error.native_code != TIMEOUT_NATIVE_CODE || empty.count != 0 || empty.eof) { return 14; } index += 1; @@ -112,7 +121,7 @@ fun exercise(nonblocking: bool) -> i32 { return 19; } var immediate: NetIoResult = tcp_read_timeout(client.value, &data[0], 8, 0); - if (immediate.error.kind != NET_ERROR_TIMED_OUT) { + if (immediate.error.kind != NET_ERROR_TIMED_OUT || immediate.error.native_code != TIMEOUT_NATIVE_CODE) { return 21; } sent = tcp_write_timeout(peer.value, "x" as ptr, 1, -1); diff --git a/tests/fixtures/native_providers/async_sleep.wave b/tests/fixtures/native_providers/async_sleep.wave new file mode 100644 index 00000000..36e6fa81 --- /dev/null +++ b/tests/fixtures/native_providers/async_sleep.wave @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MPL-2.0 +import("std::task" as task); +async fun check_sleep() -> i32 { + var negative: i32 = await task::sleep_ms(-1); + var minimum: i32 = await task::sleep_ms(-9223372036854775808); + var overflow: i32 = await task::sleep_ms(9223372036854775807); + var zero: i32 = await task::sleep_ms(0); + var positive: i32 = await task::sleep_ms(1); + if (negative != -22 || minimum != -22 || overflow != -22) { return 1; } + if (zero != 0 || positive != 0) { return 2; } + return 0; +} +fun main() -> i32 { + if (task::block_on(task::sleep_ms(-1)) != -22) { return 3; } + if (task::block_on(task::sleep_ms(9223372036854775807)) != -22) { return 4; } + if (task::block_on(task::sleep_ms(0)) != 0) { return 5; } + if (task::block_on(task::sleep_ms(1)) != 0) { return 6; } + var result: i32 = task::block_on(check_sleep()); + task::shutdown(); + return result; +} diff --git a/tests/fixtures/native_providers/network_errors.wave b/tests/fixtures/native_providers/network_errors.wave new file mode 100644 index 00000000..d88f630c --- /dev/null +++ b/tests/fixtures/native_providers/network_errors.wave @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: MPL-2.0 +import("std::net::error")::{NetError, net_error_from_native, NET_ERROR_NONE, NET_ERROR_INVALID, NET_ERROR_INTERRUPTED, NET_ERROR_WOULD_BLOCK, NET_ERROR_TIMED_OUT, NET_ERROR_REFUSED, NET_ERROR_RESET, NET_ERROR_ADDRESS_IN_USE, NET_ERROR_NOT_CONNECTED, NET_ERROR_UNSUPPORTED, NET_ERROR_OTHER}; + +fun check(code: i64, kind: i32) -> bool { + var result: NetError = net_error_from_native(code); + return result.kind == kind && result.native_code == code; +} + +#[target(os="linux")] +fun platform() -> i32 { + if (!check(-22, NET_ERROR_INVALID)) { return 23; } + if (!check(-4, NET_ERROR_INTERRUPTED)) { return 5; } + if (!check(-11, NET_ERROR_WOULD_BLOCK)) { return 12; } + if (!check(-110, NET_ERROR_TIMED_OUT)) { return 111; } + if (!check(-111, NET_ERROR_REFUSED)) { return 112; } + if (!check(-104, NET_ERROR_RESET)) { return 105; } + if (!check(-98, NET_ERROR_ADDRESS_IN_USE)) { return 99; } + if (!check(-107, NET_ERROR_NOT_CONNECTED)) { return 108; } + if (!check(-38, NET_ERROR_UNSUPPORTED)) { return 39; } + if (!check(-95, NET_ERROR_UNSUPPORTED)) { return 96; } + if (!check(-35, NET_ERROR_OTHER)) { return 201; } + if (!check(-60, NET_ERROR_OTHER)) { return 201; } + if (!check(-61, NET_ERROR_OTHER)) { return 201; } + if (!check(-45, NET_ERROR_OTHER)) { return 201; } + if (!check(-10035, NET_ERROR_OTHER)) { return 201; } + return 0; +} + +#[target(os="macos")] +fun platform() -> i32 { + if (!check(-22, NET_ERROR_INVALID)) { return 23; } + if (!check(-4, NET_ERROR_INTERRUPTED)) { return 5; } + if (!check(-35, NET_ERROR_WOULD_BLOCK)) { return 36; } + if (!check(-60, NET_ERROR_TIMED_OUT)) { return 61; } + if (!check(-61, NET_ERROR_REFUSED)) { return 62; } + if (!check(-54, NET_ERROR_RESET)) { return 55; } + if (!check(-48, NET_ERROR_ADDRESS_IN_USE)) { return 49; } + if (!check(-57, NET_ERROR_NOT_CONNECTED)) { return 58; } + if (!check(-45, NET_ERROR_UNSUPPORTED)) { return 46; } + if (!check(-78, NET_ERROR_UNSUPPORTED)) { return 79; } + if (!check(-102, NET_ERROR_UNSUPPORTED)) { return 103; } + if (!check(-11, NET_ERROR_OTHER)) { return 201; } + if (!check(-38, NET_ERROR_OTHER)) { return 201; } + if (!check(-95, NET_ERROR_OTHER)) { return 201; } + if (!check(-98, NET_ERROR_OTHER)) { return 201; } + if (!check(-104, NET_ERROR_OTHER)) { return 201; } + if (!check(-107, NET_ERROR_OTHER)) { return 201; } + if (!check(-110, NET_ERROR_OTHER)) { return 201; } + if (!check(-111, NET_ERROR_OTHER)) { return 201; } + if (!check(-10035, NET_ERROR_OTHER)) { return 201; } + return 0; +} + +#[target(os="freebsd")] +fun platform() -> i32 { + if (!check(-22, NET_ERROR_INVALID)) { return 23; } + if (!check(-4, NET_ERROR_INTERRUPTED)) { return 5; } + if (!check(-35, NET_ERROR_WOULD_BLOCK)) { return 36; } + if (!check(-60, NET_ERROR_TIMED_OUT)) { return 61; } + if (!check(-61, NET_ERROR_REFUSED)) { return 62; } + if (!check(-54, NET_ERROR_RESET)) { return 55; } + if (!check(-48, NET_ERROR_ADDRESS_IN_USE)) { return 49; } + if (!check(-57, NET_ERROR_NOT_CONNECTED)) { return 58; } + if (!check(-45, NET_ERROR_UNSUPPORTED)) { return 46; } + if (!check(-78, NET_ERROR_UNSUPPORTED)) { return 79; } + if (!check(-11, NET_ERROR_OTHER)) { return 201; } + if (!check(-38, NET_ERROR_OTHER)) { return 201; } + if (!check(-95, NET_ERROR_OTHER)) { return 201; } + if (!check(-98, NET_ERROR_OTHER)) { return 201; } + if (!check(-104, NET_ERROR_OTHER)) { return 201; } + if (!check(-107, NET_ERROR_OTHER)) { return 201; } + if (!check(-110, NET_ERROR_OTHER)) { return 201; } + if (!check(-111, NET_ERROR_OTHER)) { return 201; } + if (!check(-10035, NET_ERROR_OTHER)) { return 201; } + return 0; +} + +#[target(os="windows")] +fun platform() -> i32 { + if (!check(-22, NET_ERROR_INVALID)) { return 23; } + if (!check(-10022, NET_ERROR_INVALID)) { return 23; } + if (!check(-10004, NET_ERROR_INTERRUPTED)) { return 5; } + if (!check(-10035, NET_ERROR_WOULD_BLOCK)) { return 36; } + if (!check(-10060, NET_ERROR_TIMED_OUT)) { return 61; } + if (!check(-10061, NET_ERROR_REFUSED)) { return 62; } + if (!check(-10054, NET_ERROR_RESET)) { return 55; } + if (!check(-10048, NET_ERROR_ADDRESS_IN_USE)) { return 49; } + if (!check(-10057, NET_ERROR_NOT_CONNECTED)) { return 58; } + if (!check(-95, NET_ERROR_UNSUPPORTED)) { return 96; } + if (!check(-10045, NET_ERROR_UNSUPPORTED)) { return 46; } + if (!check(-4, NET_ERROR_OTHER)) { return 201; } + if (!check(-11, NET_ERROR_OTHER)) { return 201; } + if (!check(-35, NET_ERROR_OTHER)) { return 201; } + if (!check(-38, NET_ERROR_OTHER)) { return 201; } + if (!check(-45, NET_ERROR_OTHER)) { return 201; } + if (!check(-48, NET_ERROR_OTHER)) { return 201; } + if (!check(-54, NET_ERROR_OTHER)) { return 201; } + if (!check(-57, NET_ERROR_OTHER)) { return 201; } + if (!check(-60, NET_ERROR_OTHER)) { return 201; } + if (!check(-61, NET_ERROR_OTHER)) { return 201; } + if (!check(-98, NET_ERROR_OTHER)) { return 201; } + if (!check(-104, NET_ERROR_OTHER)) { return 201; } + if (!check(-107, NET_ERROR_OTHER)) { return 201; } + if (!check(-110, NET_ERROR_OTHER)) { return 201; } + if (!check(-111, NET_ERROR_OTHER)) { return 201; } + return 0; +} + +fun main() -> i32 { + if (!check(-9223372036854775808, NET_ERROR_OTHER)) { return 202; } + if (!check(-123456789, NET_ERROR_OTHER)) { return 203; } + var zero: NetError = net_error_from_native(0); + var success: NetError = net_error_from_native(123); + if (zero.kind != NET_ERROR_NONE || zero.native_code != 0) { return 204; } + if (success.kind != NET_ERROR_NONE || success.native_code != 0) { return 205; } + return platform(); +} diff --git a/tests/fixtures/native_providers/trig_check.wave b/tests/fixtures/native_providers/trig_check.wave new file mode 100644 index 00000000..a69db8ff --- /dev/null +++ b/tests/fixtures/native_providers/trig_check.wave @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MPL-2.0 +// Inputs and references are supplied by the Rust harness from checked-in data. +fun main() -> i32 { + var i: i32 = 0; + while (i < CASES) { + var x: f64 = float_from_bits_f64(inputs[i]); + var s: f64 = float_from_bits_f64(sines[i]); + var c: f64 = float_from_bits_f64(cosines[i]); + var t: f64 = float_from_bits_f64(tangents[i]); + var actual: SinCosF64 = sin_cos_f64(x); + if (abs_f64(actual.sin - s) > 1e-12 || abs_f64(actual.cos - c) > 1e-12) { + println("sin/cos vector {} failed", i); return 1; + } + if (sin_f64(x) != actual.sin || cos_f64(x) != actual.cos) { return 2; } + var tangent: f64 = tan_f64(x); + if (abs_f64(c) >= 1e-6 && abs_f64(tangent - t) > 1e-12 + 1e-9 * abs_f64(t)) { + println("tan vector {} failed", i); return 3; + } + // Pole-near samples are checked separately: preserve side/quadrant; + // a broad absolute/relative bound detects loss of the small remainder. + if (abs_f64(c) < 1e-6) { + if (((tangent < 0.0) as i32) != ((t < 0.0) as i32) || ((actual.cos < 0.0) as i32) != ((c < 0.0) as i32)) { return 4; } + if (abs_f64(tangent - t) > 1e-8 * abs_f64(t)) { return 5; } + } + var wrapped: f64 = wrap_angle_pi_f64(x); + if (wrapped < -MATH_PI_F64 || wrapped > MATH_PI_F64) { return 6; } + if (x == 0.0) { + if (float_to_bits_f64(actual.sin) != inputs[i] || float_to_bits_f64(tangent) != inputs[i]) { return 7; } + if (float_to_bits_f64(wrapped) != inputs[i]) { return 8; } + } + i += 1; + } + i = 0; + while (i < SINGLE_CASES) { + var x: f32 = float_from_bits_f64(inputs32[i]) as f32; + var s: f64 = float_from_bits_f64(sines32[i]); + var c: f64 = float_from_bits_f64(cosines32[i]); + var t: f64 = float_from_bits_f64(tangents32[i]); + var actual: SinCosF32 = sin_cos_f32(x); + if (abs_f64(actual.sin as f64 - s) > 1e-6 || abs_f64(actual.cos as f64 - c) > 1e-6) { return 12; } + if (sin_f32(x) != actual.sin || cos_f32(x) != actual.cos) { return 13; } + var tangent: f64 = tan_f32(x) as f64; + if (abs_f64(c) >= 1e-6 && abs_f64(tangent - t) > 1e-6 + 1e-5 * abs_f64(t)) { return 14; } + if (abs_f64(c) < 1e-6 && (((tangent < 0.0) as i32) != ((t < 0.0) as i32) || abs_f64(tangent - t) > 1e-5 * abs_f64(t))) { return 15; } + i += 1; + } + var nan: f64 = nan_f64(); + var inf: f64 = infinity_f64(); + if (!is_nan_f64(sin_f64(nan)) || !is_nan_f64(cos_f64(inf)) || !is_nan_f64(tan_f64(-inf))) { return 9; } + var negative_zero: f32 = float_from_bits_f32(2147483648); + if (float_to_bits_f32(sin_f32(negative_zero)) != 2147483648) { return 10; } + if (float_to_bits_f32(tan_f32(negative_zero)) != 2147483648) { return 11; } + return 0; +} diff --git a/tests/fixtures/native_providers/trig_reference.txt b/tests/fixtures/native_providers/trig_reference.txt new file mode 100644 index 00000000..e3381cf3 --- /dev/null +++ b/tests/fixtures/native_providers/trig_reference.txt @@ -0,0 +1,496 @@ +# Generated by tools/generate_trig_vectors.py (mpmath 1.3.0, 800 digits) +# Exact input, sin, cos, tan as hexadecimal binary64 bits +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +0000000000000001 0000000000000001 3ff0000000000000 0000000000000001 +8000000000000001 8000000000000001 3ff0000000000000 8000000000000001 +01a56e1fc2f8f359 01a56e1fc2f8f359 3ff0000000000000 01a56e1fc2f8f359 +81a56e1fc2f8f359 81a56e1fc2f8f359 3ff0000000000000 81a56e1fc2f8f359 +3fb999999999999a 3fb98eaecb8bcb2c 3fefd712f9a817c1 3fb9af8877430b80 +3fe921fb54442d18 3fe6a09e667f3bcc 3fe6a09e667f3bcd 3fefffffffffffff +412e848000000000 bfd6664b2568d867 3fedf9df9906d32c bfd7e9768ab734c0 +426d1a94a2000000 bfe38f4477984352 3fe9538731dff223 bfe8b6bb0174398f +4415af1d78b58c40 bfe4a5e605fd6450 3fe872720fc60d3d bfeb06fbbe995394 +54b249ad2594c37d bfd85c5e5b929359 3fed9757496841f5 bfda5807d6f76f7d +6974e718d7d7625a bfe49b644938c64c 3fe87b4df51f679e bfeaef7845d41e88 +7e37e43c8800759c bfea2c16b010e385 bfe2699022adc4c1 3ff6be411f37ac77 +7fefffffffffffff 3f7452fc98b34e97 bfefffe62ecfab75 bf74530cfe729484 +3ff921fb54442d17 3ff0000000000000 3cb469898cc51702 4329153d9443ed0b +3ff921fb54442d18 3ff0000000000000 3c91a62633145c07 434d02967c31cdb5 +3ff921fb54442d19 3ff0000000000000 bca72cece675d1fd c33617a15494767a +400921fb54442d17 3cc469898cc51702 bff0000000000000 bcc469898cc51702 +400921fb54442d18 3ca1a62633145c07 bff0000000000000 bca1a62633145c07 +400921fb54442d19 bcb72cece675d1fd bff0000000000000 3cb72cece675d1fd +4012d97c7f3321d1 bff0000000000000 bcd34f272993d141 430a8410087262e4 +4012d97c7f3321d2 bff0000000000000 bcaa79394c9e8a0a 4333570efd768923 +4012d97c7f3321d3 bff0000000000000 3cc961b1acd85d7d c3142c0d64d5de51 +401921fb54442d17 bcd469898cc51702 3ff0000000000000 bcd469898cc51702 +401921fb54442d18 bcb1a62633145c07 3ff0000000000000 bcb1a62633145c07 +401921fb54442d19 3cc72cece675d1fd 3ff0000000000000 3cc72cece675d1fd +403ab41b09886fe9 3ff0000000000000 3ce960444b22d0e4 42f42d2fd868005a +403ab41b09886fea 3ff0000000000000 bcca7eeed374bc71 c31352e42df73873 +403ab41b09886feb 3ff0000000000000 bcf34fddda6e978e c2ea8315318b45d6 +409921fb54442d17 bd5469898cc51702 3ff0000000000000 bd5469898cc51702 +409921fb54442d18 bd31a62633145c07 3ff0000000000000 bd31a62633145c07 +409921fb54442d19 3d472cece675d1fd 3ff0000000000000 3d472cece675d1fd +413921fb54442d17 bdf469898cc51702 3ff0000000000000 bdf469898cc51702 +413921fb54442d18 bdd1a62633145c07 3ff0000000000000 bdd1a62633145c07 +413921fb54442d19 3de72cece675d1fd 3ff0000000000000 3de72cece675d1fd +427921fb54442d17 bf346989873b9824 3fefffffe5f57002 bf34698997d814c5 +427921fb54442d18 bf11a62632db1824 3feffffffec88318 bf11a6263386e3cc +427921fb54442d19 3f272cece46f2b3d 3feffffff79b9632 3f272cecea831f7d +463921fb54442d17 3fdbb6fcb05651e8 3fecd80c17e27101 3fdebf4fad827a6f +463921fb54442d18 3fe179d4013ca110 3feace7ca21233e9 3fe4dc923f42acd3 +463921fb54442d19 3fe4ccd2ae2a4f4c 3fe8515c83896140 3feb5ef986a7b08c +5f3921fb54442d17 3fee415539146db5 bfd4d82bf7beb887 c0073940681aa065 +5f3921fb54442d18 3fc7df6db2d7b59b 3fef7042ff9c45fe 3fc84c936a2c9206 +5f3921fb54442d19 bfeff8437ce67a62 3fa63f082ae7a787 c036fe5048b40feb +7e7921fb54442d17 bfa411a59e922293 bfeff9b45515b98b 3fa41599292e9ba9 +7e7921fb54442d18 3feb921eb761288b 3fe03e577e2d1264 3ffb284e07b1292a +7e7921fb54442d19 bfec93aa7df06509 3fdccce51f63df9d bfffc069bb33436d +001f0c8a30877858 001f0c8a30877858 3ff0000000000000 001f0c8a30877858 +0125810c2f43c2fb 0125810c2f43c2fb 3ff0000000000000 0125810c2f43c2fb +023708159e4cf624 023708159e4cf624 3ff0000000000000 023708159e4cf624 +034f5038f534d378 034f5038f534d378 3ff0000000000000 034f5038f534d378 +045ee33ec8349f3c 045ee33ec8349f3c 3ff0000000000000 045ee33ec8349f3c +05663f9b60ce56fa 05663f9b60ce56fa 3ff0000000000000 05663f9b60ce56fa +067719680cdb2fa3 067719680cdb2fa3 3ff0000000000000 067719680cdb2fa3 +078e9ae2b81f0a20 078e9ae2b81f0a20 3ff0000000000000 078e9ae2b81f0a20 +089b15f36e243a0b 089b15f36e243a0b 3ff0000000000000 089b15f36e243a0b +09a8e6168f51ba24 09a8e6168f51ba24 3ff0000000000000 09a8e6168f51ba24 +0ab02a32cb5ea4c8 0ab02a32cb5ea4c8 3ff0000000000000 0ab02a32cb5ea4c8 +0bcc29e928c28ea4 0bcc29e928c28ea4 3ff0000000000000 0bcc29e928c28ea4 +0cda013f84be3254 0cda013f84be3254 3ff0000000000000 0cda013f84be3254 +0de574aa083e0050 0de574aa083e0050 3ff0000000000000 0de574aa083e0050 +0ef2ae0327f0e166 0ef2ae0327f0e166 3ff0000000000000 0ef2ae0327f0e166 +10000bfeae3c89dd 10000bfeae3c89dd 3ff0000000000000 10000bfeae3c89dd +111297752b711d72 111297752b711d72 3ff0000000000000 111297752b711d72 +122238629e16184c 122238629e16184c 3ff0000000000000 122238629e16184c +13363eed2d1c8d28 13363eed2d1c8d28 3ff0000000000000 13363eed2d1c8d28 +144b29aeb3947a34 144b29aeb3947a34 3ff0000000000000 144b29aeb3947a34 +155d0714ef049414 155d0714ef049414 3ff0000000000000 155d0714ef049414 +16620f8232ee0ce1 16620f8232ee0ce1 3ff0000000000000 16620f8232ee0ce1 +177f02d0be00d240 177f02d0be00d240 3ff0000000000000 177f02d0be00d240 +1886e7c47b0097d2 1886e7c47b0097d2 3ff0000000000000 1886e7c47b0097d2 +199b002080d12fa2 199b002080d12fa2 3ff0000000000000 199b002080d12fa2 +1aa8a30d65a49e3e 1aa8a30d65a49e3e 3ff0000000000000 1aa8a30d65a49e3e +1bbd18f26d5d3582 1bbd18f26d5d3582 3ff0000000000000 1bbd18f26d5d3582 +1cc485203e21496c 1cc485203e21496c 3ff0000000000000 1cc485203e21496c +1dd9a43c78a56472 1dd9a43c78a56472 3ff0000000000000 1dd9a43c78a56472 +1ee1bebdc71e1f16 1ee1bebdc71e1f16 3ff0000000000000 1ee1bebdc71e1f16 +1ffa3861280be1fe 1ffa3861280be1fe 3ff0000000000000 1ffa3861280be1fe +21066e66cf8fdf6a 21066e66cf8fdf6a 3ff0000000000000 21066e66cf8fdf6a +221a78c745e4031c 221a78c745e4031c 3ff0000000000000 221a78c745e4031c +23295a17940d01c3 23295a17940d01c3 3ff0000000000000 23295a17940d01c3 +24393f43bba001aa 24393f43bba001aa 3ff0000000000000 24393f43bba001aa +254e5e6191ce02da 254e5e6191ce02da 3ff0000000000000 254e5e6191ce02da +265f62d0a961096c 265f62d0a961096c 3ff0000000000000 265f62d0a961096c +2763c21ba8e117b6 2763c21ba8e117b6 3ff0000000000000 2763c21ba8e117b6 +287216a9fd45f3b0 287216a9fd45f3b0 3ff0000000000000 287216a9fd45f3b0 +298f9770de338970 298f9770de338970 3ff0000000000000 298f9770de338970 +2a97e3835bfeb13a 2a97e3835bfeb13a 3ff0000000000000 2a97e3835bfeb13a +2bac5b3c2f943268 2bac5b3c2f943268 3ff0000000000000 2bac5b3c2f943268 +2cb5e27848d8be12 2cb5e27848d8be12 3ff0000000000000 2cb5e27848d8be12 +2dc97936c9cf2140 2dc97936c9cf2140 3ff0000000000000 2dc97936c9cf2140 +2ede35dd905e3daa 2ede35dd905e3daa 3ff0000000000000 2ede35dd905e3daa +2fe0322ca82f5fde 2fe0322ca82f5fde 3ff0000000000000 2fe0322ca82f5fde +30f369a3a1d05012 30f369a3a1d05012 3ff0000000000000 30f369a3a1d05012 +320a01d82a7ce7ad 320a01d82a7ce7ad 3ff0000000000000 320a01d82a7ce7ad +3318984f54ede04f 3318984f54ede04f 3ff0000000000000 3318984f54ede04f +342da41a77292fdf 342da41a77292fdf 3ff0000000000000 342da41a77292fdf +3538de233f13c5db 3538de233f13c5db 3ff0000000000000 3538de233f13c5db +3644a3eb3b96188c 3644a3eb3b96188c 3ff0000000000000 3644a3eb3b96188c +3755640fa556ef83 3755640fa556ef83 3ff0000000000000 3755640fa556ef83 +386bbca1f3948aca 386bbca1f3948aca 3ff0000000000000 386bbca1f3948aca +3972bb99d98caa53 3972bb99d98caa53 3ff0000000000000 3972bb99d98caa53 +3a89d898ed038163 3a89d898ed038163 3ff0000000000000 3a89d898ed038163 +3b9701d08590293b 3b9701d08590293b 3ff0000000000000 3b9701d08590293b +3ca26f97301bc67c 3ca26f97301bc67c 3ff0000000000000 3ca26f97301bc67c +3dba782f6bdd0ed7 3dba782f6bdd0ed7 3ff0000000000000 3dba782f6bdd0ed7 +3ec1db041620580e 3ec1db041620493b 3fefffffffffb04c 3ec1db04162075b4 +3fde33dd108d31cd 3fdd180e4b190223 3fec809b80ed9c17 3fe055043ed1850b +40efb002aca38f14 bfc9f289fd435191 bfef55ead042460c 3fca7f603789b11d +41f9049c05675626 3fefff76399a5989 bf8779a24aa2dd24 c055cf12cbe5cf69 +4308a600e728f8f2 bfe1ab8e0adf5f6d bfeaadcf9039f5ee 3fe531c453b92002 +4412de3c3cea9847 bfef7b59ad5b2467 bfc6f0f88e982d4d 4015f4da0b7df2a8 +4528f83e6319e7c7 bfe67b8ed1af6d67 bfe6c571aa51e5b8 3fef982b592ea473 +4633c1fc259c6259 3fdc55859a4048a2 bfecb1704bd6070c bfdf997d653525d9 +474ac5c18039c7b6 bfef92c42b151d4c bfc4d54be79f1f04 40183f9b7cc62e8a +4854df049716d7ea 3fcf0fcdc03a5b8a bfef0b21ec1168d6 bfd00268565c5045 +4960795265f4bc56 bfef9deecfccc870 bfc3bf14972d38a2 40199e4d8f28d2c5 +4a7cc4c8e107dc36 bfef964abfe19550 3fc47f168dce04c6 c018a859605a418e +4b8a4c6d90402910 bfeed6ed4f31b29a bfd1142e5aa074ea 400ce438c7f00a5c +4c9856d10de8c22e 3fe91f8d743682e7 bfe3d1daa84d5555 bff4480984425a69 +4daee71c772bf71e 3fd32e989045cce4 3fee8764bda26dab 3fd41b3a07b45c33 +4ebd699d0dee83b4 bfec827024d102af 3fdd10e0bbe6b6be bfff632e7a7c2b92 +4fc1e5f85cdff778 bfbbb3f963e849db bfefcfe4849ea653 3fbbddde1fbce465 +50d30492350500aa bfd0c7141731936e 3feee1802528dc9f bfd162bbfe20713e +51ec404cf016a0cf 3fd8cd1e85e782d4 3fed7fe3b7434012 3fdae747ebda96f5 +52fb994d1c8c7b4c 3fe8497d19e68afd bfe4d6036bc4298d bff2a66c2b72d3a2 +540fcc049b7b67f0 3fee4c0b974d9768 3fd49990ffd8c2d9 40078826b5fcfa47 +551b27c89d6d7ead bfdf2bd958404b92 bfebf2aca8b295ba 3fe1d86812bcd49e +56244dc0988c1538 3fef59e9a3410ef9 3fc9a4dd4099d326 40138f96a1e7ff51 +573da781684d5e3d bfedf180750bb490 bfd692e89ef0d1b3 400539300aa16825 +58471014e44a6b74 3fed9bf2f213a1d7 bfd845ee89900164 c003846de997d12a +595195031b2e58c4 bfe6be9a0f382a69 3fe6827acde31473 bff02abc2ecbaefd +5a609b52b3a1b6ca bfef1ccc9e302f89 3fcdefc549938236 c010a0e37aec0b75 +5b7b51ab2f8f9136 3fef9c382f2babaf 3fc3eac7f7192a92 401964b772101ea7 +5c87ecb8f7f8fdc4 3feab58ba17bd738 3fe19fdae7e9f100 3ff83f55316c47d2 +5d9bbb2a46b8ddc7 bfdcc4826c97d7b5 bfec95c6fab2693e 3fe01a28552454ee +5eaaf960f0156254 3fd082e61f43eea7 3feeeaaea910ff9c 3fd11700adcb8629 +5fb28901ae8bfcee bfd3548a1c80dc0f 3fee81687244dc05 bfd446f9666fdf63 +60cf6c1f87287d44 bfcb40e6263d41e2 3fef44286d6c97a8 bfcbe4a221967be7 +61d9d8471de1373c bfed930f73c3eda2 bfd871207786ccdf 40035c1e62ddc81f +62e6148d3bdd5766 bfef90bd285c5b57 bfc5063a13d6bace 401805a168dd98e2 +63f4f083384e226a bfc0928ead764268 3fefbb0c47484eda bfc0b691ee6ed02f +650a92226cbc602e 3fea7f137debbb04 bfe1f156323ce03b bff7a0a60e2794f1 +6614d993d17d8ac0 bfe7096734cbfe4f bfe635e75451e455 3ff0985c0f0eaf25 +67260dda8750386b 3fef3f127bd1cca2 bfcb9d9b1783c479 c0121a8409e74850 +683935349f7a6a5b bfefdaf6b8ca4508 bfb850c04f4ea9d7 4024f61d781be59d +694747506f0128ec 3fef4df102cae212 bfca8ad4439be743 c012dee50b3299e8 +6a50eb04bc9bd31e 3fc648921738f51e 3fef82e812e13fda 3fc6a1080a0c5f0d +6b67c0d61ed65e4f bfe5bfd448d442d1 3fe779014a6fd4b3 bfeda68cf7223e5d +6c784982ba0b62dc 3febec41b876a5f7 bfdf42d26c4f2f57 bffc953bd7b02ff3 +6d88ae5a63da6760 bfc9aef9c1c85b80 bfef596533705db4 3fca377854894665 +6e96306205bfe007 bfdaa4a50da8dea4 bfed1864baab4d15 3fdd4d948e32f686 +6face27deda670fa bfee189bfce3fdbf 3fd5befeca9ec28b c00624c80fde1713 +70b2eeea97be28de bfe03be17cfd139d 3feb9391bd793b70 bfe2d6875999c456 +71cc41e567927eaa 3feb0405af3c801e bfe1269d767591bd bff933f3144ddfc9 +72d832074c3b77ed 3fe7ff19dcbe2ecd bfe52b8492471117 bff222dfe5b6040f +73efdc01590e5e9e 3fdebb7844bd1cd0 3fec11b8b56f2ddd 3fe1849c1423f660 +74f1700a4f8811b2 bfe9b543be006437 3fe30e188fb79109 bff5961a54236e7f +760cfef91b61bc1c 3fbf5e15bd51b62e bfefc245b94de69b bfbf9b0d49b68b3d +771b605ece7530f4 3fba493689c92b40 bfefd4b37486d7c3 bfba6cf82d40c911 +7823897091de25a8 bfb387ef1031c1f5 3fefe81fbd1778d5 bfb3968c8c031057 +79373eb6fa2dee12 bfe0b27ae31d6547 bfeb4c657ba09359 3fe392ab3b242996 +7a4e6e4eec40a6e6 3fdbd59fc60145a9 3fecd0ab116b7916 3fdee9355726e6d7 +7b5b8329702692b4 3feffd388bc2744a bf9aabbbc65f9c67 c04330c3c97cb67e +7c66f25a3d66c5e8 bf59fa58e76488c9 bfeffffd5d25b540 3f59fa5b0b3edca1 +7d78dc46f9daf1f0 3fe86a89a4c717ba bfe4af3f4800c864 bff2e2f0a1d5e613 +7e8adbb529a5b5e4 bfc05d3ad29717d2 3fefbcc71111bd51 bfc07fe3f2dc877f +7f9b8384c1bc5bd4 bfed1b4bdef61e13 3fda97f33e9d0b4c c0018311a5b533f3 +6048573636a35abe 3fb368ce89219ea0 3fefe86bb706ea88 3fb37726602bd576 +5a20a3cabde702ce bfe5b635e7c40c80 3fe781e73a13d11a bfed8e3bc623c2ea +779695de42ce3386 bfec6214456a1bfb 3fdd8e7e6cd82258 bffebac02cffe265 +72804cad493011c5 bfde788dc8cd7eac bfec23efcb571502 3fe1533930369ef2 +77ff0603b34f8a05 bfe0b5783b0b03af 3feb4a9121f0aa78 bfe3977c849d1ab9 +498796a299efdcd8 3fede98f08dcb51c 3fd6bce10b4db012 40050c6c5e82916e +76c9af9015126c79 bfe8d2e7808a6597 3fe431880c388d00 bff3ab36563ec8b9 +6d7471dcf84f217b bfebf8e2802e7a2d bfdf15891f2e4c2a 3ffccbe052a5df8c +51fe8e7dc891b61f bfaa784886c950f5 3feff50b82f522ff bfaa815b7549a306 +428eac3caaa861f0 bfee0d088008f1d2 3fd5feaae15caea0 c005dc41dd2f1ecd +5425ceb684ad01f8 bfdf4367b45e507c bfebec17efc4284c 3fe1ea1c4f4b79b5 +4e1e73021ba3465b bfed307dee44145e bfda3a6192f2e4d5 4001ce7927430039 +76c0226b6b366794 3fdff4fa6b39306f 3febb9a8b29997d3 3fe2712cad4e4c86 +4bb0915c8d3d71ae 3fcc09db3b50b4b0 bfef390b6d8731ed bfccbc855551e65a +49dd4ce25d3d02f8 3fe28cf13ce63ba1 bfea130f11015cf1 bfe6c429e758ac56 +54ab57555db44810 3fe911d48bb8a5fe bfe3e3333be7dfb7 bff42b4ec3f0963b +46eb689a0d2f68b4 3fefc582eb4c36f1 bfbe8956f935d070 c020a5a991ef83ce +4e7c3f32fb894722 bfd5928b3c4b4524 3fee209a4e1eede1 bfd6e9cfee15d252 +449b1e74bf9def68 3fe547459c3f088b bfe7e6810e149ad0 bfec7d4b5a74ccea +77824089a485562e 3fddfbecf4b2526b 3fec4553c5b2da03 3fe0f83a12cc93ee +5f7479355f9fa896 bfe21ee4d2fe97a7 3fea600073fc2d10 bfe5fc3adbf9cba7 +51dc76e954a8a53e 3fefffb064ebf200 bf81d8206565d656 c05cb10f1090d360 +544e444a0a68e409 3fc909f3047fae10 bfef61bc2a518fe7 bfc98839c1615a3c +63803f4341a57a0c bfeee79cab0f14e0 bfd099d400b8af48 400dc93da1ea523a +65eb1770e1363163 3fe81919d8459fb9 3fe50de73d7fd833 3ff250249dc3bfd1 +609fcb40b6ce5a42 bfe163fd84f9ad03 bfeadcac8fe8b212 3fe4b789d0fcaad9 +70ff067b86d2d84f bfeff4904c9a08ad bfab0b6fa3cd0197 4032e7bbe4e01650 +6f64c05186a6c022 3fbbaacac08e0042 3fefd0047b5043bd 3fbbd485a3336917 +5f42eff3bb7b680e 3fecbfa3b8107911 bfdc1bb66e440394 c0005d4fcf88c2a8 +746cc8cff7087530 3febe8d3115d3670 3fdf4f12944c60c1 3ffc868ab09dc484 +72e5f53e430dc0c6 bfd758560675b299 3fedcb901aa7a8e7 bfd9129538a3c8fd +6da248d3d2fae318 bfde8cb135471d5e bfec1e79ddc75703 3fe1620bfba59b95 +783bcdd9b18c659a 3fe4ffb105ef572c bfe8257d28132e2b bfebd41e8ee14069 +67607b59ec9bb1a6 3fedc6e784450b68 bfd770107a094819 c00453d8cdbddc59 +57cd82f5d727c49d bfe6ae85d51b1fd9 3fe692ae676deb03 bff013bc022c83b9 +43a2ee37306e278c bfe2db088224146e bfe9dacebf57b3e4 3fe75658f1ab3f06 +59a005573dcecc78 3fefe471c2a7ded4 bfb4facea1d37fd2 c028528b200fa878 +6eb99f5b943c76f4 3fea974923c86c24 3fe1cd61a47513c2 3ff7e620bbd808fb +758047f5c64b713e bfd0e47112fd20e0 3feedd7f658a620a bfd1836e8f31f57a +573d1bf5d8bb1683 bfdcc4f5218081ff bfec95aa1e4e5b22 3fe01a78cbe593a7 +72045a7225e384d0 3fec3b71a67e2264 bfde21159f990b85 bffdfc34969d989e +54dd84f6e091b8b0 3fe4582a3ab78ab0 3fe8b347eb44264a 3fea5b5575abc9ee +7949c0213085d48f bfd6e5311f0f245f 3fede1de0ec6ac7a bfd884906eed344c +47d371072d7c9860 3feafa92c6f5635d bfe13576a771907c bff9156b1dce31a0 +7420667c243834a4 3fe825290ff7e266 bfe50011b78091a1 bff2656519560c9f +545fd8bd04b0ee09 3fee1de342eb4f74 bfd5a1aff0118cd9 c00646b0035b292d +54133fc370f869b4 3fed14eb4fff9e43 3fdab3ccf053c462 40016cfb9c34f432 +5aed620c885b1412 bfe6de5d48702451 bfe66235338382dd 3ff058bf865b4c8b +6c6d5d6829eac918 3fea64a3497f52ba bfe2182382f97a49 bff7569a4c0e5f1e +78f660cd6f92845e bfe0b793734af274 bfeb4946e34a07b5 3fe39ae201f68b60 +7cc6d5af3991cf71 3fe38eb37d606b7b bfe953f726d1c564 bfe8b59698862010 +54dba7dffdec377c bfdde44e558da20d bfec4b93e136de44 3fe0e71f457dfa8d +7f59d8fcbe13eefe 3fefaadf0ef0c234 3fc267b09f0e807b 401b8785fc6ca2b8 +735f287340cf3940 bfe162d1af53cd70 bfeadd6ea3e2fe3b 3fe4b58f01dd14de +4290c320eaab4410 3fe4b781a774f9cb 3fe8638803e742cc 3feb2e9d34e5d7e7 +5a7d6824e89aed52 bfe96505cbf8846c bfe378886e79f61c 3ff4de29cbcf5b4d +45b84839709c60c5 bfeaa98dfab0f14b 3fe1b1f9741494ea bff81ba981fd8cbe +47ee831055f8d972 3fede49ce044f826 bfd6d6d6c4551896 c004f108b0e4e419 +571c9bfc11bd1454 3fef6755e64ce939 bfc89899862c2ae7 c0146daab31ad51a +57bb81683bb47276 bfda3a846d730f18 bfed307619ebd216 3fdcc1126cc39140 +66de1d4470ba365a bfeb69a12540012c bfe08250b3f27175 3ffa913f043729a9 +7568586841528e18 3feedc4932adcd3c bfd0ed49baa115af c00d2babe4fc51c2 +72935398ea6f7e75 bfe7fc4c6b739d8a bfe52eb16112c2eb 3ff21e0a0f773d0f +429ffcbcf6d71f54 bfeffb480cb29dd8 3fa16012dd7033fb c03d733dff81700e +5e9c2cd051d6a114 bfd3754f0d955b88 bfee7c32a8b68c90 3fd46cd65f177965 +4db80a37872416c4 bf91a943e26756a0 bfeffec80f20ced6 3f91a9f012f24ab6 +7d66ec9f42c8a389 bfe6681f7c1ad69d 3fe6d8919d3d2a77 bfef627fb68ca04c +74210b7a10c5cbf4 3fef7bbede33fd39 3fc6e849113597ca 4015fd73e9c4c1b5 +55567b06985ba6d2 3febf6a337f05f68 3fdf1d9e809321e4 3ffcc2158f07fd9b +49fc3085c40ac0d2 bfeb36fe141cdb9c 3fe0d5473f8d601c bff9de2d2a3342c8 +77b5ee1fa53e7ae0 bfe32ce3a3d92511 3fe99e540e32ae0a bfe7f3b005ac3313 +5da119f5e03bb1c4 3fdea4f5badc95cd 3fec17df18100d7f 3fe173f4653e7b37 +6e79128bb9a656ac bfe2d519b008b2f3 3fe9df215de804d0 bfe74b1c2183c7f9 +59cb7b7b3406f2d8 bfee1bc3abf28a9e 3fd5ad7f907ca286 c00638fbb4ddc074 +55dacaff9b9a67e6 3fbfdba7bcf9ed2c 3fefc051b177ac03 3fc00dc66f755c0f +64be8340b1988acc bfefc4cedd573d75 bfbeb8084ffb4b48 40208bfe0e64109a +4707d2c89e3078d1 bfed09604d3b15cf 3fdae5dd51fef9b6 c00145aecc8f5177 +4a621ba100b3b836 bfd1e5150dd774b3 bfeeb9421479e734 3fd2a3643912d86f +69d710f107389d90 3feeff81b2e4e007 bfcfc773a4bceaed c00f36aa450b857a +6d91c8d6153775b0 3fe25f1412e8276e 3fea3373cf352859 3fe67000742bce07 +8000000000000001 8000000000000001 3ff0000000000000 8000000000000001 +81a56e1fc2f8f359 81a56e1fc2f8f359 3ff0000000000000 81a56e1fc2f8f359 +bfb999999999999a bfb98eaecb8bcb2c 3fefd712f9a817c1 bfb9af8877430b80 +bfe921fb54442d18 bfe6a09e667f3bcc 3fe6a09e667f3bcd bfefffffffffffff +c12e848000000000 3fd6664b2568d867 3fedf9df9906d32c 3fd7e9768ab734c0 +c26d1a94a2000000 3fe38f4477984352 3fe9538731dff223 3fe8b6bb0174398f +c415af1d78b58c40 3fe4a5e605fd6450 3fe872720fc60d3d 3feb06fbbe995394 +d4b249ad2594c37d 3fd85c5e5b929359 3fed9757496841f5 3fda5807d6f76f7d +e974e718d7d7625a 3fe49b644938c64c 3fe87b4df51f679e 3feaef7845d41e88 +fe37e43c8800759c 3fea2c16b010e385 bfe2699022adc4c1 bff6be411f37ac77 +ffefffffffffffff bf7452fc98b34e97 bfefffe62ecfab75 3f74530cfe729484 +bff921fb54442d17 bff0000000000000 3cb469898cc51702 c329153d9443ed0b +bff921fb54442d18 bff0000000000000 3c91a62633145c07 c34d02967c31cdb5 +bff921fb54442d19 bff0000000000000 bca72cece675d1fd 433617a15494767a +c00921fb54442d17 bcc469898cc51702 bff0000000000000 3cc469898cc51702 +c00921fb54442d18 bca1a62633145c07 bff0000000000000 3ca1a62633145c07 +c00921fb54442d19 3cb72cece675d1fd bff0000000000000 bcb72cece675d1fd +c012d97c7f3321d1 3ff0000000000000 bcd34f272993d141 c30a8410087262e4 +c012d97c7f3321d2 3ff0000000000000 bcaa79394c9e8a0a c333570efd768923 +c012d97c7f3321d3 3ff0000000000000 3cc961b1acd85d7d 43142c0d64d5de51 +c01921fb54442d17 3cd469898cc51702 3ff0000000000000 3cd469898cc51702 +c01921fb54442d18 3cb1a62633145c07 3ff0000000000000 3cb1a62633145c07 +c01921fb54442d19 bcc72cece675d1fd 3ff0000000000000 bcc72cece675d1fd +c03ab41b09886fe9 bff0000000000000 3ce960444b22d0e4 c2f42d2fd868005a +c03ab41b09886fea bff0000000000000 bcca7eeed374bc71 431352e42df73873 +c03ab41b09886feb bff0000000000000 bcf34fddda6e978e 42ea8315318b45d6 +c09921fb54442d17 3d5469898cc51702 3ff0000000000000 3d5469898cc51702 +c09921fb54442d18 3d31a62633145c07 3ff0000000000000 3d31a62633145c07 +c09921fb54442d19 bd472cece675d1fd 3ff0000000000000 bd472cece675d1fd +c13921fb54442d17 3df469898cc51702 3ff0000000000000 3df469898cc51702 +c13921fb54442d18 3dd1a62633145c07 3ff0000000000000 3dd1a62633145c07 +c13921fb54442d19 bde72cece675d1fd 3ff0000000000000 bde72cece675d1fd +c27921fb54442d17 3f346989873b9824 3fefffffe5f57002 3f34698997d814c5 +c27921fb54442d18 3f11a62632db1824 3feffffffec88318 3f11a6263386e3cc +c27921fb54442d19 bf272cece46f2b3d 3feffffff79b9632 bf272cecea831f7d +c63921fb54442d17 bfdbb6fcb05651e8 3fecd80c17e27101 bfdebf4fad827a6f +c63921fb54442d18 bfe179d4013ca110 3feace7ca21233e9 bfe4dc923f42acd3 +c63921fb54442d19 bfe4ccd2ae2a4f4c 3fe8515c83896140 bfeb5ef986a7b08c +df3921fb54442d17 bfee415539146db5 bfd4d82bf7beb887 40073940681aa065 +df3921fb54442d18 bfc7df6db2d7b59b 3fef7042ff9c45fe bfc84c936a2c9206 +df3921fb54442d19 3feff8437ce67a62 3fa63f082ae7a787 4036fe5048b40feb +fe7921fb54442d17 3fa411a59e922293 bfeff9b45515b98b bfa41599292e9ba9 +fe7921fb54442d18 bfeb921eb761288b 3fe03e577e2d1264 bffb284e07b1292a +fe7921fb54442d19 3fec93aa7df06509 3fdccce51f63df9d 3fffc069bb33436d +801f0c8a30877858 801f0c8a30877858 3ff0000000000000 801f0c8a30877858 +8125810c2f43c2fb 8125810c2f43c2fb 3ff0000000000000 8125810c2f43c2fb +823708159e4cf624 823708159e4cf624 3ff0000000000000 823708159e4cf624 +834f5038f534d378 834f5038f534d378 3ff0000000000000 834f5038f534d378 +845ee33ec8349f3c 845ee33ec8349f3c 3ff0000000000000 845ee33ec8349f3c +85663f9b60ce56fa 85663f9b60ce56fa 3ff0000000000000 85663f9b60ce56fa +867719680cdb2fa3 867719680cdb2fa3 3ff0000000000000 867719680cdb2fa3 +878e9ae2b81f0a20 878e9ae2b81f0a20 3ff0000000000000 878e9ae2b81f0a20 +889b15f36e243a0b 889b15f36e243a0b 3ff0000000000000 889b15f36e243a0b +89a8e6168f51ba24 89a8e6168f51ba24 3ff0000000000000 89a8e6168f51ba24 +8ab02a32cb5ea4c8 8ab02a32cb5ea4c8 3ff0000000000000 8ab02a32cb5ea4c8 +8bcc29e928c28ea4 8bcc29e928c28ea4 3ff0000000000000 8bcc29e928c28ea4 +8cda013f84be3254 8cda013f84be3254 3ff0000000000000 8cda013f84be3254 +8de574aa083e0050 8de574aa083e0050 3ff0000000000000 8de574aa083e0050 +8ef2ae0327f0e166 8ef2ae0327f0e166 3ff0000000000000 8ef2ae0327f0e166 +90000bfeae3c89dd 90000bfeae3c89dd 3ff0000000000000 90000bfeae3c89dd +911297752b711d72 911297752b711d72 3ff0000000000000 911297752b711d72 +922238629e16184c 922238629e16184c 3ff0000000000000 922238629e16184c +93363eed2d1c8d28 93363eed2d1c8d28 3ff0000000000000 93363eed2d1c8d28 +944b29aeb3947a34 944b29aeb3947a34 3ff0000000000000 944b29aeb3947a34 +955d0714ef049414 955d0714ef049414 3ff0000000000000 955d0714ef049414 +96620f8232ee0ce1 96620f8232ee0ce1 3ff0000000000000 96620f8232ee0ce1 +977f02d0be00d240 977f02d0be00d240 3ff0000000000000 977f02d0be00d240 +9886e7c47b0097d2 9886e7c47b0097d2 3ff0000000000000 9886e7c47b0097d2 +999b002080d12fa2 999b002080d12fa2 3ff0000000000000 999b002080d12fa2 +9aa8a30d65a49e3e 9aa8a30d65a49e3e 3ff0000000000000 9aa8a30d65a49e3e +9bbd18f26d5d3582 9bbd18f26d5d3582 3ff0000000000000 9bbd18f26d5d3582 +9cc485203e21496c 9cc485203e21496c 3ff0000000000000 9cc485203e21496c +9dd9a43c78a56472 9dd9a43c78a56472 3ff0000000000000 9dd9a43c78a56472 +9ee1bebdc71e1f16 9ee1bebdc71e1f16 3ff0000000000000 9ee1bebdc71e1f16 +9ffa3861280be1fe 9ffa3861280be1fe 3ff0000000000000 9ffa3861280be1fe +a1066e66cf8fdf6a a1066e66cf8fdf6a 3ff0000000000000 a1066e66cf8fdf6a +a21a78c745e4031c a21a78c745e4031c 3ff0000000000000 a21a78c745e4031c +a3295a17940d01c3 a3295a17940d01c3 3ff0000000000000 a3295a17940d01c3 +a4393f43bba001aa a4393f43bba001aa 3ff0000000000000 a4393f43bba001aa +a54e5e6191ce02da a54e5e6191ce02da 3ff0000000000000 a54e5e6191ce02da +a65f62d0a961096c a65f62d0a961096c 3ff0000000000000 a65f62d0a961096c +a763c21ba8e117b6 a763c21ba8e117b6 3ff0000000000000 a763c21ba8e117b6 +a87216a9fd45f3b0 a87216a9fd45f3b0 3ff0000000000000 a87216a9fd45f3b0 +a98f9770de338970 a98f9770de338970 3ff0000000000000 a98f9770de338970 +aa97e3835bfeb13a aa97e3835bfeb13a 3ff0000000000000 aa97e3835bfeb13a +abac5b3c2f943268 abac5b3c2f943268 3ff0000000000000 abac5b3c2f943268 +acb5e27848d8be12 acb5e27848d8be12 3ff0000000000000 acb5e27848d8be12 +adc97936c9cf2140 adc97936c9cf2140 3ff0000000000000 adc97936c9cf2140 +aede35dd905e3daa aede35dd905e3daa 3ff0000000000000 aede35dd905e3daa +afe0322ca82f5fde afe0322ca82f5fde 3ff0000000000000 afe0322ca82f5fde +b0f369a3a1d05012 b0f369a3a1d05012 3ff0000000000000 b0f369a3a1d05012 +b20a01d82a7ce7ad b20a01d82a7ce7ad 3ff0000000000000 b20a01d82a7ce7ad +b318984f54ede04f b318984f54ede04f 3ff0000000000000 b318984f54ede04f +b42da41a77292fdf b42da41a77292fdf 3ff0000000000000 b42da41a77292fdf +b538de233f13c5db b538de233f13c5db 3ff0000000000000 b538de233f13c5db +b644a3eb3b96188c b644a3eb3b96188c 3ff0000000000000 b644a3eb3b96188c +b755640fa556ef83 b755640fa556ef83 3ff0000000000000 b755640fa556ef83 +b86bbca1f3948aca b86bbca1f3948aca 3ff0000000000000 b86bbca1f3948aca +b972bb99d98caa53 b972bb99d98caa53 3ff0000000000000 b972bb99d98caa53 +ba89d898ed038163 ba89d898ed038163 3ff0000000000000 ba89d898ed038163 +bb9701d08590293b bb9701d08590293b 3ff0000000000000 bb9701d08590293b +bca26f97301bc67c bca26f97301bc67c 3ff0000000000000 bca26f97301bc67c +bdba782f6bdd0ed7 bdba782f6bdd0ed7 3ff0000000000000 bdba782f6bdd0ed7 +bec1db041620580e bec1db041620493b 3fefffffffffb04c bec1db04162075b4 +bfde33dd108d31cd bfdd180e4b190223 3fec809b80ed9c17 bfe055043ed1850b +c0efb002aca38f14 3fc9f289fd435191 bfef55ead042460c bfca7f603789b11d +c1f9049c05675626 bfefff76399a5989 bf8779a24aa2dd24 4055cf12cbe5cf69 +c308a600e728f8f2 3fe1ab8e0adf5f6d bfeaadcf9039f5ee bfe531c453b92002 +c412de3c3cea9847 3fef7b59ad5b2467 bfc6f0f88e982d4d c015f4da0b7df2a8 +c528f83e6319e7c7 3fe67b8ed1af6d67 bfe6c571aa51e5b8 bfef982b592ea473 +c633c1fc259c6259 bfdc55859a4048a2 bfecb1704bd6070c 3fdf997d653525d9 +c74ac5c18039c7b6 3fef92c42b151d4c bfc4d54be79f1f04 c0183f9b7cc62e8a +c854df049716d7ea bfcf0fcdc03a5b8a bfef0b21ec1168d6 3fd00268565c5045 +c960795265f4bc56 3fef9deecfccc870 bfc3bf14972d38a2 c0199e4d8f28d2c5 +ca7cc4c8e107dc36 3fef964abfe19550 3fc47f168dce04c6 4018a859605a418e +cb8a4c6d90402910 3feed6ed4f31b29a bfd1142e5aa074ea c00ce438c7f00a5c +cc9856d10de8c22e bfe91f8d743682e7 bfe3d1daa84d5555 3ff4480984425a69 +cdaee71c772bf71e bfd32e989045cce4 3fee8764bda26dab bfd41b3a07b45c33 +cebd699d0dee83b4 3fec827024d102af 3fdd10e0bbe6b6be 3fff632e7a7c2b92 +cfc1e5f85cdff778 3fbbb3f963e849db bfefcfe4849ea653 bfbbddde1fbce465 +d0d30492350500aa 3fd0c7141731936e 3feee1802528dc9f 3fd162bbfe20713e +d1ec404cf016a0cf bfd8cd1e85e782d4 3fed7fe3b7434012 bfdae747ebda96f5 +d2fb994d1c8c7b4c bfe8497d19e68afd bfe4d6036bc4298d 3ff2a66c2b72d3a2 +d40fcc049b7b67f0 bfee4c0b974d9768 3fd49990ffd8c2d9 c0078826b5fcfa47 +d51b27c89d6d7ead 3fdf2bd958404b92 bfebf2aca8b295ba bfe1d86812bcd49e +d6244dc0988c1538 bfef59e9a3410ef9 3fc9a4dd4099d326 c0138f96a1e7ff51 +d73da781684d5e3d 3fedf180750bb490 bfd692e89ef0d1b3 c00539300aa16825 +d8471014e44a6b74 bfed9bf2f213a1d7 bfd845ee89900164 4003846de997d12a +d95195031b2e58c4 3fe6be9a0f382a69 3fe6827acde31473 3ff02abc2ecbaefd +da609b52b3a1b6ca 3fef1ccc9e302f89 3fcdefc549938236 4010a0e37aec0b75 +db7b51ab2f8f9136 bfef9c382f2babaf 3fc3eac7f7192a92 c01964b772101ea7 +dc87ecb8f7f8fdc4 bfeab58ba17bd738 3fe19fdae7e9f100 bff83f55316c47d2 +dd9bbb2a46b8ddc7 3fdcc4826c97d7b5 bfec95c6fab2693e bfe01a28552454ee +deaaf960f0156254 bfd082e61f43eea7 3feeeaaea910ff9c bfd11700adcb8629 +dfb28901ae8bfcee 3fd3548a1c80dc0f 3fee81687244dc05 3fd446f9666fdf63 +e0cf6c1f87287d44 3fcb40e6263d41e2 3fef44286d6c97a8 3fcbe4a221967be7 +e1d9d8471de1373c 3fed930f73c3eda2 bfd871207786ccdf c0035c1e62ddc81f +e2e6148d3bdd5766 3fef90bd285c5b57 bfc5063a13d6bace c01805a168dd98e2 +e3f4f083384e226a 3fc0928ead764268 3fefbb0c47484eda 3fc0b691ee6ed02f +e50a92226cbc602e bfea7f137debbb04 bfe1f156323ce03b 3ff7a0a60e2794f1 +e614d993d17d8ac0 3fe7096734cbfe4f bfe635e75451e455 bff0985c0f0eaf25 +e7260dda8750386b bfef3f127bd1cca2 bfcb9d9b1783c479 40121a8409e74850 +e83935349f7a6a5b 3fefdaf6b8ca4508 bfb850c04f4ea9d7 c024f61d781be59d +e94747506f0128ec bfef4df102cae212 bfca8ad4439be743 4012dee50b3299e8 +ea50eb04bc9bd31e bfc648921738f51e 3fef82e812e13fda bfc6a1080a0c5f0d +eb67c0d61ed65e4f 3fe5bfd448d442d1 3fe779014a6fd4b3 3feda68cf7223e5d +ec784982ba0b62dc bfebec41b876a5f7 bfdf42d26c4f2f57 3ffc953bd7b02ff3 +ed88ae5a63da6760 3fc9aef9c1c85b80 bfef596533705db4 bfca377854894665 +ee96306205bfe007 3fdaa4a50da8dea4 bfed1864baab4d15 bfdd4d948e32f686 +eface27deda670fa 3fee189bfce3fdbf 3fd5befeca9ec28b 400624c80fde1713 +f0b2eeea97be28de 3fe03be17cfd139d 3feb9391bd793b70 3fe2d6875999c456 +f1cc41e567927eaa bfeb0405af3c801e bfe1269d767591bd 3ff933f3144ddfc9 +f2d832074c3b77ed bfe7ff19dcbe2ecd bfe52b8492471117 3ff222dfe5b6040f +f3efdc01590e5e9e bfdebb7844bd1cd0 3fec11b8b56f2ddd bfe1849c1423f660 +f4f1700a4f8811b2 3fe9b543be006437 3fe30e188fb79109 3ff5961a54236e7f +f60cfef91b61bc1c bfbf5e15bd51b62e bfefc245b94de69b 3fbf9b0d49b68b3d +f71b605ece7530f4 bfba493689c92b40 bfefd4b37486d7c3 3fba6cf82d40c911 +f823897091de25a8 3fb387ef1031c1f5 3fefe81fbd1778d5 3fb3968c8c031057 +f9373eb6fa2dee12 3fe0b27ae31d6547 bfeb4c657ba09359 bfe392ab3b242996 +fa4e6e4eec40a6e6 bfdbd59fc60145a9 3fecd0ab116b7916 bfdee9355726e6d7 +fb5b8329702692b4 bfeffd388bc2744a bf9aabbbc65f9c67 404330c3c97cb67e +fc66f25a3d66c5e8 3f59fa58e76488c9 bfeffffd5d25b540 bf59fa5b0b3edca1 +fd78dc46f9daf1f0 bfe86a89a4c717ba bfe4af3f4800c864 3ff2e2f0a1d5e613 +fe8adbb529a5b5e4 3fc05d3ad29717d2 3fefbcc71111bd51 3fc07fe3f2dc877f +ff9b8384c1bc5bd4 3fed1b4bdef61e13 3fda97f33e9d0b4c 40018311a5b533f3 +e048573636a35abe bfb368ce89219ea0 3fefe86bb706ea88 bfb37726602bd576 +da20a3cabde702ce 3fe5b635e7c40c80 3fe781e73a13d11a 3fed8e3bc623c2ea +f79695de42ce3386 3fec6214456a1bfb 3fdd8e7e6cd82258 3ffebac02cffe265 +f2804cad493011c5 3fde788dc8cd7eac bfec23efcb571502 bfe1533930369ef2 +f7ff0603b34f8a05 3fe0b5783b0b03af 3feb4a9121f0aa78 3fe3977c849d1ab9 +c98796a299efdcd8 bfede98f08dcb51c 3fd6bce10b4db012 c0050c6c5e82916e +f6c9af9015126c79 3fe8d2e7808a6597 3fe431880c388d00 3ff3ab36563ec8b9 +ed7471dcf84f217b 3febf8e2802e7a2d bfdf15891f2e4c2a bffccbe052a5df8c +d1fe8e7dc891b61f 3faa784886c950f5 3feff50b82f522ff 3faa815b7549a306 +c28eac3caaa861f0 3fee0d088008f1d2 3fd5feaae15caea0 4005dc41dd2f1ecd +d425ceb684ad01f8 3fdf4367b45e507c bfebec17efc4284c bfe1ea1c4f4b79b5 +ce1e73021ba3465b 3fed307dee44145e bfda3a6192f2e4d5 c001ce7927430039 +f6c0226b6b366794 bfdff4fa6b39306f 3febb9a8b29997d3 bfe2712cad4e4c86 +cbb0915c8d3d71ae bfcc09db3b50b4b0 bfef390b6d8731ed 3fccbc855551e65a +c9dd4ce25d3d02f8 bfe28cf13ce63ba1 bfea130f11015cf1 3fe6c429e758ac56 +d4ab57555db44810 bfe911d48bb8a5fe bfe3e3333be7dfb7 3ff42b4ec3f0963b +c6eb689a0d2f68b4 bfefc582eb4c36f1 bfbe8956f935d070 4020a5a991ef83ce +ce7c3f32fb894722 3fd5928b3c4b4524 3fee209a4e1eede1 3fd6e9cfee15d252 +c49b1e74bf9def68 bfe547459c3f088b bfe7e6810e149ad0 3fec7d4b5a74ccea +f7824089a485562e bfddfbecf4b2526b 3fec4553c5b2da03 bfe0f83a12cc93ee +df7479355f9fa896 3fe21ee4d2fe97a7 3fea600073fc2d10 3fe5fc3adbf9cba7 +d1dc76e954a8a53e bfefffb064ebf200 bf81d8206565d656 405cb10f1090d360 +d44e444a0a68e409 bfc909f3047fae10 bfef61bc2a518fe7 3fc98839c1615a3c +e3803f4341a57a0c 3feee79cab0f14e0 bfd099d400b8af48 c00dc93da1ea523a +e5eb1770e1363163 bfe81919d8459fb9 3fe50de73d7fd833 bff250249dc3bfd1 +e09fcb40b6ce5a42 3fe163fd84f9ad03 bfeadcac8fe8b212 bfe4b789d0fcaad9 +f0ff067b86d2d84f 3feff4904c9a08ad bfab0b6fa3cd0197 c032e7bbe4e01650 +ef64c05186a6c022 bfbbaacac08e0042 3fefd0047b5043bd bfbbd485a3336917 +df42eff3bb7b680e bfecbfa3b8107911 bfdc1bb66e440394 40005d4fcf88c2a8 +f46cc8cff7087530 bfebe8d3115d3670 3fdf4f12944c60c1 bffc868ab09dc484 +f2e5f53e430dc0c6 3fd758560675b299 3fedcb901aa7a8e7 3fd9129538a3c8fd +eda248d3d2fae318 3fde8cb135471d5e bfec1e79ddc75703 bfe1620bfba59b95 +f83bcdd9b18c659a bfe4ffb105ef572c bfe8257d28132e2b 3febd41e8ee14069 +e7607b59ec9bb1a6 bfedc6e784450b68 bfd770107a094819 400453d8cdbddc59 +d7cd82f5d727c49d 3fe6ae85d51b1fd9 3fe692ae676deb03 3ff013bc022c83b9 +c3a2ee37306e278c 3fe2db088224146e bfe9dacebf57b3e4 bfe75658f1ab3f06 +d9a005573dcecc78 bfefe471c2a7ded4 bfb4facea1d37fd2 4028528b200fa878 +eeb99f5b943c76f4 bfea974923c86c24 3fe1cd61a47513c2 bff7e620bbd808fb +f58047f5c64b713e 3fd0e47112fd20e0 3feedd7f658a620a 3fd1836e8f31f57a +d73d1bf5d8bb1683 3fdcc4f5218081ff bfec95aa1e4e5b22 bfe01a78cbe593a7 +f2045a7225e384d0 bfec3b71a67e2264 bfde21159f990b85 3ffdfc34969d989e +d4dd84f6e091b8b0 bfe4582a3ab78ab0 3fe8b347eb44264a bfea5b5575abc9ee +f949c0213085d48f 3fd6e5311f0f245f 3fede1de0ec6ac7a 3fd884906eed344c +c7d371072d7c9860 bfeafa92c6f5635d bfe13576a771907c 3ff9156b1dce31a0 +f420667c243834a4 bfe825290ff7e266 bfe50011b78091a1 3ff2656519560c9f +d45fd8bd04b0ee09 bfee1de342eb4f74 bfd5a1aff0118cd9 400646b0035b292d +d4133fc370f869b4 bfed14eb4fff9e43 3fdab3ccf053c462 c0016cfb9c34f432 +daed620c885b1412 3fe6de5d48702451 bfe66235338382dd bff058bf865b4c8b +ec6d5d6829eac918 bfea64a3497f52ba bfe2182382f97a49 3ff7569a4c0e5f1e +f8f660cd6f92845e 3fe0b793734af274 bfeb4946e34a07b5 bfe39ae201f68b60 +fcc6d5af3991cf71 bfe38eb37d606b7b bfe953f726d1c564 3fe8b59698862010 +d4dba7dffdec377c 3fdde44e558da20d bfec4b93e136de44 bfe0e71f457dfa8d +ff59d8fcbe13eefe bfefaadf0ef0c234 3fc267b09f0e807b c01b8785fc6ca2b8 +f35f287340cf3940 3fe162d1af53cd70 bfeadd6ea3e2fe3b bfe4b58f01dd14de +c290c320eaab4410 bfe4b781a774f9cb 3fe8638803e742cc bfeb2e9d34e5d7e7 +da7d6824e89aed52 3fe96505cbf8846c bfe378886e79f61c bff4de29cbcf5b4d +c5b84839709c60c5 3feaa98dfab0f14b 3fe1b1f9741494ea 3ff81ba981fd8cbe +c7ee831055f8d972 bfede49ce044f826 bfd6d6d6c4551896 4004f108b0e4e419 +d71c9bfc11bd1454 bfef6755e64ce939 bfc89899862c2ae7 40146daab31ad51a +d7bb81683bb47276 3fda3a846d730f18 bfed307619ebd216 bfdcc1126cc39140 +e6de1d4470ba365a 3feb69a12540012c bfe08250b3f27175 bffa913f043729a9 +f568586841528e18 bfeedc4932adcd3c bfd0ed49baa115af 400d2babe4fc51c2 +f2935398ea6f7e75 3fe7fc4c6b739d8a bfe52eb16112c2eb bff21e0a0f773d0f +c29ffcbcf6d71f54 3feffb480cb29dd8 3fa16012dd7033fb 403d733dff81700e +de9c2cd051d6a114 3fd3754f0d955b88 bfee7c32a8b68c90 bfd46cd65f177965 +cdb80a37872416c4 3f91a943e26756a0 bfeffec80f20ced6 bf91a9f012f24ab6 +fd66ec9f42c8a389 3fe6681f7c1ad69d 3fe6d8919d3d2a77 3fef627fb68ca04c +f4210b7a10c5cbf4 bfef7bbede33fd39 3fc6e849113597ca c015fd73e9c4c1b5 +d5567b06985ba6d2 bfebf6a337f05f68 3fdf1d9e809321e4 bffcc2158f07fd9b +c9fc3085c40ac0d2 3feb36fe141cdb9c 3fe0d5473f8d601c 3ff9de2d2a3342c8 +f7b5ee1fa53e7ae0 3fe32ce3a3d92511 3fe99e540e32ae0a 3fe7f3b005ac3313 +dda119f5e03bb1c4 bfdea4f5badc95cd 3fec17df18100d7f bfe173f4653e7b37 +ee79128bb9a656ac 3fe2d519b008b2f3 3fe9df215de804d0 3fe74b1c2183c7f9 +d9cb7b7b3406f2d8 3fee1bc3abf28a9e 3fd5ad7f907ca286 400638fbb4ddc074 +d5dacaff9b9a67e6 bfbfdba7bcf9ed2c 3fefc051b177ac03 bfc00dc66f755c0f +e4be8340b1988acc 3fefc4cedd573d75 bfbeb8084ffb4b48 c0208bfe0e64109a +c707d2c89e3078d1 3fed09604d3b15cf 3fdae5dd51fef9b6 400145aecc8f5177 +ca621ba100b3b836 3fd1e5150dd774b3 bfeeb9421479e734 bfd2a3643912d86f +e9d710f107389d90 bfeeff81b2e4e007 bfcfc773a4bceaed 400f36aa450b857a +ed91c8d6153775b0 bfe25f1412e8276e 3fea3373cf352859 bfe67000742bce07 diff --git a/tests/fixtures/native_providers/trig_reference_f32.txt b/tests/fixtures/native_providers/trig_reference_f32.txt new file mode 100644 index 00000000..0c1f57ee --- /dev/null +++ b/tests/fixtures/native_providers/trig_reference_f32.txt @@ -0,0 +1,242 @@ +# Generated by tools/generate_trig_vectors.py (mpmath 1.3.0, 800 digits) +# Exact input, sin, cos, tan as hexadecimal binary64 bits +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +3fb99999a0000000 3fb98eaed1ea022b 3fefd712f993a59b 3fb9af887db9f053 +3fe921fb60000000 3fe6a09e6ecb41fe 3fe6a09e5e333598 3ff000000bbbd2ec +412e848000000000 bfd6664b2568d867 3fedf9df9906d32c bfd7e9768ab734c0 +426d1a94a0000000 bf954d602c80a5de 3feffe3a2a437b7f bf954e8e5ae045a0 +4415af1d80000000 3fe502ad17d67516 3fe822e45d2fb241 3febdb120e3606b4 +3ff921fb60000000 3feffffffffffff7 be6777a5cf72cecc c175d14946dc9897 +3ff921fb60000000 3feffffffffffff7 be6777a5cf72cecc c175d14946dc9897 +3ff921fb60000000 3feffffffffffff7 be6777a5cf72cecc c175d14946dc9897 +400921fb60000000 be7777a5cf72cec6 bfefffffffffffde 3e7777a5cf72cedf +400921fb60000000 be7777a5cf72cec6 bfefffffffffffde 3e7777a5cf72cedf +400921fb60000000 be7777a5cf72cec6 bfefffffffffffde 3e7777a5cf72cedf +4012d97c80000000 bfefffffffffffff 3e499bc5b961b1ad c193fe4dac06d831 +4012d97c80000000 bfefffffffffffff 3e499bc5b961b1ad c193fe4dac06d831 +4012d97c80000000 bfefffffffffffff 3e499bc5b961b1ad c193fe4dac06d831 +401921fb60000000 3e8777a5cf72cead 3fefffffffffff76 3e8777a5cf72cf12 +401921fb60000000 3e8777a5cf72cead 3fefffffffffff76 3e8777a5cf72cf12 +401921fb60000000 3e8777a5cf72cead 3fefffffffffff76 3e8777a5cf72cf12 +403ab41b00000000 3feffffffffffa52 3ea310dfd3960324 413adaad2f107edb +403ab41b00000000 3feffffffffffa52 3ea310dfd3960324 413adaad2f107edb +403ab41b00000000 3feffffffffffa52 3ea310dfd3960324 413adaad2f107edb +409921fb60000000 3f0777a5cf5126e0 3fefffffff765212 3f0777a5cfb61eab +409921fb60000000 3f0777a5cf5126e0 3fefffffff765212 3f0777a5cfb61eab +409921fb60000000 3f0777a5cf5126e0 3fefffffff765212 3f0777a5cfb61eab +413921fb60000000 3fa7758b5f08054e 3feff76583dd002c 3fa77bdbb52047c1 +413921fb60000000 3fa7758b5f08054e 3feff76583dd002c 3fa77bdbb52047c1 +413921fb60000000 3fa7758b5f08054e 3feff76583dd002c 3fa77bdbb52047c1 +427921fb60000000 3fec7a2eece4bc9b 3fdd312d2951b11c 3fff3767c1fa9cd2 +427921fb60000000 3fec7a2eece4bc9b 3fdd312d2951b11c 3fff3767c1fa9cd2 +427921fb60000000 3fec7a2eece4bc9b 3fdd312d2951b11c 3fff3767c1fa9cd2 +463921fb60000000 3fef542b413ab2f0 3fca143b23fd1af1 40133888559bd61f +463921fb60000000 3fef542b413ab2f0 3fca143b23fd1af1 40133888559bd61f +463921fb60000000 3fef542b413ab2f0 3fca143b23fd1af1 40133888559bd61f +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +0000000000000000 0000000000000000 3ff0000000000000 0000000000000000 +3755640000000000 3755640000000000 3ff0000000000000 3755640000000000 +386bbca200000000 386bbca200000000 3ff0000000000000 386bbca200000000 +3972bb99e0000000 3972bb99e0000000 3ff0000000000000 3972bb99e0000000 +3a89d898e0000000 3a89d898e0000000 3ff0000000000000 3a89d898e0000000 +3b9701d080000000 3b9701d080000000 3ff0000000000000 3b9701d080000000 +3ca26f9740000000 3ca26f9740000000 3ff0000000000000 3ca26f9740000000 +3dba782f60000000 3dba782f60000000 3ff0000000000000 3dba782f60000000 +3ec1db0420000000 3ec1db041ffff12d 3fefffffffffb04c 3ec1db0420001da6 +3fde33dd20000000 3fdd180e58db8cda 3fec809b7d6ab21e 3fe05504488e01f2 +40efb002a0000000 bfc9c106713999e3 bfef5878434a409c 3fca4aaba719d5bc +41f9049c00000000 3fab431e5869e8ad bfeff460fbcd44d6 bfab4d087dac356a +4308a600e0000000 3fdfceb69d4c9f3d 3febc4a6a72d2b3f 3fe253d3777dc17f +4412de3c40000000 3feff6ffc59d3f14 bfa7fe9db8e511ba c035508fd1d86af6 +4528f83e60000000 3fe9472ee9abc2bb 3fe39f3614c3884a 3ff49cb293c0d6e2 +4633c1fc20000000 3fcd3cfc79eef05d bfef276b23160123 bfce083fde88c316 +474ac5c180000000 bfc24dc12aa3eee2 bfefabcf8ec0f274 3fc27e68fd4d28d3 +428eac3ca0000000 3fefce6d17ee699a bfbc1eef6ce89f43 c02218d2248dd65c +46eb689a00000000 bfb46fb69a8be6db 3fefe5dafd584e96 bfb48076b1389942 +449b1e74c0000000 bfeb42607fd5354a bfe0c2d168a6a0e3 3ffa0588d2603273 +43a2ee3740000000 bfe33ee16db19400 bfe990d2c2655486 3fe816dc092fda67 +47d3710720000000 3feed2ceb4e8da22 bfd131d3e575b26d c00cae93088d3ff1 +4290c320e0000000 bfebaf088f74987a bfe00cdefaf9ebc4 3ffb98d55600f7f5 +45b8483980000000 bfee1ca60d04ee43 3fd5a8954082e082 c0063eae065f0bc3 +47ee831060000000 bfeb836fb116f39f bfe0572a3b4f456f 3ffaf0abee9561d9 +429ffcbd00000000 3fbbaf3814f36a07 bfefcff5137913e4 bfbbd907214d97af +4707d2c8a0000000 bf9053de5e08419e bfeffef56463add9 3f9054666b0430a6 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +bfb99999a0000000 bfb98eaed1ea022b 3fefd712f993a59b bfb9af887db9f053 +bfe921fb60000000 bfe6a09e6ecb41fe 3fe6a09e5e333598 bff000000bbbd2ec +c12e848000000000 3fd6664b2568d867 3fedf9df9906d32c 3fd7e9768ab734c0 +c26d1a94a0000000 3f954d602c80a5de 3feffe3a2a437b7f 3f954e8e5ae045a0 +c415af1d80000000 bfe502ad17d67516 3fe822e45d2fb241 bfebdb120e3606b4 +bff921fb60000000 bfeffffffffffff7 be6777a5cf72cecc 4175d14946dc9897 +bff921fb60000000 bfeffffffffffff7 be6777a5cf72cecc 4175d14946dc9897 +bff921fb60000000 bfeffffffffffff7 be6777a5cf72cecc 4175d14946dc9897 +c00921fb60000000 3e7777a5cf72cec6 bfefffffffffffde be7777a5cf72cedf +c00921fb60000000 3e7777a5cf72cec6 bfefffffffffffde be7777a5cf72cedf +c00921fb60000000 3e7777a5cf72cec6 bfefffffffffffde be7777a5cf72cedf +c012d97c80000000 3fefffffffffffff 3e499bc5b961b1ad 4193fe4dac06d831 +c012d97c80000000 3fefffffffffffff 3e499bc5b961b1ad 4193fe4dac06d831 +c012d97c80000000 3fefffffffffffff 3e499bc5b961b1ad 4193fe4dac06d831 +c01921fb60000000 be8777a5cf72cead 3fefffffffffff76 be8777a5cf72cf12 +c01921fb60000000 be8777a5cf72cead 3fefffffffffff76 be8777a5cf72cf12 +c01921fb60000000 be8777a5cf72cead 3fefffffffffff76 be8777a5cf72cf12 +c03ab41b00000000 bfeffffffffffa52 3ea310dfd3960324 c13adaad2f107edb +c03ab41b00000000 bfeffffffffffa52 3ea310dfd3960324 c13adaad2f107edb +c03ab41b00000000 bfeffffffffffa52 3ea310dfd3960324 c13adaad2f107edb +c09921fb60000000 bf0777a5cf5126e0 3fefffffff765212 bf0777a5cfb61eab +c09921fb60000000 bf0777a5cf5126e0 3fefffffff765212 bf0777a5cfb61eab +c09921fb60000000 bf0777a5cf5126e0 3fefffffff765212 bf0777a5cfb61eab +c13921fb60000000 bfa7758b5f08054e 3feff76583dd002c bfa77bdbb52047c1 +c13921fb60000000 bfa7758b5f08054e 3feff76583dd002c bfa77bdbb52047c1 +c13921fb60000000 bfa7758b5f08054e 3feff76583dd002c bfa77bdbb52047c1 +c27921fb60000000 bfec7a2eece4bc9b 3fdd312d2951b11c bfff3767c1fa9cd2 +c27921fb60000000 bfec7a2eece4bc9b 3fdd312d2951b11c bfff3767c1fa9cd2 +c27921fb60000000 bfec7a2eece4bc9b 3fdd312d2951b11c bfff3767c1fa9cd2 +c63921fb60000000 bfef542b413ab2f0 3fca143b23fd1af1 c0133888559bd61f +c63921fb60000000 bfef542b413ab2f0 3fca143b23fd1af1 c0133888559bd61f +c63921fb60000000 bfef542b413ab2f0 3fca143b23fd1af1 c0133888559bd61f +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +8000000000000000 8000000000000000 3ff0000000000000 8000000000000000 +b755640000000000 b755640000000000 3ff0000000000000 b755640000000000 +b86bbca200000000 b86bbca200000000 3ff0000000000000 b86bbca200000000 +b972bb99e0000000 b972bb99e0000000 3ff0000000000000 b972bb99e0000000 +ba89d898e0000000 ba89d898e0000000 3ff0000000000000 ba89d898e0000000 +bb9701d080000000 bb9701d080000000 3ff0000000000000 bb9701d080000000 +bca26f9740000000 bca26f9740000000 3ff0000000000000 bca26f9740000000 +bdba782f60000000 bdba782f60000000 3ff0000000000000 bdba782f60000000 +bec1db0420000000 bec1db041ffff12d 3fefffffffffb04c bec1db0420001da6 +bfde33dd20000000 bfdd180e58db8cda 3fec809b7d6ab21e bfe05504488e01f2 +c0efb002a0000000 3fc9c106713999e3 bfef5878434a409c bfca4aaba719d5bc +c1f9049c00000000 bfab431e5869e8ad bfeff460fbcd44d6 3fab4d087dac356a +c308a600e0000000 bfdfceb69d4c9f3d 3febc4a6a72d2b3f bfe253d3777dc17f +c412de3c40000000 bfeff6ffc59d3f14 bfa7fe9db8e511ba 4035508fd1d86af6 +c528f83e60000000 bfe9472ee9abc2bb 3fe39f3614c3884a bff49cb293c0d6e2 +c633c1fc20000000 bfcd3cfc79eef05d bfef276b23160123 3fce083fde88c316 +c74ac5c180000000 3fc24dc12aa3eee2 bfefabcf8ec0f274 bfc27e68fd4d28d3 +c28eac3ca0000000 bfefce6d17ee699a bfbc1eef6ce89f43 402218d2248dd65c +c6eb689a00000000 3fb46fb69a8be6db 3fefe5dafd584e96 3fb48076b1389942 +c49b1e74c0000000 3feb42607fd5354a bfe0c2d168a6a0e3 bffa0588d2603273 +c3a2ee3740000000 3fe33ee16db19400 bfe990d2c2655486 bfe816dc092fda67 +c7d3710720000000 bfeed2ceb4e8da22 bfd131d3e575b26d 400cae93088d3ff1 +c290c320e0000000 3febaf088f74987a bfe00cdefaf9ebc4 bffb98d55600f7f5 +c5b8483980000000 3fee1ca60d04ee43 3fd5a8954082e082 40063eae065f0bc3 +c7ee831060000000 3feb836fb116f39f bfe0572a3b4f456f bffaf0abee9561d9 +c29ffcbd00000000 bfbbaf3814f36a07 bfefcff5137913e4 3fbbd907214d97af +c707d2c8a0000000 3f9053de5e08419e bfeffef56463add9 bf9054666b0430a6 +36a0000000000000 36a0000000000000 3ff0000000000000 36a0000000000000 +b6a0000000000000 b6a0000000000000 3ff0000000000000 b6a0000000000000 +47efffffe0000000 bfe0b33665089575 3feb4bf2c79bdfce bfe393d94b4988c2 +c7efffffe0000000 3fe0b33665089575 3feb4bf2c79bdfce 3fe393d94b4988c2 +3ff921fb40000000 3fefffffffffffe6 3e74442d18469893 4169437b336b6b0c +3ff921fb60000000 3feffffffffffff7 be6777a5cf72cecc c175d14946dc9897 +3ff921fb80000000 3fefffffffffff88 be85dde973dcb398 c1576a190eb2b072 +400921fb40000000 3e84442d18469883 bfefffffffffff99 be84442d184698c4 +400921fb60000000 be7777a5cf72cec6 bfefffffffffffde 3e7777a5cf72cedf +400921fb80000000 be95dde973dcb347 bfeffffffffffe22 3e95dde973dcb48d diff --git a/tests/fixtures/native_providers/wide_abi.c b/tests/fixtures/native_providers/wide_abi.c new file mode 100644 index 00000000..a2ad8f86 --- /dev/null +++ b/tests/fixtures/native_providers/wide_abi.c @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MPL-2.0 +// Independently compiled C caller exercises the public native ABI. C may use +// its platform runtime; the Wave object is separately checked for dependencies. +#include +typedef unsigned __int128 u128; +typedef __int128 i128; +extern u128 wave_unsigned_div(u128, u128), wave_unsigned_rem(u128, u128); +extern i128 wave_signed_div(i128, i128), wave_signed_rem(i128, i128); +extern float wave_to_float(u128); +extern i128 wave_from_double(double); +int main(int argc, char **argv) { + (void)argv; + const u128 samples[] = {0, 1, 3, (u128)1 << 64, (u128)1 << 100, + ((u128)1 << 127) - 1, (u128)1 << 127, ~(u128)0}; + for (unsigned i = 0; i < sizeof(samples) / sizeof(samples[0]); ++i) { + u128 a = samples[i] + (unsigned)(argc - 1); + u128 b = ((u128)1 << 65) + (unsigned)argc; + if (wave_unsigned_div(a, b) != a / b || wave_unsigned_rem(a, b) != a % b) return 1; + if (wave_signed_div((i128)a, -(i128)b) != (i128)a / -(i128)b) return 2; + if (wave_signed_rem((i128)a, -(i128)b) != (i128)a % -(i128)b) return 3; + if (wave_to_float(a) != (float)a) return 4; + } + double value = -0x1p100 * argc; + if (wave_from_double(value) != (i128)value) return 5; + return 0; +} diff --git a/tests/fixtures/native_providers/wide_abi.wave b/tests/fixtures/native_providers/wide_abi.wave new file mode 100644 index 00000000..b423572f --- /dev/null +++ b/tests/fixtures/native_providers/wide_abi.wave @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MPL-2.0 +export(c) fun wave_unsigned_div(a: u128, b: u128) -> u128 { return a / b; } +export(c) fun wave_signed_div(a: i128, b: i128) -> i128 { return a / b; } +export(c) fun wave_unsigned_rem(a: u128, b: u128) -> u128 { return a % b; } +export(c) fun wave_signed_rem(a: i128, b: i128) -> i128 { return a % b; } +export(c) fun wave_to_float(a: u128) -> f32 { return a as f32; } +export(c) fun wave_from_double(a: f64) -> i128 { return a as i128; } diff --git a/tests/fixtures/native_providers/wide_arithmetic.wave b/tests/fixtures/native_providers/wide_arithmetic.wave new file mode 100644 index 00000000..d01a0c9a --- /dev/null +++ b/tests/fixtures/native_providers/wide_arithmetic.wave @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: MPL-2.0 +// Pointer arguments let the host test all 128 bits without a host arithmetic API. +export(c) fun udiv(a: ptr, b: ptr, output: ptr) { deref output = deref a / deref b; } +export(c) fun urem(a: ptr, b: ptr, output: ptr) { deref output = deref a % deref b; } +export(c) fun sdiv(a: ptr, b: ptr, output: ptr) { deref output = deref a / deref b; } +export(c) fun srem(a: ptr, b: ptr, output: ptr) { deref output = deref a % deref b; } +export(c) fun mul(a: ptr, b: ptr, output: ptr) { deref output = deref a * deref b; } +export(c) fun u_to_f64(a: ptr) -> f64 { return deref a as f64; } +export(c) fun s_to_f64(a: ptr) -> f64 { return deref a as f64; } +export(c) fun u_to_f32(a: ptr) -> f32 { return deref a as f32; } +export(c) fun s_to_f32(a: ptr) -> f32 { return deref a as f32; } +export(c) fun f64_to_u(a: f64, output: ptr) { deref output = a as u128; } +export(c) fun f64_to_s(a: f64, output: ptr) { deref output = a as i128; } +export(c) fun f32_to_u(a: f32, output: ptr) { deref output = a as u128; } +export(c) fun f32_to_s(a: f32, output: ptr) { deref output = a as i128; } +export(c) fun shl(a: ptr, b: ptr, output: ptr) { deref output = deref a << deref b; } +export(c) fun lshr(a: ptr, b: ptr, output: ptr) { deref output = deref a >> deref b; } +export(c) fun ashr(a: ptr, b: ptr, output: ptr) { deref output = deref a >> deref b; } +export(c) fun compound(a: ptr, b: ptr, output: ptr) { deref output = deref a; deref output /= deref b; } + +import("std::time::clock")::{time_now_monotonic_ns}; +import("std::math::float")::{float_to_bits_f32, float_to_bits_f64, float_from_bits_f64}; +static left: array = [0,0,0,0,0,1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,9223372036854775807,9223372036854775807,9223372036854775807,9223372036854775807,9223372036854775807,9223372036854775808,9223372036854775808,9223372036854775808,9223372036854775808,9223372036854775808,18446744073709551615,18446744073709551615,18446744073709551615,18446744073709551615,18446744073709551615,18446744073709551616,18446744073709551616,18446744073709551616,18446744073709551616,18446744073709551616,170141183460469231731687303715884105727,170141183460469231731687303715884105727,170141183460469231731687303715884105727,170141183460469231731687303715884105727,170141183460469231731687303715884105727,170141183460469231731687303715884105728,170141183460469231731687303715884105728,170141183460469231731687303715884105728,170141183460469231731687303715884105728,340282366920938463463374607431768211455,340282366920938463463374607431768211455,340282366920938463463374607431768211455,340282366920938463463374607431768211455,340282366920938463463374607431768211455,291418864332232241439988395988053958886,291418864332232241439988395988053958886,291418864332232241439988395988053958886,291418864332232241439988395988053958886,291418864332232241439988395988053958886,18846464147442634679741936447216300117,18846464147442634679741936447216300117,18846464147442634679741936447216300117,18846464147442634679741936447216300117,18846464147442634679741936447216300117,245203185851727385845485937452715697870,245203185851727385845485937452715697870,245203185851727385845485937452715697870,245203185851727385845485937452715697870,245203185851727385845485937452715697870,114652594115518069740405279983274155324,114652594115518069740405279983274155324,114652594115518069740405279983274155324,114652594115518069740405279983274155324,114652594115518069740405279983274155324,166166142659951810159888545336341693602,166166142659951810159888545336341693602,166166142659951810159888545336341693602,166166142659951810159888545336341693602,166166142659951810159888545336341693602,263759780562757722014930566387023379220,263759780562757722014930566387023379220,263759780562757722014930566387023379220,263759780562757722014930566387023379220,263759780562757722014930566387023379220,230640933272743625625576298081442878168,230640933272743625625576298081442878168,230640933272743625625576298081442878168,230640933272743625625576298081442878168,230640933272743625625576298081442878168,306718949341522620460258775176139511069,306718949341522620460258775176139511069,306718949341522620460258775176139511069,306718949341522620460258775176139511069,306718949341522620460258775176139511069,65113537344948203193705796192292199208,65113537344948203193705796192292199208,65113537344948203193705796192292199208,65113537344948203193705796192292199208,65113537344948203193705796192292199208,229327982523567729552085144630167445229,229327982523567729552085144630167445229,229327982523567729552085144630167445229,229327982523567729552085144630167445229,229327982523567729552085144630167445229,280974730663033946535541310993302633037,280974730663033946535541310993302633037,280974730663033946535541310993302633037,280974730663033946535541310993302633037,280974730663033946535541310993302633037,87931291536685888760541015732968165503,87931291536685888760541015732968165503,87931291536685888760541015732968165503,87931291536685888760541015732968165503,87931291536685888760541015732968165503,131037031310206406097666786152457743889,131037031310206406097666786152457743889,131037031310206406097666786152457743889,131037031310206406097666786152457743889,131037031310206406097666786152457743889,297105132560930403746098241077493610706,297105132560930403746098241077493610706,297105132560930403746098241077493610706,297105132560930403746098241077493610706,297105132560930403746098241077493610706,231001566418938911282812937946962496454,231001566418938911282812937946962496454,231001566418938911282812937946962496454,231001566418938911282812937946962496454,231001566418938911282812937946962496454,6274627916369965814003806980848572626,6274627916369965814003806980848572626,6274627916369965814003806980848572626,6274627916369965814003806980848572626,6274627916369965814003806980848572626,9687398916324857071513154332292290797,9687398916324857071513154332292290797,9687398916324857071513154332292290797,9687398916324857071513154332292290797,9687398916324857071513154332292290797,206098718630803680044749332060727159438,206098718630803680044749332060727159438,206098718630803680044749332060727159438,206098718630803680044749332060727159438,206098718630803680044749332060727159438,280822055026938302630811942962048661385,280822055026938302630811942962048661385,280822055026938302630811942962048661385,280822055026938302630811942962048661385,280822055026938302630811942962048661385,130115090678679890393001477399677717019,130115090678679890393001477399677717019,130115090678679890393001477399677717019,130115090678679890393001477399677717019,130115090678679890393001477399677717019,34977586735391474740600109004789528994,34977586735391474740600109004789528994,34977586735391474740600109004789528994,34977586735391474740600109004789528994,34977586735391474740600109004789528994,161419598747412801403378589501099002188,161419598747412801403378589501099002188,161419598747412801403378589501099002188,161419598747412801403378589501099002188,161419598747412801403378589501099002188,285474360523189274072323309291576511028,285474360523189274072323309291576511028,285474360523189274072323309291576511028,285474360523189274072323309291576511028,285474360523189274072323309291576511028,152883657307965189162822886067322056,152883657307965189162822886067322056,152883657307965189162822886067322056,152883657307965189162822886067322056,152883657307965189162822886067322056,6167003650087614829768661713674713325,6167003650087614829768661713674713325,6167003650087614829768661713674713325,6167003650087614829768661713674713325,6167003650087614829768661713674713325,26907301159788152716437922254097286976,26907301159788152716437922254097286976,26907301159788152716437922254097286976,26907301159788152716437922254097286976,26907301159788152716437922254097286976,35394661592064597307009101925202309470,35394661592064597307009101925202309470,35394661592064597307009101925202309470,35394661592064597307009101925202309470,35394661592064597307009101925202309470,85864296478326116337732227011988408213,85864296478326116337732227011988408213,85864296478326116337732227011988408213,85864296478326116337732227011988408213,85864296478326116337732227011988408213,242346078553388817991704003840497528708,242346078553388817991704003840497528708,242346078553388817991704003840497528708,242346078553388817991704003840497528708,242346078553388817991704003840497528708,223547052971231363017406574755764480812,223547052971231363017406574755764480812,223547052971231363017406574755764480812,223547052971231363017406574755764480812,223547052971231363017406574755764480812,120006466838770586540610802252957381208,120006466838770586540610802252957381208,120006466838770586540610802252957381208,120006466838770586540610802252957381208,120006466838770586540610802252957381208,129524253855446463659403718320145127822,129524253855446463659403718320145127822,129524253855446463659403718320145127822,129524253855446463659403718320145127822,129524253855446463659403718320145127822,275384209188672322523595159677475933587,275384209188672322523595159677475933587,275384209188672322523595159677475933587,275384209188672322523595159677475933587,275384209188672322523595159677475933587,107239999239400919857985336041891460490,107239999239400919857985336041891460490,107239999239400919857985336041891460490,107239999239400919857985336041891460490,107239999239400919857985336041891460490,51285902985064743099156215266677513732,51285902985064743099156215266677513732,51285902985064743099156215266677513732,51285902985064743099156215266677513732,51285902985064743099156215266677513732]; +static right: array = [1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455,1,3,18446744073709551617,170141183460469231731687303715884105727,340282366920938463463374607431768211455]; +static uq: array = [0,0,0,0,0,1,0,0,0,0,2,0,0,0,0,3,1,0,0,0,9223372036854775807,3074457345618258602,0,0,0,9223372036854775808,3074457345618258602,0,0,0,18446744073709551615,6148914691236517205,0,0,0,18446744073709551616,6148914691236517205,0,0,0,170141183460469231731687303715884105727,56713727820156410577229101238628035242,9223372036854775807,1,0,170141183460469231731687303715884105728,56713727820156410577229101238628035242,9223372036854775807,1,340282366920938463463374607431768211455,113427455640312821154458202477256070485,18446744073709551615,2,1,291418864332232241439988395988053958886,97139621444077413813329465329351319628,15797848290613233827,1,0,18846464147442634679741936447216300117,6282154715814211559913978815738766705,1021668868616373733,0,0,245203185851727385845485937452715697870,81734395283909128615161979150905232623,13292491340040486781,1,0,114652594115518069740405279983274155324,38217531371839356580135093327758051774,6215329581057172646,0,0,166166142659951810159888545336341693602,55388714219983936719962848445447231200,9007884643272800451,0,0,263759780562757722014930566387023379220,87919926854252574004976855462341126406,14298446355022092373,1,0,230640933272743625625576298081442878168,76880311090914541875192099360480959389,12503070045919645152,1,0,306718949341522620460258775176139511069,102239649780507540153419591725379837023,16627267560927510238,1,0,65113537344948203193705796192292199208,21704512448316067731235265397430733069,3529811932380443311,0,0,229327982523567729552085144630167445229,76442660841189243184028381543389148409,12431894843188496295,1,0,280974730663033946535541310993302633037,93658243554344648845180436997767544345,15231670669919544125,1,0,87931291536685888760541015732968165503,29310430512228629586847005244322721834,4766764865676554509,0,0,131037031310206406097666786152457743889,43679010436735468699222262050819247963,7103531701128842548,0,0,297105132560930403746098241077493610706,99035044186976801248699413692497870235,16106101508957726264,1,0,231001566418938911282812937946962496454,77000522139646303760937645982320832151,12522620007948405714,1,0,6274627916369965814003806980848572626,2091542638789988604667935660282857542,340148260923325548,0,0,9687398916324857071513154332292290797,3229132972108285690504384777430763599,525154947540656571,0,0,206098718630803680044749332060727159438,68699572876934560014916444020242386479,11172633924299802886,1,0,280822055026938302630811942962048661385,93607351675646100876937314320682887128,15223394107102518954,1,0,130115090678679890393001477399677717019,43371696892893296797667159133225905673,7053553199348657235,0,0,34977586735391474740600109004789528994,11659195578463824913533369668263176331,1896138776340579981,0,0,161419598747412801403378589501099002188,53806532915804267134459529833699667396,8750573982184168479,0,0,285474360523189274072323309291576511028,95158120174396424690774436430525503676,15475596093407596756,1,0,152883657307965189162822886067322056,50961219102655063054274295355774018,8287839669541261,0,0,6167003650087614829768661713674713325,2055667883362538276589553904558237775,334313937757551380,0,0,26907301159788152716437922254097286976,8969100386596050905479307418032428992,1458647718658202412,0,0,35394661592064597307009101925202309470,11798220530688199102336367308400769823,1918748449625283975,0,0,85864296478326116337732227011988408213,28621432159442038779244075670662802737,4654712839037031145,0,0,242346078553388817991704003840497528708,80782026184462939330568001280165842902,13137607243046343505,1,0,223547052971231363017406574755764480812,74515684323743787672468858251921493604,12118510024207059135,1,0,120006466838770586540610802252957381208,40002155612923528846870267417652460402,6505563602945235774,0,0,129524253855446463659403718320145127822,43174751285148821219801239440048375940,7021523870981951473,0,0,275384209188672322523595159677475933587,91794736396224107507865053225825311195,14928607893528057223,1,0,107239999239400919857985336041891460490,35746666413133639952661778680630486830,5813492007635116020,0,0,51285902985064743099156215266677513732,17095300995021581033052071755559171244,2780214371714400566,0,0]; +static ur: array = [0,0,0,0,0,0,1,1,1,1,0,2,2,2,2,0,0,3,3,3,0,1,9223372036854775807,9223372036854775807,9223372036854775807,0,2,9223372036854775808,9223372036854775808,9223372036854775808,0,0,18446744073709551615,18446744073709551615,18446744073709551615,0,1,18446744073709551616,18446744073709551616,18446744073709551616,0,1,9223372036854775808,0,170141183460469231731687303715884105727,0,2,9223372036854775809,1,0,0,0,1,0,0,2,6687732633507010627,121277680871763009708301092272169853159,291418864332232241439988395988053958886,0,2,12005993403289823856,18846464147442634679741936447216300117,18846464147442634679741936447216300117,0,1,13755114198790022993,75062002391258154113798633736831592143,245203185851727385845485937452715697870,0,2,4240003404856686742,114652594115518069740405279983274155324,114652594115518069740405279983274155324,0,2,3908884681216314335,166166142659951810159888545336341693602,166166142659951810159888545336341693602,0,2,17440629444037862079,93618597102288490283243262671139273493,263759780562757722014930566387023379220,0,1,15110565515775067384,60499749812274393893888994365558772441,230640933272743625625576298081442878168,0,0,10637694892982556223,136577765881053388728571471460255405342,306718949341522620460258775176139511069,0,1,1077612278795315321,65113537344948203193705796192292199208,65113537344948203193705796192292199208,0,2,12153076113251686214,59186799063098497820397840914283339502,229327982523567729552085144630167445229,0,2,7382704074506032912,110833547202564714803854007277418527310,280974730663033946535541310993302633037,0,1,18284253525118574450,87931291536685888760541015732968165503,87931291536685888760541015732968165503,0,0,11050837193185943773,131037031310206406097666786152457743889,131037031310206406097666786152457743889,0,1,8852713150229041818,126963949100461172014410937361609504979,297105132560930403746098241077493610706,0,1,12567760698021756916,60860382958469679551125634231078390727,231001566418938911282812937946962496454,0,0,5427446421247761510,6274627916369965814003806980848572626,6274627916369965814003806980848572626,0,0,1687377606097565490,9687398916324857071513154332292290797,9687398916324857071513154332292290797,0,1,15224556652184592776,35957535170334448313062028344843053711,206098718630803680044749332060727159438,0,1,7819419811464812767,110680871566469070899124639246164555658,280822055026938302630811942962048661385,0,0,4563296156804718024,130115090678679890393001477399677717019,130115090678679890393001477399677717019,0,1,11897046523553149717,34977586735391474740600109004789528994,34977586735391474740600109004789528994,0,0,215008598024121645,161419598747412801403378589501099002188,161419598747412801403378589501099002188,0,0,8290038785272756576,115333177062720042340636005575692405301,285474360523189274072323309291576511028,0,2,4143167085676553019,152883657307965189162822886067322056,152883657307965189162822886067322056,0,0,4639183038035131865,6167003650087614829768661713674713325,6167003650087614829768661713674713325,0,0,12635329586349386772,26907301159788152716437922254097286976,26907301159788152716437922254097286976,0,1,5188108461656871895,35394661592064597307009101925202309470,35394661592064597307009101925202309470,0,2,14577687255174296748,85864296478326116337732227011988408213,85864296478326116337732227011988408213,0,2,13708762935587331123,72204895092919586260016700124613422981,242346078553388817991704003840497528708,0,0,10777989948710609517,53405869510762131285719271039880375085,223547052971231363017406574755764480812,0,2,9022596745069434650,120006466838770586540610802252957381208,120006466838770586540610802252957381208,0,2,18408005745662445981,129524253855446463659403718320145127822,129524253855446463659403718320145127822,0,2,15603273561027753996,105243025728203090791907855961591827860,275384209188672322523595159677475933587,0,0,14948913663917856150,107239999239400919857985336041891460490,107239999239400919857985336041891460490,0,0,6491277964886498510,51285902985064743099156215266677513732,51285902985064743099156215266677513732]; +static sq: array = [0,0,0,0,0,1,0,0,0,340282366920938463463374607431768211455,2,0,0,0,340282366920938463463374607431768211454,3,1,0,0,340282366920938463463374607431768211453,9223372036854775807,3074457345618258602,0,0,340282366920938463454151235394913435649,9223372036854775808,3074457345618258602,0,0,340282366920938463454151235394913435648,18446744073709551615,6148914691236517205,0,0,340282366920938463444927863358058659841,18446744073709551616,6148914691236517205,0,0,340282366920938463444927863358058659840,170141183460469231731687303715884105727,56713727820156410577229101238628035242,9223372036854775807,1,170141183460469231731687303715884105729,170141183460469231731687303715884105728,283568639100782052886145506193140176214,340282366920938463454151235394913435649,340282366920938463463374607431768211455,340282366920938463463374607431768211455,0,0,0,1,291418864332232241439988395988053958886,323994532724703056122245870283863460600,340282366920938463460725711648671893669,0,48863502588706222023386211443714252570,18846464147442634679741936447216300117,6282154715814211559913978815738766705,1021668868616373733,0,321435902773495828783632670984551911339,245203185851727385845485937452715697870,308589306564534770924078384105417373594,340282366920938463458220354698099146623,0,95079181069211077617888669979052513586,114652594115518069740405279983274155324,38217531371839356580135093327758051774,6215329581057172646,0,225629772805420393722969327448494056132,166166142659951810159888545336341693602,55388714219983936719962848445447231200,9007884643272800451,0,174116224260986653303486062095426517854,263759780562757722014930566387023379220,314774838134878216313893260416853267378,340282366920938463459226309713080752215,0,76522586358180741448444041044744832236,230640933272743625625576298081442878168,303735222371540184184108504314993100360,340282366920938463457430933403978304994,0,109641433648194837837798309350325333288,306718949341522620460258775176139511069,329094561061133182462335996679891977994,340282366920938463461555130918986170080,0,33563417579415843003115832255628700387,65113537344948203193705796192292199208,21704512448316067731235265397430733069,3529811932380443311,0,275168829575990260269668811239476012248,229327982523567729552085144630167445229,303297572121814885492944786497901289381,340282366920938463457359758201247156137,0,110954384397370733911289462801600766227,280974730663033946535541310993302633037,320513154834970291154096841952279685317,340282366920938463460159534027978203967,0,59307636257904516927833296438465578419,87931291536685888760541015732968165503,29310430512228629586847005244322721834,4766764865676554509,0,252351075384252574702833591698800045953,131037031310206406097666786152457743889,43679010436735468699222262050819247963,7103531701128842548,0,209245335610732057365707821279310467567,297105132560930403746098241077493610706,325889955467602443557615818647010011206,340282366920938463461033964867016386106,0,43177234360008059717276366354274600750,231001566418938911282812937946962496454,303855433420271946069854050936832973122,340282366920938463457450483366007065556,0,109280800501999552180561669484805715002,6274627916369965814003806980848572626,2091542638789988604667935660282857542,340148260923325548,0,334007739004568497649370800450919638830,9687398916324857071513154332292290797,3229132972108285690504384777430763599,525154947540656571,0,330594968004613606391861453099475920659,206098718630803680044749332060727159438,295554484157560202323832848974754527450,340282366920938463456100497282358462728,0,134183648290134783418625275371041052018,280822055026938302630811942962048661385,320462262956271743185853719275195028099,340282366920938463460151257465161178796,0,59460311894000160832562664469719550071,130115090678679890393001477399677717019,43371696892893296797667159133225905673,7053553199348657235,0,210167276242258573070373130032090494437,34977586735391474740600109004789528994,11659195578463824913533369668263176331,1896138776340579981,0,305304780185546988722774498426978682462,161419598747412801403378589501099002188,53806532915804267134459529833699667396,8750573982184168479,0,178862768173525662059996017930669209268,285474360523189274072323309291576511028,322013031455022066999690841385037644647,340282366920938463460403459451466256598,0,54808006397749189391051298140191700428,152883657307965189162822886067322056,50961219102655063054274295355774018,8287839669541261,0,340129483263630498274211784545700889400,6167003650087614829768661713674713325,2055667883362538276589553904558237775,334313937757551380,0,334115363270850848633605945718093498131,26907301159788152716437922254097286976,8969100386596050905479307418032428992,1458647718658202412,0,313375065761150310746936685177670924480,35394661592064597307009101925202309470,11798220530688199102336367308400769823,1918748449625283975,0,304887705328873866156365505506565901986,85864296478326116337732227011988408213,28621432159442038779244075670662802737,4654712839037031145,0,254418070442612347125642380419779803243,242346078553388817991704003840497528708,307636937465088581639484406234677983874,340282366920938463458065470601105003347,0,97936288367549645471670603591270682748,223547052971231363017406574755764480812,301370595604369429981385263206433634575,340282366920938463457046373382265718977,0,116735313949707100445968032676003730644,120006466838770586540610802252957381208,40002155612923528846870267417652460402,6505563602945235774,0,220275900082167876922763805178810830248,129524253855446463659403718320145127822,43174751285148821219801239440048375940,7021523870981951473,0,210758113065491999803970889111623083634,275384209188672322523595159677475933587,318649647676849749816781458180337452167,340282366920938463459856471251586717065,0,64898157732266140939779447754292277869,107239999239400919857985336041891460490,35746666413133639952661778680630486830,5813492007635116020,0,233042367681537543605389271389876750966,51285902985064743099156215266677513732,17095300995021581033052071755559171244,2780214371714400566,0,288996463935873720364218392165090697724]; +static sr: array = [0,0,0,0,0,0,1,1,1,0,0,2,2,2,0,0,0,3,3,0,0,1,9223372036854775807,9223372036854775807,0,0,2,9223372036854775808,9223372036854775808,0,0,0,18446744073709551615,18446744073709551615,0,0,1,18446744073709551616,18446744073709551616,0,0,1,9223372036854775808,0,0,0,340282366920938463463374607431768211454,340282366920938463454151235394913435647,340282366920938463463374607431768211455,0,340282366920938463463374607431768211455,340282366920938463463374607431768211455,340282366920938463463374607431768211455,0,0,340282366920938463463374607431768211454,340282366920938463451615595991565670465,291418864332232241439988395988053958886,0,0,2,12005993403289823856,18846464147442634679741936447216300117,0,0,0,340282366920938463458682977556848682831,245203185851727385845485937452715697870,0,0,2,4240003404856686742,114652594115518069740405279983274155324,0,0,2,3908884681216314335,166166142659951810159888545336341693602,0,0,340282366920938463463374607431768211454,340282366920938463462368492802096521917,263759780562757722014930566387023379220,0,0,0,340282366920938463460038428873833727222,230640933272743625625576298081442878168,0,0,340282366920938463463374607431768211455,340282366920938463455565558251041216061,306718949341522620460258775176139511069,0,0,1,1077612278795315321,65113537344948203193705796192292199208,0,0,340282366920938463463374607431768211454,340282366920938463457080939471310346052,229327982523567729552085144630167445229,0,0,340282366920938463463374607431768211454,340282366920938463452310567432564692750,280974730663033946535541310993302633037,0,0,1,18284253525118574450,87931291536685888760541015732968165503,0,0,0,11050837193185943773,131037031310206406097666786152457743889,0,0,0,340282366920938463453780576508287701656,297105132560930403746098241077493610706,0,0,0,340282366920938463457495624056080416754,231001566418938911282812937946962496454,0,0,0,5427446421247761510,6274627916369965814003806980848572626,0,0,0,1687377606097565490,9687398916324857071513154332292290797,0,0,0,340282366920938463460152420010243252614,206098718630803680044749332060727159438,0,0,0,340282366920938463452747283169523472605,280822055026938302630811942962048661385,0,0,0,4563296156804718024,130115090678679890393001477399677717019,0,0,1,11897046523553149717,34977586735391474740600109004789528994,0,0,0,215008598024121645,161419598747412801403378589501099002188,0,0,340282366920938463463374607431768211455,340282366920938463453217902143331416414,285474360523189274072323309291576511028,0,0,2,4143167085676553019,152883657307965189162822886067322056,0,0,0,4639183038035131865,6167003650087614829768661713674713325,0,0,0,12635329586349386772,26907301159788152716437922254097286976,0,0,1,5188108461656871895,35394661592064597307009101925202309470,0,0,2,14577687255174296748,85864296478326116337732227011988408213,0,0,340282366920938463463374607431768211454,340282366920938463458636626293645990961,242346078553388817991704003840497528708,0,0,340282366920938463463374607431768211455,340282366920938463455705853306769269355,223547052971231363017406574755764480812,0,0,2,9022596745069434650,120006466838770586540610802252957381208,0,0,2,18408005745662445981,129524253855446463659403718320145127822,0,0,340282366920938463463374607431768211454,340282366920938463460531136919086413834,275384209188672322523595159677475933587,0,0,0,14948913663917856150,107239999239400919857985336041891460490,0,0,0,6491277964886498510,51285902985064743099156215266677513732,0]; +// Conversion references round integers directly to each IEEE format. +static cast_inputs: array = [0,1,2,3,9223372036854775807,9223372036854775808,18446744073709551615,18446744073709551616,170141183460469231731687303715884105727,170141183460469231731687303715884105728,340282366920938463463374607431768211455,291418864332232241439988395988053958886,18846464147442634679741936447216300117,245203185851727385845485937452715697870,114652594115518069740405279983274155324,166166142659951810159888545336341693602,263759780562757722014930566387023379220,230640933272743625625576298081442878168,306718949341522620460258775176139511069,65113537344948203193705796192292199208,229327982523567729552085144630167445229,280974730663033946535541310993302633037,87931291536685888760541015732968165503,131037031310206406097666786152457743889,297105132560930403746098241077493610706,231001566418938911282812937946962496454,6274627916369965814003806980848572626,9687398916324857071513154332292290797,206098718630803680044749332060727159438,280822055026938302630811942962048661385,130115090678679890393001477399677717019,34977586735391474740600109004789528994,161419598747412801403378589501099002188,285474360523189274072323309291576511028,152883657307965189162822886067322056,6167003650087614829768661713674713325,26907301159788152716437922254097286976,35394661592064597307009101925202309470,85864296478326116337732227011988408213,242346078553388817991704003840497528708,223547052971231363017406574755764480812,120006466838770586540610802252957381208,129524253855446463659403718320145127822,275384209188672322523595159677475933587,107239999239400919857985336041891460490,51285902985064743099156215266677513732,33554433,33554434,33554435,17179870207,17179870208,17179870209,19342814266755571402145791,19342814266755571402145792,19342814266755571402145793,18014398509481985,18014398509481986,18014398509481987,9223372036854776831,9223372036854776832,9223372036854776833,10384593717069656409982497265287167,10384593717069656409982497265287168,10384593717069656409982497265287169]; +static unsigned_f32: array = [0,1065353216,1073741824,1077936128,1593835520,1593835520,1602224128,1602224128,2130706432,2130706432,2139095040,2136685883,2103630631,2134407274,2125234835,2130314463,2135322185,2133689300,2137440236,2118381989,2133624566,2136170948,2122599911,2126850465,2136966238,2133707081,2090274401,2095658805,2132479275,2136163420,2126759555,2110948225,2129846417,2136392797,2045480440,2090104600,2107765059,2111112732,2122396089,2134266408,2133339545,2125762767,2126701294,2135895314,2124503896,2115654969,1275068416,1275068416,1275068417,1350565888,1350565888,1350565889,1769996288,1769996288,1769996289,1518338048,1518338048,1518338048,1593835520,1593835520,1593835520,2013265920,2013265920,2013265920]; +static signed_f32: array = [0,1065353216,1073741824,1077936128,1593835520,1593835520,1602224128,1602224128,2130706432,4278190080,3212836864,4262660883,2103630631,4270788395,2125234835,2130314463,4268115675,4272224344,4257874082,2118381989,4272353811,4264720625,2122599911,2126850465,4261539464,4272188783,2090274401,2095658805,4274644393,4264750735,2126759555,2110948225,2129846417,4263833229,2045480440,2090104600,2107765059,2111112732,2122396089,4271070128,4272923855,2125762767,2126701294,4265823161,2124503896,2115654969,1275068416,1275068416,1275068417,1350565888,1350565888,1350565889,1769996288,1769996288,1769996289,1518338048,1518338048,1518338048,1593835520,1593835520,1593835520,2013265920,2013265920,2013265920]; +static unsigned_f64: array = [0,4607182418800017408,4611686018427387904,4613937818241073152,4890909195324358656,4890909195324358656,4895412794951729152,4895412794951729152,5179139571476070400,5179139571476070400,5183643171103440896,5182349764959350897,5164603361375283340,5181126446135829048,5176202030015330553,5178929134568275502,5181617635107988035,5180740986519559106,5182754754837434040,5172522936524389465,5180706233002600537,5182073311042996556,5174787416035466668,5177069414898213043,5182500279226120669,5180750532399455961,5157432790288774386,5160323519767170183,5180091359507049417,5182069269752558556,5177020607767568331,5168531965061668807,5178677854625806135,5182192415253684082,5133384215617165709,5157341628989309164,5166823015617597019,5168620284097937182,5174677990228201509,5181050819135343626,5180553213071457257,5176485461677330615,5176989329126585220,5181925331171711651,5175809610510035576,5171058878788713601,4719772409618497536,4719772409752715264,4719772409886932992,4760304806398787584,4760304806399049728,4760304806399311872,4985484787767574528,4985484787767574528,4985484787767574528,4850376798678024192,4850376798678024192,4850376798678024193,4890909195324358656,4890909195324358656,4890909195324358657,5116089176692883456,5116089176692883456,5116089176692883457]; +static signed_f64: array = [0,4607182418800017408,4611686018427387904,4613937818241073152,4890909195324358656,4890909195324358656,4895412794951729152,4895412794951729152,5179139571476070400,14402511608330846208,13830554455654793216,14394174434025094716,5164603361375283340,14398537859011328912,5176202030015330553,5178929134568275502,14397102953430546164,14399308778243868797,14391604539949419073,5172522936524389465,14399378285277785934,14395280249690512078,5174787416035466668,5177069414898213043,14393572376958015629,14399289686484075085,5157432790288774386,5160323519767170183,14400608032268888174,14395296414852264081,5177020607767568331,5168531965061668807,5178677854625806135,14394803832847761976,5133384215617165709,5157341628989309164,5166823015617597019,5168620284097937182,5174677990228201509,14398689113012299755,14399684325140072494,5176485461677330615,5176989329126585220,14395872169175651701,5175809610510035576,5171058878788713601,4719772409618497536,4719772409752715264,4719772409886932992,4760304806398787584,4760304806399049728,4760304806399311872,4985484787767574528,4985484787767574528,4985484787767574528,4850376798678024192,4850376798678024192,4850376798678024193,4890909195324358656,4890909195324358656,4890909195324358657,5116089176692883456,5116089176692883456,5116089176692883457]; + +fun main() -> i32 { + var index: i32 = (time_now_monotonic_ns() as u64 % 229) as i32; + var count: i32 = 0; + var output: u128 = 0; + var signed_output: i128 = 0; + while (count < 229) { + var a: u128 = left[index]; + var b: u128 = right[index]; + var sa: i128 = a as i128; + var sb: i128 = b as i128; + udiv(&a, &b, &output); if (output != uq[index]) { return 1; } + urem(&a, &b, &output); if (output != ur[index]) { return 2; } + sdiv(&sa, &sb, &signed_output); if (signed_output != sq[index] as i128) { return 3; } + srem(&sa, &sb, &signed_output); if (signed_output != sr[index] as i128) { return 4; } + compound(&a, &b, &output); if (output != uq[index]) { return 5; } + index = (index + 1) % 229; count += 1; + } + index = (time_now_monotonic_ns() as u64 % 64) as i32; + count = 0; + while (count < 64) { + var a: u128 = cast_inputs[index]; var b: i128 = a as i128; + if (float_to_bits_f32(u_to_f32(&a)) != unsigned_f32[index] || float_to_bits_f32(s_to_f32(&b)) != signed_f32[index]) { return 6; } + if (float_to_bits_f64(u_to_f64(&a)) != unsigned_f64[index] || float_to_bits_f64(s_to_f64(&b)) != signed_f64[index]) { return 7; } + index = (index + 1) % 64; count += 1; + } + if (true) { var value: f64 = float_from_bits_f64(0); + f64_to_u(value, &output); if (output != 0) { return 8; } + f32_to_u(value as f32, &output); if (output != 0) { return 9; } + f64_to_s(value, &signed_output); if (signed_output != 0) { return 10; } + f32_to_s(value as f32, &signed_output); if (signed_output != 0) { return 11; } + } + if (true) { var value: f64 = float_from_bits_f64(9223372036854775808); + f64_to_u(value, &output); if (output != 0) { return 8; } + f32_to_u(value as f32, &output); if (output != 0) { return 9; } + f64_to_s(value, &signed_output); if (signed_output != 0) { return 10; } + f32_to_s(value as f32, &signed_output); if (signed_output != 0) { return 11; } + } + if (true) { var value: f64 = float_from_bits_f64(4604930618986332160); + f64_to_u(value, &output); if (output != 0) { return 8; } + f32_to_u(value as f32, &output); if (output != 0) { return 9; } + f64_to_s(value, &signed_output); if (signed_output != 0) { return 10; } + f32_to_s(value as f32, &signed_output); if (signed_output != 0) { return 11; } + } + if (true) { var value: f64 = float_from_bits_f64(13828302655841107968); + f64_to_u(value, &output); if (output != 0) { return 8; } + f32_to_u(value as f32, &output); if (output != 0) { return 9; } + f64_to_s(value, &signed_output); if (signed_output != 0) { return 10; } + f32_to_s(value as f32, &signed_output); if (signed_output != 0) { return 11; } + } + if (true) { var value: f64 = float_from_bits_f64(4607182418800017408); + f64_to_u(value, &output); if (output != 1) { return 8; } + f32_to_u(value as f32, &output); if (output != 1) { return 9; } + f64_to_s(value, &signed_output); if (signed_output != 1) { return 10; } + f32_to_s(value as f32, &signed_output); if (signed_output != 1) { return 11; } + } + if (true) { var value: f64 = float_from_bits_f64(13830554455654793216); + f64_to_s(value, &signed_output); if (signed_output != -1) { return 10; } + f32_to_s(value as f32, &signed_output); if (signed_output != -1) { return 11; } + } + if (true) { var value: f64 = float_from_bits_f64(4638417345121878016); + f64_to_u(value, &output); if (output != 123) { return 8; } + f32_to_u(value as f32, &output); if (output != 123) { return 9; } + f64_to_s(value, &signed_output); if (signed_output != 123) { return 10; } + f32_to_s(value as f32, &signed_output); if (signed_output != 123) { return 11; } + } + if (true) { var value: f64 = float_from_bits_f64(13861789381976653824); + f64_to_s(value, &signed_output); if (signed_output != -123) { return 10; } + f32_to_s(value as f32, &signed_output); if (signed_output != -123) { return 11; } + } + if (true) { var value: f64 = float_from_bits_f64(4890909195324358656); + f64_to_u(value, &output); if (output != 9223372036854775808) { return 8; } + f32_to_u(value as f32, &output); if (output != 9223372036854775808) { return 9; } + f64_to_s(value, &signed_output); if (signed_output != 9223372036854775808) { return 10; } + f32_to_s(value as f32, &signed_output); if (signed_output != 9223372036854775808) { return 11; } + } + if (true) { var value: f64 = float_from_bits_f64(14114281232179134464); + f64_to_s(value, &signed_output); if (signed_output != -9223372036854775808) { return 10; } + f32_to_s(value as f32, &signed_output); if (signed_output != -9223372036854775808) { return 11; } + } + if (true) { var value: f64 = float_from_bits_f64(5057542381537067008); + f64_to_u(value, &output); if (output != 1267650600228229401496703205376) { return 8; } + f32_to_u(value as f32, &output); if (output != 1267650600228229401496703205376) { return 9; } + f64_to_s(value, &signed_output); if (signed_output != 1267650600228229401496703205376) { return 10; } + f32_to_s(value as f32, &signed_output); if (signed_output != 1267650600228229401496703205376) { return 11; } + } + if (true) { var value: f64 = float_from_bits_f64(14280914418391842816); + f64_to_s(value, &signed_output); if (signed_output != -1267650600228229401496703205376) { return 10; } + f32_to_s(value as f32, &signed_output); if (signed_output != -1267650600228229401496703205376) { return 11; } + } + if (true) { var value: f64 = float_from_bits_f64(14402511608330846208); + f64_to_s(value, &signed_output); if (signed_output != -170141183460469231731687303715884105728) { return 10; } + f32_to_s(value as f32, &signed_output); if (signed_output != -170141183460469231731687303715884105728) { return 11; } + } + if (true) { var value: f64 = float_from_bits_f64(5179139571476070400); + f64_to_u(value, &output); if (output != 170141183460469231731687303715884105728) { return 8; } + f32_to_u(value as f32, &output); if (output != 170141183460469231731687303715884105728) { return 9; } + } + return 0; +} diff --git a/tests/frontend_regressions.rs b/tests/frontend_regressions.rs index f4015590..5e270b9e 100644 --- a/tests/frontend_regressions.rs +++ b/tests/frontend_regressions.rs @@ -772,3 +772,52 @@ fn missing_linker_keeps_phase_and_previous_artifact() { .to_string_lossy() .starts_with(".wave-output-"))); } + +#[test] +fn terminal_carets_use_display_cells_without_changing_json_locations() { + let dir = directory(); + let path = dir.join("display.wave"); + let source = "fun main() {\n\tprintln(\"한e\u{301}\"); @\n}\n"; + std::fs::write(&path, source).unwrap(); + let target = frontend_target(); + let human = Command::new(env!("CARGO_BIN_EXE_wavec")) + .env("NO_COLOR", "1") + .arg("check") + .arg(&path) + .args(["--target", &target]) + .output() + .unwrap(); + assert!(!human.status.success()); + let text = String::from_utf8(human.stderr).unwrap(); + assert!( + text.contains(" 2 | println(\"한e\u{301}\"); @"), + "{text}" + ); + assert!( + text.contains(&format!(" | {}^", " ".repeat(20))), + "{text}" + ); + let json = wave(&[ + OsStr::new("check"), + path.as_os_str(), + OsStr::new("--target"), + OsStr::new(&target), + OsStr::new("--error-format=json"), + ]); + let text = String::from_utf8(json.stderr).unwrap(); + let parsed = utils::json::parse(text.trim()).unwrap(); + let error = parsed.get("error").unwrap(); + assert_eq!(error.get_num("column"), Some(18.0)); + let span = error.get("span").unwrap(); + assert_eq!( + span.get_num("start"), + Some(source.find('@').unwrap() as f64) + ); + assert_eq!( + span.get_num("end"), + Some((source.find('@').unwrap() + 1) as f64) + ); + assert_eq!(span.get_num("column"), Some(18.0)); + assert_eq!(span.get_num("end_column"), Some(19.0)); + let _ = std::fs::remove_dir_all(dir); +} diff --git a/tests/native_providers.rs b/tests/native_providers.rs index a7899115..c797c132 100644 --- a/tests/native_providers.rs +++ b/tests/native_providers.rs @@ -326,3 +326,261 @@ fn darwin_bidirectional_c_abi_fixtures() { } } } + +#[test] +fn network_error_tables_and_async_sleep_results_run_on_native_hosts() { + let target = host_target(); + if !supported(&target) { + return; + } + let case = Case::new(); + for name in ["network_errors.wave", "async_sleep.wave"] { + for opt in ["-O0", "-O2"] { + let output = case.0.join("probe.exe"); + build(&case, &fixture(name), &target, opt, &output, false); + checked(&mut Command::new(output), name, &case.0); + } + } +} + +#[test] +fn full_range_trigonometry_matches_high_precision_references() { + let target = host_target(); + if !supported(&target) { + return; + } + let case = Case::new(); + let rows: Vec> = include_str!("fixtures/native_providers/trig_reference.txt") + .lines() + .filter(|s| !s.starts_with('#')) + .map(|s| { + s.split_whitespace() + .map(|n| u64::from_str_radix(n, 16).unwrap()) + .collect() + }) + .collect(); + let mut source = String::from("import(\"std::math::trig\")::{SinCosF64, SinCosF32, sin_cos_f64, sin_cos_f32, sin_f64, cos_f64, tan_f64, sin_f32, cos_f32, tan_f32, wrap_angle_pi_f64, MATH_PI_F64};\nimport(\"std::math::float\")::{abs_f64, float_from_bits_f64, float_from_bits_f32, float_to_bits_f64, float_to_bits_f32, nan_f64, infinity_f64, is_nan_f64};\n"); + for (column, name) in ["inputs", "sines", "cosines", "tangents"] + .iter() + .enumerate() + { + source += &format!( + "static {name}: array = [{}];\n", + rows.len(), + rows.iter() + .map(|r| r[column].to_string()) + .collect::>() + .join(",") + ); + } + source += &format!("const CASES: i32 = {};\n", rows.len()); + let single_rows: Vec> = + include_str!("fixtures/native_providers/trig_reference_f32.txt") + .lines() + .filter(|s| !s.starts_with('#')) + .map(|s| { + s.split_whitespace() + .map(|n| u64::from_str_radix(n, 16).unwrap()) + .collect() + }) + .collect(); + for (column, name) in ["inputs32", "sines32", "cosines32", "tangents32"] + .iter() + .enumerate() + { + source += &format!( + "static {name}: array = [{}];\n", + single_rows.len(), + single_rows + .iter() + .map(|r| r[column].to_string()) + .collect::>() + .join(",") + ); + } + source += &format!("const SINGLE_CASES: i32 = {};\n", single_rows.len()); + source += include_str!("fixtures/native_providers/trig_check.wave"); + let path = case.0.join("trig.wave"); + fs::write(&path, source).unwrap(); + for opt in ["-O0", "-O2"] { + let output = case.0.join("probe.exe"); + build(&case, &path, &target, opt, &output, false); + checked(&mut Command::new(output), "trig reference vectors", &case.0); + } +} + +#[test] +fn native_wide_arithmetic_is_freestanding_and_matches_reference_values() { + let target = host_target(); + if !supported(&target) { + return; + } + let case = Case::new(); + for opt in ["-O0", "-O2"] { + let output = case.0.join("wide.exe"); + build( + &case, + &fixture("wide_arithmetic.wave"), + &target, + opt, + &output, + false, + ); + checked(&mut Command::new(output), "native i128 runtime", &case.0); + } +} + +#[test] +fn wide_arithmetic_objects_do_not_reference_external_runtime_helpers() { + let case = Case::new(); + let source = root().join("tests/fixtures/wasm_wide/wide.wave"); + for target in [ + "x86_64-unknown-linux-gnu", + "aarch64-unknown-linux-gnu", + "riscv64-unknown-linux-gnu", + "loongarch64-unknown-linux-gnu", + "x86_64-apple-darwin", + "aarch64-apple-darwin", + "x86_64-pc-windows-msvc", + "aarch64-pc-windows-msvc", + "x86_64-unknown-freebsd", + ] { + if !supported(target) { + continue; + } + for opt in ["-O0", "-O2"] { + let output = case.0.join("wide.o"); + build(&case, &source, target, opt, &output, true); + let bytes = fs::read(output).unwrap(); + for symbol in [ + "__divti3", + "__udivti3", + "__modti3", + "__umodti3", + "__multi3", + "__ashlti3", + "__lshrti3", + "__ashrti3", + "__floattidf", + "__floattisf", + "__floatuntidf", + "__floatuntisf", + "__fixdfti", + "__fixsfti", + "__fixunsdfti", + "__fixunssfti", + ] { + assert!( + !bytes.windows(symbol.len()).any(|w| w == symbol.as_bytes()), + "{target} {opt} still references {symbol}" + ); + } + } + } +} + +#[test] +fn native_arithmetic_helpers_preserve_direct_lowering_and_private_symbol_ownership() { + let target = host_target(); + if !supported(&target) { + return; + } + let case = Case::new(); + let source = case.0.join("direct.wave"); + fs::write(&source, "export(c) fun multiply(a: u128, b: u128) -> u128 { return a * b; } export(c) fun shift(a: u128, b: u128) -> u128 { return a << b; } export(c) fun divide(a: u128) -> u128 { return a / 18446744073709551616; }").unwrap(); + for opt in ["-O0", "-O2"] { + checked( + case.compiler() + .arg("build") + .arg(&source) + .args(["--target", &target, opt, "--emit=ir", "--out-dir"]) + .arg(&case.0), + "native direct arithmetic", + &case.0, + ); + assert!(!fs::read_to_string(case.0.join("direct.ll")) + .unwrap() + .contains("__wave.runtime.")); + } + fs::write(&source, "extern(c, \"__wave.runtime.udiv.i128.i128\") fun user_symbol() -> u64; export(c) fun first(a: u128, b: u128) -> u128 { return a / b; } export(c) fun second(a: u128, b: u128) -> u128 { return a / b; } export(c) fun user() -> u64 { return user_symbol(); }").unwrap(); + checked( + case.compiler() + .arg("build") + .arg(&source) + .args(["--target", &target, "-O0", "--emit=ir", "--out-dir"]) + .arg(&case.0), + "native private arithmetic", + &case.0, + ); + let ir = fs::read_to_string(case.0.join("direct.ll")).unwrap(); + assert_eq!( + ir.matches("define private i128 @__wave.runtime.udiv.i128.i128.") + .count(), + 1, + "{ir}" + ); + assert!( + ir.contains("declare i64 @__wave.runtime.udiv.i128.i128()"), + "{ir}" + ); + assert!(!ir.contains("__wave.runtime.sdiv")); +} + +#[cfg(all( + target_os = "linux", + target_arch = "x86_64", + feature = "llvm-target-x86" +))] +#[test] +fn native_i128_runtime_preserves_the_public_c_abi() { + let case = Case::new(); + for opt in ["-O0", "-O2"] { + let object = case.0.join("wide.o"); + build( + &case, + &fixture("wide_abi.wave"), + &host_target(), + opt, + &object, + true, + ); + let binary = case.0.join("wide-c"); + checked( + Command::new("clang") + .arg(fixture("wide_abi.c")) + .arg(&object) + .args(["-O2", "-o"]) + .arg(&binary), + "i128 C ABI link", + &case.0, + ); + checked(&mut Command::new(binary), "i128 C ABI run", &case.0); + } +} + +#[test] +fn network_error_values_remain_available_without_a_socket_provider() { + let case = Case::new(); + let source = case.0.join("net-error.wave"); + fs::write(&source, "import(\"std::net::error\")::{NetError, net_error_from_native}; export(c) fun classify(value: i64) -> i32 { var error: NetError = net_error_from_native(value); return error.kind; }").unwrap(); + for target in [ + "wasm64-unknown-unknown", + "wasm32-unknown-unknown", + "wasm32-wasip1", + "x86_64-unknown-none-elf", + "aarch64-unknown-none-elf", + "riscv64-unknown-none-elf", + ] { + if !supported(target) { + continue; + } + checked( + case.compiler() + .arg("check") + .arg(&source) + .args(["--target", target]), + "portable network error values", + &case.0, + ); + } +} diff --git a/tools/generate_trig_vectors.py b/tools/generate_trig_vectors.py new file mode 100644 index 00000000..2115738c --- /dev/null +++ b/tools/generate_trig_vectors.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: MPL-2.0 +"""Regenerate pinned trig reference vectors and check the 2/pi reduction table. + +Maintenance-only dependency: mpmath 1.3.0 at 800 decimal digits. The compiler, +standard library and regression tests consume checked-in data without mpmath. +Inputs are reconstructed from their exact binary64 values before evaluation. +""" +from pathlib import Path +import math +import random +import struct +import re +import mpmath as mp + + +def bits(x): + return struct.unpack(">Q", struct.pack(">d", x))[0] + + +def main(): + mp.mp.dps = 800 + root = Path(__file__).resolve().parents[1] + constant = int((2 / mp.pi) * (1 << 2048)) + limbs = [(constant >> (32 * i)) & 0xFFFFFFFF for i in range(64)] + path = root / "std/math/trig_reduction.wave" + text = path.read_text() + actual = [int(x) for x in re.search(r"= \[(.*?)\];", text, re.S)[1].replace("\n", "").split(",")] + assert actual == limbs, "2/pi limbs differ from the high-precision reference" + samples = [0.0, -0.0, 5e-324, -5e-324, 1e-300, -1e-300, 0.1, 0.7853981633974483, + 1e6, 1e12, 1e20, 1e100, 1e200, 1e300, float.fromhex("0x1.fffffffffffffp1023")] + for n in [1, 2, 3, 4, 17, 1024, 1048576, 2**40, 2**100, 2**500, 2**1000]: + center = float(mp.pi * n / 2) + samples.extend([math.nextafter(center, -math.inf), center, math.nextafter(center, math.inf)]) + rng = random.Random(600) + for exponent in range(-1022, 1024, 17): + samples.append(math.ldexp(rng.uniform(1, 2), exponent)) + for _ in range(80): + samples.append(math.ldexp(rng.uniform(1, 2), rng.randrange(-1, 1024))) + samples += [-x for x in samples if x > 0] + write_vectors(root / "tests/fixtures/native_providers/trig_reference.txt", samples) + single = [0.0, -0.0] + for x in samples: + try: + single.append(struct.unpack(">f", struct.pack(">f", x))[0]) + except OverflowError: + pass + for raw in [1, 0x80000001, 0x7f7fffff, 0xff7fffff, 0x3fc90fda, 0x3fc90fdb, 0x3fc90fdc, + 0x40490fda, 0x40490fdb, 0x40490fdc]: + single.append(struct.unpack(">f", struct.pack(">I", raw))[0]) + write_vectors(root / "tests/fixtures/native_providers/trig_reference_f32.txt", single) + + +def write_vectors(path, samples): + lines = ["# Generated by tools/generate_trig_vectors.py (mpmath 1.3.0, 800 digits)", + "# Exact input, sin, cos, tan as hexadecimal binary64 bits"] + for x in samples: + # mpmath takes the exact binary float; do not round it through decimal text. + exact = mp.mpf(x) + values = [float(mp.sin(exact)), float(mp.cos(exact)), float(mp.tan(exact))] + if x == 0: # mpmath does not distinguish signed zero. + values[0] = values[2] = x + lines.append(" ".join(f"{bits(v):016x}" for v in [x, *values])) + path.write_text("\n".join(lines) + "\n") + + + +if __name__ == "__main__": + main() diff --git a/tools/generate_unicode_width.py b/tools/generate_unicode_width.py new file mode 100644 index 00000000..f7cd90f7 --- /dev/null +++ b/tools/generate_unicode_width.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: MPL-2.0 +"""Regenerate Utils terminal-width tables from pinned Unicode data (stdlib only).""" +from pathlib import Path +from urllib.request import urlopen + +VERSION = "17.0.0" +BASE = f"https://www.unicode.org/Public/{VERSION}/ucd/" + + +def read(name): + with urlopen(BASE + name, timeout=60) as response: + return response.read().decode("utf-8") + + +def ranges(values): + result = [] + for value in sorted(values): + if result and result[-1][1] + 1 == value: + result[-1][1] = value + else: + result.append([value, value]) + return result + + +def main(): + zero = set(range(0x1160, 0x1200)) # Hangul medial/final jamo join the initial cell. + for line in read("UnicodeData.txt").splitlines(): + fields = line.split(";") + if fields[2] in {"Mn", "Mc", "Me", "Cf"}: + zero.add(int(fields[0], 16)) + wide = set() + for line in read("EastAsianWidth.txt").splitlines(): + line = line.split("#")[0].strip() + if not line: + continue + interval, width = [part.strip() for part in line.split(";")] + if width not in {"W", "F"}: + continue + bounds = interval.split("..") + wide.update(range(int(bounds[0], 16), int(bounds[-1], 16) + 1)) + with urlopen("https://www.unicode.org/license.txt", timeout=60) as response: + license_text = response.read().decode("utf-8") + text = "// Generated by tools/generate_unicode_width.py; do not edit.\n" + text += f"// Unicode {VERSION}: {BASE}UnicodeData.txt and EastAsianWidth.txt\n" + text += "// SPDX-License-Identifier: Unicode-3.0\n//\n" + text += "\n".join("// " + line for line in license_text.splitlines()) + "\n\n" + text += f'pub const UNICODE_VERSION: &str = "{VERSION}";\n' + for name, values in [("ZERO_WIDTH", zero), ("WIDE", wide)]: + text += f"pub(super) const {name}: &[(u32, u32)] = &[\n" + text += "".join(f" (0x{a:X}, 0x{b:X}),\n" for a, b in ranges(values)) + text += "];\n" + output = Path(__file__).resolve().parents[1] / "utils/src/display_width_tables.rs" + output.write_text(text, encoding="utf-8") + + +if __name__ == "__main__": + main() diff --git a/utils/src/display_width.rs b/utils/src/display_width.rs new file mode 100644 index 00000000..49c8d864 --- /dev/null +++ b/utils/src/display_width.rs @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: MPL-2.0 +//! Terminal diagnostic layout; source locations stay in Unicode scalar columns. +//! Wide/fullwidth scalars occupy two cells, combining marks and format +//! characters zero, and ambiguous characters one. This is scalar cell width, +//! not terminal-dependent grapheme/emoji ligature shaping. +#[path = "display_width_tables.rs"] +mod tables; +pub use tables::UNICODE_VERSION; + +pub const TAB_STOP: usize = 4; + +fn in_ranges(c: char, ranges: &[(u32, u32)]) -> bool { + let value = c as u32; + let i = ranges.partition_point(|&(_, end)| end < value); + ranges.get(i).is_some_and(|&(start, _)| start <= value) +} + +pub fn cell_width(c: char) -> usize { + if in_ranges(c, tables::ZERO_WIDTH) { + 0 + } else if in_ranges(c, tables::WIDE) { + 2 + } else { + 1 + } +} + +pub struct DiagnosticLine { + pub text: String, + pub caret_offset: usize, + pub caret_width: usize, +} + +/// Expand tabs relative to the source (excluding the diagnostic gutter), and +/// project a scalar-column range into terminal cells. EOF/zero-width ranges +/// still get one caret. A multiline/oversized range stops at the displayed line. +pub fn diagnostic_line(source: &str, column: usize, length: usize) -> DiagnosticLine { + let start = column.saturating_sub(1); + let end = start.saturating_add(length); + let mut text = String::new(); + let mut cells = 0; + let mut caret_offset = 0; + let mut caret_width = 0; + for (index, c) in source.chars().enumerate() { + let width = if c == '\t' { + TAB_STOP - cells % TAB_STOP + } else { + cell_width(c) + }; + if c == '\t' { + text.push_str(&" ".repeat(width)); + } else { + text.push(c); + } + if index < start { + caret_offset += width; + } + if index >= start && index < end { + caret_width += width; + } + cells += width; + } + DiagnosticLine { + text, + caret_offset, + caret_width: caret_width.max(1), + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn aligns_tabs_wide_and_combining_text() { + let line = diagnostic_line("\t한e\u{301}\t文x", 6, 1); + assert_eq!(line.text, " 한e\u{301} 文x"); + assert_eq!((line.caret_offset, line.caret_width), (8, 2)); + let line = diagnostic_line("a\t文", 2, 2); + assert_eq!((line.caret_offset, line.caret_width), (1, 5)); + } + + #[test] + fn eof_and_zero_cell_ranges_remain_visible() { + let line = diagnostic_line("文e\u{301}", 3, 1); + assert_eq!((line.caret_offset, line.caret_width), (3, 1)); + let line = diagnostic_line("\t文", 3, 100); + assert_eq!((line.caret_offset, line.caret_width), (6, 1)); + assert_eq!(diagnostic_line("", 1, 0).caret_width, 1); + assert_eq!(diagnostic_line("abc", 2, usize::MAX).caret_width, 2); + } + + #[test] + fn pinned_tables_are_sorted_and_cover_supplementary_characters() { + assert_eq!(UNICODE_VERSION, "17.0.0"); + for ranges in [tables::WIDE, tables::ZERO_WIDTH] { + assert!(ranges.windows(2).all(|r| r[0].1 < r[1].0)); + } + assert_eq!(cell_width('한'), 2); + assert_eq!(cell_width('\u{20000}'), 2); + assert_eq!(cell_width('\u{e0100}'), 0); + assert_eq!(cell_width('é'), 1); + assert_eq!(cell_width('\u{903}'), 0); + } +} diff --git a/utils/src/display_width_tables.rs b/utils/src/display_width_tables.rs new file mode 100644 index 00000000..c325e928 --- /dev/null +++ b/utils/src/display_width_tables.rs @@ -0,0 +1,513 @@ +// Generated by tools/generate_unicode_width.py; do not edit. +// Unicode 17.0.0: https://www.unicode.org/Public/17.0.0/ucd/UnicodeData.txt and EastAsianWidth.txt +// SPDX-License-Identifier: Unicode-3.0 +// +// UNICODE LICENSE V3 +// +// COPYRIGHT AND PERMISSION NOTICE +// +// Copyright © 1991-2026 Unicode, Inc. +// +// NOTICE TO USER: Carefully read the following legal agreement. BY +// DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR +// SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +// TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT +// DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of data files and any associated documentation (the "Data Files") or +// software and any associated documentation (the "Software") to deal in the +// Data Files or Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, and/or sell +// copies of the Data Files or Software, and to permit persons to whom the +// Data Files or Software are furnished to do so, provided that either (a) +// this copyright and permission notice appear with all copies of the Data +// Files or Software, or (b) this copyright and permission notice appear in +// associated Documentation. +// +// THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +// KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF +// THIRD PARTY RIGHTS. +// +// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE +// BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, +// OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +// ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA +// FILES OR SOFTWARE. +// +// Except as contained in this notice, the name of a copyright holder shall +// not be used in advertising or otherwise to promote the sale, use or other +// dealings in these Data Files or Software without prior written +// authorization of the copyright holder. + +pub const UNICODE_VERSION: &str = "17.0.0"; +pub(super) const ZERO_WIDTH: &[(u32, u32)] = &[ + (0xAD, 0xAD), + (0x300, 0x36F), + (0x483, 0x489), + (0x591, 0x5BD), + (0x5BF, 0x5BF), + (0x5C1, 0x5C2), + (0x5C4, 0x5C5), + (0x5C7, 0x5C7), + (0x600, 0x605), + (0x610, 0x61A), + (0x61C, 0x61C), + (0x64B, 0x65F), + (0x670, 0x670), + (0x6D6, 0x6DD), + (0x6DF, 0x6E4), + (0x6E7, 0x6E8), + (0x6EA, 0x6ED), + (0x70F, 0x70F), + (0x711, 0x711), + (0x730, 0x74A), + (0x7A6, 0x7B0), + (0x7EB, 0x7F3), + (0x7FD, 0x7FD), + (0x816, 0x819), + (0x81B, 0x823), + (0x825, 0x827), + (0x829, 0x82D), + (0x859, 0x85B), + (0x890, 0x891), + (0x897, 0x89F), + (0x8CA, 0x903), + (0x93A, 0x93C), + (0x93E, 0x94F), + (0x951, 0x957), + (0x962, 0x963), + (0x981, 0x983), + (0x9BC, 0x9BC), + (0x9BE, 0x9C4), + (0x9C7, 0x9C8), + (0x9CB, 0x9CD), + (0x9D7, 0x9D7), + (0x9E2, 0x9E3), + (0x9FE, 0x9FE), + (0xA01, 0xA03), + (0xA3C, 0xA3C), + (0xA3E, 0xA42), + (0xA47, 0xA48), + (0xA4B, 0xA4D), + (0xA51, 0xA51), + (0xA70, 0xA71), + (0xA75, 0xA75), + (0xA81, 0xA83), + (0xABC, 0xABC), + (0xABE, 0xAC5), + (0xAC7, 0xAC9), + (0xACB, 0xACD), + (0xAE2, 0xAE3), + (0xAFA, 0xAFF), + (0xB01, 0xB03), + (0xB3C, 0xB3C), + (0xB3E, 0xB44), + (0xB47, 0xB48), + (0xB4B, 0xB4D), + (0xB55, 0xB57), + (0xB62, 0xB63), + (0xB82, 0xB82), + (0xBBE, 0xBC2), + (0xBC6, 0xBC8), + (0xBCA, 0xBCD), + (0xBD7, 0xBD7), + (0xC00, 0xC04), + (0xC3C, 0xC3C), + (0xC3E, 0xC44), + (0xC46, 0xC48), + (0xC4A, 0xC4D), + (0xC55, 0xC56), + (0xC62, 0xC63), + (0xC81, 0xC83), + (0xCBC, 0xCBC), + (0xCBE, 0xCC4), + (0xCC6, 0xCC8), + (0xCCA, 0xCCD), + (0xCD5, 0xCD6), + (0xCE2, 0xCE3), + (0xCF3, 0xCF3), + (0xD00, 0xD03), + (0xD3B, 0xD3C), + (0xD3E, 0xD44), + (0xD46, 0xD48), + (0xD4A, 0xD4D), + (0xD57, 0xD57), + (0xD62, 0xD63), + (0xD81, 0xD83), + (0xDCA, 0xDCA), + (0xDCF, 0xDD4), + (0xDD6, 0xDD6), + (0xDD8, 0xDDF), + (0xDF2, 0xDF3), + (0xE31, 0xE31), + (0xE34, 0xE3A), + (0xE47, 0xE4E), + (0xEB1, 0xEB1), + (0xEB4, 0xEBC), + (0xEC8, 0xECE), + (0xF18, 0xF19), + (0xF35, 0xF35), + (0xF37, 0xF37), + (0xF39, 0xF39), + (0xF3E, 0xF3F), + (0xF71, 0xF84), + (0xF86, 0xF87), + (0xF8D, 0xF97), + (0xF99, 0xFBC), + (0xFC6, 0xFC6), + (0x102B, 0x103E), + (0x1056, 0x1059), + (0x105E, 0x1060), + (0x1062, 0x1064), + (0x1067, 0x106D), + (0x1071, 0x1074), + (0x1082, 0x108D), + (0x108F, 0x108F), + (0x109A, 0x109D), + (0x1160, 0x11FF), + (0x135D, 0x135F), + (0x1712, 0x1715), + (0x1732, 0x1734), + (0x1752, 0x1753), + (0x1772, 0x1773), + (0x17B4, 0x17D3), + (0x17DD, 0x17DD), + (0x180B, 0x180F), + (0x1885, 0x1886), + (0x18A9, 0x18A9), + (0x1920, 0x192B), + (0x1930, 0x193B), + (0x1A17, 0x1A1B), + (0x1A55, 0x1A5E), + (0x1A60, 0x1A7C), + (0x1A7F, 0x1A7F), + (0x1AB0, 0x1ADD), + (0x1AE0, 0x1AEB), + (0x1B00, 0x1B04), + (0x1B34, 0x1B44), + (0x1B6B, 0x1B73), + (0x1B80, 0x1B82), + (0x1BA1, 0x1BAD), + (0x1BE6, 0x1BF3), + (0x1C24, 0x1C37), + (0x1CD0, 0x1CD2), + (0x1CD4, 0x1CE8), + (0x1CED, 0x1CED), + (0x1CF4, 0x1CF4), + (0x1CF7, 0x1CF9), + (0x1DC0, 0x1DFF), + (0x200B, 0x200F), + (0x202A, 0x202E), + (0x2060, 0x2064), + (0x2066, 0x206F), + (0x20D0, 0x20F0), + (0x2CEF, 0x2CF1), + (0x2D7F, 0x2D7F), + (0x2DE0, 0x2DFF), + (0x302A, 0x302F), + (0x3099, 0x309A), + (0xA66F, 0xA672), + (0xA674, 0xA67D), + (0xA69E, 0xA69F), + (0xA6F0, 0xA6F1), + (0xA802, 0xA802), + (0xA806, 0xA806), + (0xA80B, 0xA80B), + (0xA823, 0xA827), + (0xA82C, 0xA82C), + (0xA880, 0xA881), + (0xA8B4, 0xA8C5), + (0xA8E0, 0xA8F1), + (0xA8FF, 0xA8FF), + (0xA926, 0xA92D), + (0xA947, 0xA953), + (0xA980, 0xA983), + (0xA9B3, 0xA9C0), + (0xA9E5, 0xA9E5), + (0xAA29, 0xAA36), + (0xAA43, 0xAA43), + (0xAA4C, 0xAA4D), + (0xAA7B, 0xAA7D), + (0xAAB0, 0xAAB0), + (0xAAB2, 0xAAB4), + (0xAAB7, 0xAAB8), + (0xAABE, 0xAABF), + (0xAAC1, 0xAAC1), + (0xAAEB, 0xAAEF), + (0xAAF5, 0xAAF6), + (0xABE3, 0xABEA), + (0xABEC, 0xABED), + (0xFB1E, 0xFB1E), + (0xFE00, 0xFE0F), + (0xFE20, 0xFE2F), + (0xFEFF, 0xFEFF), + (0xFFF9, 0xFFFB), + (0x101FD, 0x101FD), + (0x102E0, 0x102E0), + (0x10376, 0x1037A), + (0x10A01, 0x10A03), + (0x10A05, 0x10A06), + (0x10A0C, 0x10A0F), + (0x10A38, 0x10A3A), + (0x10A3F, 0x10A3F), + (0x10AE5, 0x10AE6), + (0x10D24, 0x10D27), + (0x10D69, 0x10D6D), + (0x10EAB, 0x10EAC), + (0x10EFA, 0x10EFF), + (0x10F46, 0x10F50), + (0x10F82, 0x10F85), + (0x11000, 0x11002), + (0x11038, 0x11046), + (0x11070, 0x11070), + (0x11073, 0x11074), + (0x1107F, 0x11082), + (0x110B0, 0x110BA), + (0x110BD, 0x110BD), + (0x110C2, 0x110C2), + (0x110CD, 0x110CD), + (0x11100, 0x11102), + (0x11127, 0x11134), + (0x11145, 0x11146), + (0x11173, 0x11173), + (0x11180, 0x11182), + (0x111B3, 0x111C0), + (0x111C9, 0x111CC), + (0x111CE, 0x111CF), + (0x1122C, 0x11237), + (0x1123E, 0x1123E), + (0x11241, 0x11241), + (0x112DF, 0x112EA), + (0x11300, 0x11303), + (0x1133B, 0x1133C), + (0x1133E, 0x11344), + (0x11347, 0x11348), + (0x1134B, 0x1134D), + (0x11357, 0x11357), + (0x11362, 0x11363), + (0x11366, 0x1136C), + (0x11370, 0x11374), + (0x113B8, 0x113C0), + (0x113C2, 0x113C2), + (0x113C5, 0x113C5), + (0x113C7, 0x113CA), + (0x113CC, 0x113D0), + (0x113D2, 0x113D2), + (0x113E1, 0x113E2), + (0x11435, 0x11446), + (0x1145E, 0x1145E), + (0x114B0, 0x114C3), + (0x115AF, 0x115B5), + (0x115B8, 0x115C0), + (0x115DC, 0x115DD), + (0x11630, 0x11640), + (0x116AB, 0x116B7), + (0x1171D, 0x1172B), + (0x1182C, 0x1183A), + (0x11930, 0x11935), + (0x11937, 0x11938), + (0x1193B, 0x1193E), + (0x11940, 0x11940), + (0x11942, 0x11943), + (0x119D1, 0x119D7), + (0x119DA, 0x119E0), + (0x119E4, 0x119E4), + (0x11A01, 0x11A0A), + (0x11A33, 0x11A39), + (0x11A3B, 0x11A3E), + (0x11A47, 0x11A47), + (0x11A51, 0x11A5B), + (0x11A8A, 0x11A99), + (0x11B60, 0x11B67), + (0x11C2F, 0x11C36), + (0x11C38, 0x11C3F), + (0x11C92, 0x11CA7), + (0x11CA9, 0x11CB6), + (0x11D31, 0x11D36), + (0x11D3A, 0x11D3A), + (0x11D3C, 0x11D3D), + (0x11D3F, 0x11D45), + (0x11D47, 0x11D47), + (0x11D8A, 0x11D8E), + (0x11D90, 0x11D91), + (0x11D93, 0x11D97), + (0x11EF3, 0x11EF6), + (0x11F00, 0x11F01), + (0x11F03, 0x11F03), + (0x11F34, 0x11F3A), + (0x11F3E, 0x11F42), + (0x11F5A, 0x11F5A), + (0x13430, 0x13440), + (0x13447, 0x13455), + (0x1611E, 0x1612F), + (0x16AF0, 0x16AF4), + (0x16B30, 0x16B36), + (0x16F4F, 0x16F4F), + (0x16F51, 0x16F87), + (0x16F8F, 0x16F92), + (0x16FE4, 0x16FE4), + (0x16FF0, 0x16FF1), + (0x1BC9D, 0x1BC9E), + (0x1BCA0, 0x1BCA3), + (0x1CF00, 0x1CF2D), + (0x1CF30, 0x1CF46), + (0x1D165, 0x1D169), + (0x1D16D, 0x1D182), + (0x1D185, 0x1D18B), + (0x1D1AA, 0x1D1AD), + (0x1D242, 0x1D244), + (0x1DA00, 0x1DA36), + (0x1DA3B, 0x1DA6C), + (0x1DA75, 0x1DA75), + (0x1DA84, 0x1DA84), + (0x1DA9B, 0x1DA9F), + (0x1DAA1, 0x1DAAF), + (0x1E000, 0x1E006), + (0x1E008, 0x1E018), + (0x1E01B, 0x1E021), + (0x1E023, 0x1E024), + (0x1E026, 0x1E02A), + (0x1E08F, 0x1E08F), + (0x1E130, 0x1E136), + (0x1E2AE, 0x1E2AE), + (0x1E2EC, 0x1E2EF), + (0x1E4EC, 0x1E4EF), + (0x1E5EE, 0x1E5EF), + (0x1E6E3, 0x1E6E3), + (0x1E6E6, 0x1E6E6), + (0x1E6EE, 0x1E6EF), + (0x1E6F5, 0x1E6F5), + (0x1E8D0, 0x1E8D6), + (0x1E944, 0x1E94A), + (0xE0001, 0xE0001), + (0xE0020, 0xE007F), + (0xE0100, 0xE01EF), +]; +pub(super) const WIDE: &[(u32, u32)] = &[ + (0x1100, 0x115F), + (0x231A, 0x231B), + (0x2329, 0x232A), + (0x23E9, 0x23EC), + (0x23F0, 0x23F0), + (0x23F3, 0x23F3), + (0x25FD, 0x25FE), + (0x2614, 0x2615), + (0x2630, 0x2637), + (0x2648, 0x2653), + (0x267F, 0x267F), + (0x268A, 0x268F), + (0x2693, 0x2693), + (0x26A1, 0x26A1), + (0x26AA, 0x26AB), + (0x26BD, 0x26BE), + (0x26C4, 0x26C5), + (0x26CE, 0x26CE), + (0x26D4, 0x26D4), + (0x26EA, 0x26EA), + (0x26F2, 0x26F3), + (0x26F5, 0x26F5), + (0x26FA, 0x26FA), + (0x26FD, 0x26FD), + (0x2705, 0x2705), + (0x270A, 0x270B), + (0x2728, 0x2728), + (0x274C, 0x274C), + (0x274E, 0x274E), + (0x2753, 0x2755), + (0x2757, 0x2757), + (0x2795, 0x2797), + (0x27B0, 0x27B0), + (0x27BF, 0x27BF), + (0x2B1B, 0x2B1C), + (0x2B50, 0x2B50), + (0x2B55, 0x2B55), + (0x2E80, 0x2E99), + (0x2E9B, 0x2EF3), + (0x2F00, 0x2FD5), + (0x2FF0, 0x303E), + (0x3041, 0x3096), + (0x3099, 0x30FF), + (0x3105, 0x312F), + (0x3131, 0x318E), + (0x3190, 0x31E5), + (0x31EF, 0x321E), + (0x3220, 0x3247), + (0x3250, 0xA48C), + (0xA490, 0xA4C6), + (0xA960, 0xA97C), + (0xAC00, 0xD7A3), + (0xF900, 0xFAFF), + (0xFE10, 0xFE19), + (0xFE30, 0xFE52), + (0xFE54, 0xFE66), + (0xFE68, 0xFE6B), + (0xFF01, 0xFF60), + (0xFFE0, 0xFFE6), + (0x16FE0, 0x16FE4), + (0x16FF0, 0x16FF6), + (0x17000, 0x18CD5), + (0x18CFF, 0x18D1E), + (0x18D80, 0x18DF2), + (0x1AFF0, 0x1AFF3), + (0x1AFF5, 0x1AFFB), + (0x1AFFD, 0x1AFFE), + (0x1B000, 0x1B122), + (0x1B132, 0x1B132), + (0x1B150, 0x1B152), + (0x1B155, 0x1B155), + (0x1B164, 0x1B167), + (0x1B170, 0x1B2FB), + (0x1D300, 0x1D356), + (0x1D360, 0x1D376), + (0x1F004, 0x1F004), + (0x1F0CF, 0x1F0CF), + (0x1F18E, 0x1F18E), + (0x1F191, 0x1F19A), + (0x1F200, 0x1F202), + (0x1F210, 0x1F23B), + (0x1F240, 0x1F248), + (0x1F250, 0x1F251), + (0x1F260, 0x1F265), + (0x1F300, 0x1F320), + (0x1F32D, 0x1F335), + (0x1F337, 0x1F37C), + (0x1F37E, 0x1F393), + (0x1F3A0, 0x1F3CA), + (0x1F3CF, 0x1F3D3), + (0x1F3E0, 0x1F3F0), + (0x1F3F4, 0x1F3F4), + (0x1F3F8, 0x1F43E), + (0x1F440, 0x1F440), + (0x1F442, 0x1F4FC), + (0x1F4FF, 0x1F53D), + (0x1F54B, 0x1F54E), + (0x1F550, 0x1F567), + (0x1F57A, 0x1F57A), + (0x1F595, 0x1F596), + (0x1F5A4, 0x1F5A4), + (0x1F5FB, 0x1F64F), + (0x1F680, 0x1F6C5), + (0x1F6CC, 0x1F6CC), + (0x1F6D0, 0x1F6D2), + (0x1F6D5, 0x1F6D8), + (0x1F6DC, 0x1F6DF), + (0x1F6EB, 0x1F6EC), + (0x1F6F4, 0x1F6FC), + (0x1F7E0, 0x1F7EB), + (0x1F7F0, 0x1F7F0), + (0x1F90C, 0x1F93A), + (0x1F93C, 0x1F945), + (0x1F947, 0x1F9FF), + (0x1FA70, 0x1FA7C), + (0x1FA80, 0x1FA8A), + (0x1FA8E, 0x1FAC6), + (0x1FAC8, 0x1FAC8), + (0x1FACD, 0x1FADC), + (0x1FADF, 0x1FAEA), + (0x1FAEF, 0x1FAF8), + (0x20000, 0x2FFFD), + (0x30000, 0x3FFFD), +]; diff --git a/utils/src/lib.rs b/utils/src/lib.rs index 203f1a0b..296b989d 100644 --- a/utils/src/lib.rs +++ b/utils/src/lib.rs @@ -17,6 +17,7 @@ pub mod colorex; pub mod const_int; +pub mod display_width; pub mod formatx; pub mod json; pub mod paths;