///|
/// Auto-generated core modules for moonbit-eval interpreter
/// This file contains embedded RuntimePackage definitions for all moonbitlang/core modules

///|
let core_modules : Map[String, RuntimePackage] = {
  "abort": moonbitlang_core_abort_module,
  "moonbitlang/core/abort": moonbitlang_core_abort_module,
  "array": moonbitlang_core_array_module,
  "moonbitlang/core/array": moonbitlang_core_array_module,
  "bench": moonbitlang_core_bench_module,
  "moonbitlang/core/bench": moonbitlang_core_bench_module,
  "bigint": moonbitlang_core_bigint_module,
  "moonbitlang/core/bigint": moonbitlang_core_bigint_module,
  "bool": moonbitlang_core_bool_module,
  "moonbitlang/core/bool": moonbitlang_core_bool_module,
  "buffer": moonbitlang_core_buffer_module,
  "moonbitlang/core/buffer": moonbitlang_core_buffer_module,
  "builtin": moonbitlang_core_builtin_module,
  "moonbitlang/core/builtin": moonbitlang_core_builtin_module,
  "byte": moonbitlang_core_byte_module,
  "moonbitlang/core/byte": moonbitlang_core_byte_module,
  "bytes": moonbitlang_core_bytes_module,
  "moonbitlang/core/bytes": moonbitlang_core_bytes_module,
  "char": moonbitlang_core_char_module,
  "moonbitlang/core/char": moonbitlang_core_char_module,
  "cmp": moonbitlang_core_cmp_module,
  "moonbitlang/core/cmp": moonbitlang_core_cmp_module,
  "deque": moonbitlang_core_deque_module,
  "moonbitlang/core/deque": moonbitlang_core_deque_module,
  "double": moonbitlang_core_double_module,
  "moonbitlang/core/double": moonbitlang_core_double_module,
  "double/internal/ryu": moonbitlang_core_double_internal_ryu_module,
  "moonbitlang/core/double/internal/ryu": moonbitlang_core_double_internal_ryu_module,
  "env": moonbitlang_core_env_module,
  "moonbitlang/core/env": moonbitlang_core_env_module,
  "error": moonbitlang_core_error_module,
  "moonbitlang/core/error": moonbitlang_core_error_module,
  "float": moonbitlang_core_float_module,
  "moonbitlang/core/float": moonbitlang_core_float_module,
  "hashmap": moonbitlang_core_hashmap_module,
  "moonbitlang/core/hashmap": moonbitlang_core_hashmap_module,
  "hashset": moonbitlang_core_hashset_module,
  "moonbitlang/core/hashset": moonbitlang_core_hashset_module,
  "immut/array": moonbitlang_core_immut_array_module,
  "moonbitlang/core/immut/array": moonbitlang_core_immut_array_module,
  "immut/hashmap": moonbitlang_core_immut_hashmap_module,
  "moonbitlang/core/immut/hashmap": moonbitlang_core_immut_hashmap_module,
  "immut/hashset": moonbitlang_core_immut_hashset_module,
  "moonbitlang/core/immut/hashset": moonbitlang_core_immut_hashset_module,
  "immut/internal/path": moonbitlang_core_immut_internal_path_module,
  "moonbitlang/core/immut/internal/path": moonbitlang_core_immut_internal_path_module,
  "immut/internal/sparse_array": moonbitlang_core_immut_internal_sparse_array_module,
  "moonbitlang/core/immut/internal/sparse_array": moonbitlang_core_immut_internal_sparse_array_module,
  "immut/list": moonbitlang_core_immut_list_module,
  "moonbitlang/core/immut/list": moonbitlang_core_immut_list_module,
  "immut/priority_queue": moonbitlang_core_immut_priority_queue_module,
  "moonbitlang/core/immut/priority_queue": moonbitlang_core_immut_priority_queue_module,
  "immut/sorted_map": moonbitlang_core_immut_sorted_map_module,
  "moonbitlang/core/immut/sorted_map": moonbitlang_core_immut_sorted_map_module,
  "immut/sorted_set": moonbitlang_core_immut_sorted_set_module,
  "moonbitlang/core/immut/sorted_set": moonbitlang_core_immut_sorted_set_module,
  "int": moonbitlang_core_int_module,
  "moonbitlang/core/int": moonbitlang_core_int_module,
  "int16": moonbitlang_core_int16_module,
  "moonbitlang/core/int16": moonbitlang_core_int16_module,
  "int64": moonbitlang_core_int64_module,
  "moonbitlang/core/int64": moonbitlang_core_int64_module,
  "json": moonbitlang_core_json_module,
  "moonbitlang/core/json": moonbitlang_core_json_module,
  "list": moonbitlang_core_list_module,
  "moonbitlang/core/list": moonbitlang_core_list_module,
  "math": moonbitlang_core_math_module,
  "moonbitlang/core/math": moonbitlang_core_math_module,
  "option": moonbitlang_core_option_module,
  "moonbitlang/core/option": moonbitlang_core_option_module,
  "prelude": moonbitlang_core_prelude_module,
  "moonbitlang/core/prelude": moonbitlang_core_prelude_module,
  "priority_queue": moonbitlang_core_priority_queue_module,
  "moonbitlang/core/priority_queue": moonbitlang_core_priority_queue_module,
  "queue": moonbitlang_core_queue_module,
  "moonbitlang/core/queue": moonbitlang_core_queue_module,
  "quickcheck": moonbitlang_core_quickcheck_module,
  "moonbitlang/core/quickcheck": moonbitlang_core_quickcheck_module,
  "quickcheck/splitmix": moonbitlang_core_quickcheck_splitmix_module,
  "moonbitlang/core/quickcheck/splitmix": moonbitlang_core_quickcheck_splitmix_module,
  "random": moonbitlang_core_random_module,
  "moonbitlang/core/random": moonbitlang_core_random_module,
  "random/internal/random_source": moonbitlang_core_random_internal_random_source_module,
  "moonbitlang/core/random/internal/random_source": moonbitlang_core_random_internal_random_source_module,
  "rational": moonbitlang_core_rational_module,
  "moonbitlang/core/rational": moonbitlang_core_rational_module,
  "ref": moonbitlang_core_ref_module,
  "moonbitlang/core/ref": moonbitlang_core_ref_module,
  "result": moonbitlang_core_result_module,
  "moonbitlang/core/result": moonbitlang_core_result_module,
  "set": moonbitlang_core_set_module,
  "moonbitlang/core/set": moonbitlang_core_set_module,
  "sorted_map": moonbitlang_core_sorted_map_module,
  "moonbitlang/core/sorted_map": moonbitlang_core_sorted_map_module,
  "sorted_set": moonbitlang_core_sorted_set_module,
  "moonbitlang/core/sorted_set": moonbitlang_core_sorted_set_module,
  "strconv": moonbitlang_core_strconv_module,
  "moonbitlang/core/strconv": moonbitlang_core_strconv_module,
  "string": moonbitlang_core_string_module,
  "moonbitlang/core/string": moonbitlang_core_string_module,
  "test": moonbitlang_core_test_module,
  "moonbitlang/core/test": moonbitlang_core_test_module,
  "tuple": moonbitlang_core_tuple_module,
  "moonbitlang/core/tuple": moonbitlang_core_tuple_module,
  "uint": moonbitlang_core_uint_module,
  "moonbitlang/core/uint": moonbitlang_core_uint_module,
  "uint16": moonbitlang_core_uint16_module,
  "moonbitlang/core/uint16": moonbitlang_core_uint16_module,
  "uint64": moonbitlang_core_uint64_module,
  "moonbitlang/core/uint64": moonbitlang_core_uint64_module,
  "unit": moonbitlang_core_unit_module,
  "moonbitlang/core/unit": moonbitlang_core_unit_module,
}

///|
fn dummy_loc() -> @basic.Location {
  {
    start: { fname: "", lnum: 0, bol: 0, cnum: 0 },
    end: { fname: "", lnum: 0, bol: 0, cnum: 0 },
  }
}

///|
let moonbitlang_core_abort_module : RuntimePackage = RuntimePackage::new(
  "moonbitlang/core/abort",
  deps={},
  files={
    "moon.pkg.json": (
      #|{
      #|  "virtual": {
      #|    "has-default": true
      #|  }
      #|}
    ),
    "abort.mbt": (
      #|pub fn[T] abort(msg : String) -> T {
      #|  let _ = msg
      #|  panic_impl()
      #|}
      #|fn[T] panic_impl() -> T = "%panic"
    ),
  },
)

///|
let moonbitlang_core_array_module : RuntimePackage = RuntimePackage::new(
  "moonbitlang/core/array",
  deps={
    "moonbitlang/core/builtin": moonbitlang_core_builtin_module,
    "moonbitlang/core/bytes": moonbitlang_core_bytes_module,
    "moonbitlang/core/string": moonbitlang_core_string_module,
    "moonbitlang/core/quickcheck": moonbitlang_core_quickcheck_module,
    "moonbitlang/core/quickcheck/splitmix": moonbitlang_core_quickcheck_splitmix_module,
  },
  files={
    "moon.pkg.json": (
      #|{
      #|  "import": [
      #|    "moonbitlang/core/builtin",
      #|    "moonbitlang/core/bytes",
      #|    "moonbitlang/core/string",
      #|    "moonbitlang/core/quickcheck",
      #|    "moonbitlang/core/quickcheck/splitmix"
      #|  ],
      #|  "test-import": [
      #|    "moonbitlang/core/char",
      #|    "moonbitlang/core/test",
      #|    "moonbitlang/core/random",
      #|    "moonbitlang/core/json"
      #|  ],
      #|  "targets": {
      #|    "array_js.mbt": ["js"],
      #|    "array_nonjs.mbt": ["not", "js"],
      #|    "blit_js.mbt": ["js"],
      #|    "blit_nonjs.mbt": ["not", "js"],
      #|    "panic_test.mbt": ["not", "native", "llvm"]
      #|  }
      #|}
    ),
    "array.mbt": (
      #|pub fn[T] Array::from_iter(iter : Iter[T]) -> Array[T] {
      #|  iter.collect()
      #|}
      #|pub fn[T] Array::push_iter(self : Self[T], iter : Iter[T]) -> Unit {
      #|  for x in iter {
      #|    self.push(x)
      #|  }
      #|}
      #|pub fn[T] Array::makei(
      #|  length : Int,
      #|  value : (Int) -> T raise?,
      #|) -> Array[T] raise? {
      #|  if length <= 0 {
      #|    []
      #|  } else {
      #|    let array = Array::make(length, value(0))
      #|    for i in 1.. Int) -> Unit {
      #|  let n = self.length()
      #|  for i = n - 1; i > 0; i = i - 1 {
      #|    let j = rand(i + 1) % (i + 1)
      #|    self.swap(i, j)
      #|  }
      #|}
      #|pub fn[T] shuffle(self : Array[T], rand~ : (Int) -> Int) -> Array[T] {
      #|  let new_arr = self.copy()
      #|  Array::shuffle_in_place(new_arr, rand~)
      #|  new_arr
      #|}
      #|pub fn[A, B] filter_map(
      #|  self : Array[A],
      #|  f : (A) -> B? raise?,
      #|) -> Array[B] raise? {
      #|  let result = []
      #|  for x in self {
      #|    if f(x) is Some(x) {
      #|      result.push(x)
      #|    }
      #|  }
      #|  result
      #|}
      #|pub fn[A] last(self : Array[A]) -> A? {
      #|  match self {
      #|    [] => None
      #|    [.., last] => Some(last)
      #|  }
      #|}
      #|pub fn[A, B] zip(self : Array[A], other : Array[B]) -> Array[(A, B)] {
      #|  let length = if self.length() < other.length() {
      #|    self.length()
      #|  } else {
      #|    other.length()
      #|  }
      #|  let arr = Array::new(capacity=length)
      #|  for i in 0.. (Array[T1], Array[T2]) {
      #|  let arr1 : Array[T1] = Array::new(capacity=self.length())
      #|  let arr2 : Array[T2] = Array::new(capacity=self.length())
      #|  for pair in self {
      #|    let (x, y) = pair
      #|    arr1.push(x)
      #|    arr2.push(y)
      #|  }
      #|  (arr1, arr2)
      #|}
      #|pub fn[A, B, C] zip_with(
      #|  l : Array[A],
      #|  r : Array[B],
      #|  merge : (A, B) -> C raise?,
      #|) -> Array[C] raise? {
      #|  let length = if l.length() < r.length() { l.length() } else { r.length() }
      #|  let arr = Array::new(capacity=length)
      #|  for i in 0.. Iter2[A, B] {
      #|  Iter2::new(yield_ => {
      #|    let length = if self.length() < other.length() {
      #|      self.length()
      #|    } else {
      #|      other.length()
      #|    }
      #|    for i in 0.. X::arbitrary(x, rs))
      #|}
      #|pub fn[A : @string.ToStringView] Array::join(
      #|  self : Array[A],
      #|  separator : @string.View,
      #|) -> String {
      #|  self[:].join(separator)
      #|}
    ),
    "array_js.mbt": (
      #|priv type JSArray
      #|fn[T] JSArray::ofAnyArray(array : Array[T]) -> JSArray = "%identity"
      #|fn[T] JSArray::toAnyArray(self : JSArray) -> Array[T] = "%identity"
      #|fn[T] JSArray::ofAnyFixedArray(array : FixedArray[T]) -> JSArray = "%identity"
      #|fn[T] JSArray::toAnyFixedArray(self : JSArray) -> FixedArray[T] = "%identity"
      #|extern "js" fn JSArray::copy(self : JSArray) -> JSArray =
      #|  #|(arr) => arr.slice(0)
      #|pub fn[T] copy(self : Array[T]) -> Array[T] {
      #|  JSArray::ofAnyArray(self).copy().toAnyArray()
      #|}
    ),
    "array_nonjs.mbt": (
      #|pub fn[T] copy(self : Array[T]) -> Array[T] {
      #|  let len = self.length()
      #|  if len == 0 {
      #|    []
      #|  } else {
      #|    let arr = Array::make(len, self[0])
      #|    Array::unsafe_blit(arr, 0, self, 0, len)
      #|    arr
      #|  }
      #|}
    ),
    "blit.mbt": (
      #|test "copy" {
      #|  let a : FixedArray[_] = [1, 2, 3, 4]
      #|  let b = a.copy()
      #|  inspect(b, content="[1, 2, 3, 4]")
      #|  inspect(physical_equal(b, a), content="false")
      #|  let c = FixedArray::make(8, 0)
      #|  a.blit_to(c, len=4, dst_offset=3)
      #|  inspect(c, content="[0, 0, 0, 1, 2, 3, 4, 0]")
      #|  inspect(([] : FixedArray[Int]).copy(), content="[]")
      #|  a.blit_to(a, len=2, src_offset=1)
      #|  inspect(a, content="[2, 3, 3, 4]")
      #|}
      #|pub fn FixedArray::blit_from_bytesview(
      #|  self : FixedArray[Byte],
      #|  bytes_offset : Int,
      #|  src : @bytes.View,
      #|) -> Unit {
      #|  FixedArray::blit_from_bytes(
      #|    self,
      #|    bytes_offset,
      #|    src.data(),
      #|    src.start_offset(),
      #|    src.length(),
      #|  )
      #|}
    ),
    "blit_js.mbt": (
      #|pub fn[T] FixedArray::copy(self : FixedArray[T]) -> FixedArray[T] {
      #|  JSArray::ofAnyFixedArray(self).copy().toAnyFixedArray()
      #|}
    ),
    "blit_nonjs.mbt": (
      #|pub fn[T] FixedArray::copy(self : FixedArray[T]) -> FixedArray[T] {
      #|  let len = self.length()
      #|  if len == 0 {
      #|    []
      #|  } else {
      #|    let arr = FixedArray::make(len, self[0])
      #|    FixedArray::unsafe_blit(arr, 0, self, 0, len)
      #|    arr
      #|  }
      #|}
    ),
    "deprecated.mbt": (
      #|#deprecated("use method call")
      #|pub fnalias Array::push_iter
    ),
    "fixedarray.mbt": (
      #|pub fn[T] FixedArray::each(
      #|  self : FixedArray[T],
      #|  f : (T) -> Unit raise?,
      #|) -> Unit raise? {
      #|  for v in self {
      #|    f(v)
      #|  }
      #|}
      #|test "each" {
      #|  let mut i = 0
      #|  let mut failed = false
      #|  let f = elem => {
      #|    if elem != i + 1 {
      #|      failed = true
      #|    }
      #|    i = i + 1
      #|  }
      #|  {
      #|    i = 0
      #|    ([] : FixedArray[_]).each(f)
      #|    assert_false(failed)
      #|    inspect(i, content="0")
      #|  }
      #|  {
      #|    i = 0
      #|    ([1] : FixedArray[_]).each(f)
      #|    assert_false(failed)
      #|    inspect(i, content="1")
      #|  }
      #|  i = 0
      #|  ([1, 2, 3, 4, 5] : FixedArray[_]).each(f)
      #|  assert_false(failed)
      #|  inspect(i, content="5")
      #|}
      #|pub fn[T] FixedArray::eachi(
      #|  self : FixedArray[T],
      #|  f : (Int, T) -> Unit raise?,
      #|) -> Unit raise? {
      #|  for i, v in self {
      #|    f(i, v)
      #|  }
      #|}
      #|test "eachi" {
      #|  let mut i = 0
      #|  let mut failed = false
      #|  let f = (index, elem) => {
      #|    if index != i || elem != i + 1 {
      #|      failed = true
      #|    }
      #|    i = i + 1
      #|  }
      #|  {
      #|    i = 0
      #|    ([] : FixedArray[_]).eachi(f)
      #|    assert_false(failed)
      #|    inspect(i, content="0")
      #|  }
      #|  {
      #|    i = 0
      #|    ([1] : FixedArray[_]).eachi(f)
      #|    assert_false(failed)
      #|    inspect(i, content="1")
      #|  }
      #|  i = 0
      #|  ([1, 2, 3, 4, 5] : FixedArray[_]).eachi(f)
      #|  assert_false(failed)
      #|  inspect(i, content="5")
      #|}
      #|pub fn[T] FixedArray::rev_each(
      #|  self : FixedArray[T],
      #|  f : (T) -> Unit raise?,
      #|) -> Unit raise? {
      #|  for i = self.length() - 1; i >= 0; i = i - 1 {
      #|    f(self[i])
      #|  }
      #|}
      #|test "rev_each" {
      #|  let mut i = 6
      #|  let mut failed = false
      #|  let f = elem => {
      #|    if elem != i - 1 {
      #|      failed = true
      #|    }
      #|    i = i - 1
      #|  }
      #|  {
      #|    i = 1
      #|    ([] : FixedArray[_]).rev_each(f)
      #|    assert_false(failed)
      #|    inspect(i, content="1")
      #|  }
      #|  {
      #|    i = 2
      #|    ([1] : FixedArray[_]).rev_each(f)
      #|    assert_false(failed)
      #|    inspect(i, content="1")
      #|  }
      #|  i = 6
      #|  ([1, 2, 3, 4, 5] : FixedArray[_]).rev_each(f)
      #|  assert_false(failed)
      #|  inspect(i, content="1")
      #|}
      #|pub fn[T] FixedArray::rev_eachi(
      #|  self : FixedArray[T],
      #|  f : (Int, T) -> Unit raise?,
      #|) -> Unit raise? {
      #|  let len = self.length()
      #|  for i in 0.. {
      #|    if index != j || elem != i - 1 {
      #|      failed = true
      #|    }
      #|    i = i - 1
      #|    j = j + 1
      #|  }
      #|  {
      #|    i = 1
      #|    j = 0
      #|    ([] : FixedArray[_]).rev_eachi(f)
      #|    assert_false(failed)
      #|    inspect(i, content="1")
      #|    inspect(j, content="0")
      #|  }
      #|  {
      #|    i = 2
      #|    j = 0
      #|    ([1] : FixedArray[_]).rev_eachi(f)
      #|    assert_false(failed)
      #|    inspect(i, content="1")
      #|    inspect(j, content="1")
      #|  }
      #|  i = 6
      #|  j = 0
      #|  ([1, 2, 3, 4, 5] : FixedArray[_]).rev_eachi(f)
      #|  assert_false(failed)
      #|  inspect(i, content="1")
      #|  inspect(j, content="5")
      #|}
      #|pub fn[T, U] FixedArray::map(
      #|  self : FixedArray[T],
      #|  f : (T) -> U raise?,
      #|) -> FixedArray[U] raise? {
      #|  if self.length() == 0 {
      #|    return []
      #|  }
      #|  let res = FixedArray::make(self.length(), f(self[0]))
      #|  for i in 1.. x)
      #|  assert_eq(empty, [])
      #|  let simple_arr : FixedArray[_] = [6]
      #|  let simple_doubled = simple_arr.map(x => x * 2)
      #|  assert_eq(simple_doubled, [12])
      #|  let arr : FixedArray[_] = [1, 2, 3, 4, 5]
      #|  let doubled = arr.map(x => x * 2)
      #|  assert_eq(doubled, [2, 4, 6, 8, 10])
      #|}
      #|pub fn[T, U] FixedArray::mapi(
      #|  self : FixedArray[T],
      #|  f : (Int, T) -> U raise?,
      #|) -> FixedArray[U] raise? {
      #|  if self.length() == 0 {
      #|    return []
      #|  }
      #|  let res = FixedArray::make(self.length(), f(0, self[0]))
      #|  for i in 1.. x + i)
      #|  assert_eq(empty, [])
      #|  let simple_arr : FixedArray[_] = [6]
      #|  let simple_doubled = simple_arr.mapi((i, x) => x * 2 + i)
      #|  assert_eq(simple_doubled, [12])
      #|  let arr : FixedArray[_] = [1, 2, 3, 4, 5]
      #|  let doubled = arr.mapi((i, x) => x * 2 + i)
      #|  assert_eq(doubled, [2, 5, 8, 11, 14])
      #|}
      #|pub fn[T] FixedArray::makei(
      #|  length : Int,
      #|  value : (Int) -> T raise?,
      #|) -> FixedArray[T] raise? {
      #|  if length <= 0 {
      #|    []
      #|  } else {
      #|    let array = FixedArray::make(length, value(0))
      #|    for i in 1.. i)
      #|  inspect(empty.length(), content="0")
      #|  let simple_arr = FixedArray::makei(1, i => i)
      #|  inspect(simple_arr.length(), content="1")
      #|  inspect(simple_arr[0], content="0")
      #|  let arr = FixedArray::makei(2, i => i)
      #|  inspect(arr.length(), content="2")
      #|  inspect(arr[0], content="0")
      #|  inspect(arr[1], content="1")
      #|}
      #|pub fn[T] FixedArray::from_array(array : Array[T]) -> FixedArray[T] {
      #|  FixedArray::makei(array.length(), i => array[i])
      #|}
      #|test "from_array" {
      #|  let array = FixedArray::from_array([1, 2, 3, 4, 5])
      #|  assert_eq(array, [1, 2, 3, 4, 5])
      #|}
      #|pub fn[A, B] FixedArray::fold(
      #|  self : FixedArray[A],
      #|  init~ : B,
      #|  f : (B, A) -> B raise?,
      #|) -> B raise? {
      #|  for i = 0, acc = init; i < self.length(); {
      #|    continue i + 1, f(acc, self[i])
      #|  } else {
      #|    acc
      #|  }
      #|}
      #|test "fold" {
      #|  let sum = ([] : FixedArray[_]).fold(init=1, (sum, elem) => sum + elem)
      #|  inspect(sum, content="1")
      #|  let sum = ([1] : FixedArray[_]).fold(init=2, (sum, elem) => sum + elem)
      #|  inspect(sum, content="3")
      #|  let sum = ([1, 2, 3, 4, 5] : FixedArray[_]).fold(init=0, (sum, elem) => sum +
      #|    elem)
      #|  inspect(sum, content="15")
      #|}
      #|pub fn[A, B] FixedArray::rev_fold(
      #|  self : FixedArray[A],
      #|  init~ : B,
      #|  f : (B, A) -> B raise?,
      #|) -> B raise? {
      #|  for i = self.length() - 1, acc = init; i >= 0; {
      #|    continue i - 1, f(acc, self[i])
      #|  } else {
      #|    acc
      #|  }
      #|}
      #|test "rev_fold" {
      #|  let sum = ([] : FixedArray[_]).rev_fold(init=1, (sum, elem) => sum + elem)
      #|  inspect(sum, content="1")
      #|  let sum = ([1] : FixedArray[_]).rev_fold(init=2, (sum, elem) => sum + elem)
      #|  inspect(sum, content="3")
      #|  let sum = ([1, 2, 3, 4, 5] : FixedArray[_]).rev_fold(init=0, (sum, elem) => sum +
      #|    elem)
      #|  inspect(sum, content="15")
      #|}
      #|pub fn[A, B] FixedArray::foldi(
      #|  self : FixedArray[A],
      #|  init~ : B,
      #|  f : (Int, B, A) -> B raise?,
      #|) -> B raise? {
      #|  for i = 0, acc = init; i < self.length(); {
      #|    continue i + 1, f(i, acc, self[i])
      #|  } else {
      #|    acc
      #|  }
      #|}
      #|test "fold_lefti" {
      #|  let f = (index, sum, elem) => index + sum + elem
      #|  {
      #|    let sum = ([] : FixedArray[_]).foldi(init=1, f)
      #|    inspect(sum, content="1")
      #|  }
      #|  {
      #|    let sum = ([1] : FixedArray[_]).foldi(init=2, f)
      #|    inspect(sum, content="3")
      #|  }
      #|  let sum = ([1, 2, 3, 4, 5] : FixedArray[_]).foldi(init=0, f)
      #|  inspect(sum, content="25")
      #|}
      #|pub fn[A, B] FixedArray::rev_foldi(
      #|  self : FixedArray[A],
      #|  init~ : B,
      #|  f : (Int, B, A) -> B raise?,
      #|) -> B raise? {
      #|  let len = self.length()
      #|  for i = len - 1, acc = init; i >= 0; {
      #|    continue i - 1, f(len - i - 1, acc, self[i])
      #|  } else {
      #|    acc
      #|  }
      #|}
      #|test "rev_foldi" {
      #|  let f = (index, sum, elem) => index + sum + elem
      #|  {
      #|    let sum = ([] : FixedArray[_]).rev_foldi(init=1, f)
      #|    inspect(sum, content="1")
      #|  }
      #|  {
      #|    let sum = ([1] : FixedArray[_]).rev_foldi(init=2, f)
      #|    inspect(sum, content="3")
      #|  }
      #|  let sum = ([1, 2, 3, 4, 5] : FixedArray[_]).rev_foldi(init=0, f)
      #|  inspect(sum, content="25")
      #|}
      #|pub fn[T] FixedArray::rev_inplace(self : FixedArray[T]) -> Unit {
      #|  let mid_len = self.length() / 2
      #|  for i in 0.. FixedArray[T] {
      #|  match self {
      #|    [] => []
      #|    [.., first] => {
      #|      let res = FixedArray::make(self.length(), first)
      #|      let len = self.length()
      #|      for i in 1.. Unit {
      #|  let temp = self[i]
      #|  self[i] = self[j]
      #|  self[j] = temp
      #|}
      #|test "swap" {
      #|  {
      #|    let arr : FixedArray[Int] = [1]
      #|    arr.swap(0, 0)
      #|    assert_eq(arr, [1])
      #|  }
      #|  {
      #|    let arr : FixedArray[_] = [1, 2]
      #|    arr.swap(0, 0)
      #|    assert_eq(arr, [1, 2])
      #|    arr.swap(0, 1)
      #|    assert_eq(arr, [2, 1])
      #|  }
      #|  let arr : FixedArray[_] = [1, 2, 3, 4, 5]
      #|  arr.swap(3, 3)
      #|  assert_eq(arr, [1, 2, 3, 4, 5])
      #|  arr.swap(1, 3)
      #|  assert_eq(arr, [1, 4, 3, 2, 5])
      #|}
      #|pub fn[T] FixedArray::all(
      #|  self : FixedArray[T],
      #|  f : (T) -> Bool raise?,
      #|) -> Bool raise? {
      #|  for i in 0.. ele < 6))
      #|    assert_true(arr.all(ele => ele < 5))
      #|  }
      #|  {
      #|    let arr : FixedArray[_] = [5]
      #|    assert_true(arr.all(ele => ele < 6))
      #|    assert_false(arr.all(ele => ele < 5))
      #|  }
      #|  let arr : FixedArray[_] = [1, 2, 3, 4, 5]
      #|  assert_true(arr.all(ele => ele < 6))
      #|  assert_false(arr.all(ele => ele < 5))
      #|}
      #|pub fn[T] FixedArray::any(
      #|  self : FixedArray[T],
      #|  f : (T) -> Bool raise?,
      #|) -> Bool raise? {
      #|  for i in 0.. ele < 6))
      #|    assert_false(arr.any(ele => ele < 5))
      #|  }
      #|  {
      #|    let arr : FixedArray[_] = [5]
      #|    assert_true(arr.any(ele => ele < 6))
      #|    assert_false(arr.any(ele => ele < 5))
      #|  }
      #|  let arr : FixedArray[_] = [1, 2, 3, 4, 5]
      #|  assert_true(arr.any(ele => ele < 6))
      #|  assert_true(arr.any(ele => ele < 5))
      #|}
      #|test "fill" {
      #|  {
      #|    let arr : FixedArray[Int] = []
      #|    arr.fill(3)
      #|    assert_eq(arr, [])
      #|  }
      #|  {
      #|    let arr : FixedArray[_] = [6]
      #|    arr.fill(5)
      #|    assert_eq(arr, [5])
      #|  }
      #|  let arr : FixedArray[_] = [0, 0, 0, 0, 0]
      #|  arr.fill(3)
      #|  assert_eq(arr, [3, 3, 3, 3, 3])
      #|}
      #|pub fn[T : Eq] FixedArray::search(self : FixedArray[T], value : T) -> Int? {
      #|  for i in 0.. Bool {
      #|  for i in 0.. Bool {
      #|  if prefix.length() > self.length() {
      #|    return false
      #|  }
      #|  for i in 0.. Bool {
      #|  let self_len = self.length()
      #|  let suf_len = suffix.length()
      #|  if suf_len > self_len {
      #|    return false
      #|  }
      #|  for i in 0.. Bool {
      #|  if self.length() != that.length() {
      #|    return false
      #|  }
      #|  for i in 0.. if i < slen {
      #|    self[i]
      #|  } else {
      #|    other[i - slen]
      #|  })
      #|}
      #|test "op_add" {
      #|  {
      #|    inspect(([] : FixedArray[Int]) + [], content="[]")
      #|    inspect(([] : FixedArray[_]) + [1, 2, 3, 4, 5], content="[1, 2, 3, 4, 5]")
      #|    inspect(([1, 2, 3, 4, 5] : FixedArray[_]) + [], content="[1, 2, 3, 4, 5]")
      #|  }
      #|  {
      #|    inspect(([1] : FixedArray[_]) + [2], content="[1, 2]")
      #|    inspect(
      #|      ([1] : FixedArray[_]) + [1, 2, 3, 4, 5],
      #|      content="[1, 1, 2, 3, 4, 5]",
      #|    )
      #|    inspect(
      #|      ([1, 2, 3, 4, 5] : FixedArray[_]) + [1],
      #|      content="[1, 2, 3, 4, 5, 1]",
      #|    )
      #|  }
      #|  inspect(
      #|    ([1, 2, 3, 4, 5] : FixedArray[_]) + [6, 7, 8, 9, 10],
      #|    content="[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]",
      #|  )
      #|}
      #|test "iter" {
      #|  let arr : FixedArray[_] = [1, 2, 3, 4, 5]
      #|  let iter = arr.iter()
      #|  let exb = StringBuilder::new()
      #|  let mut i = 0
      #|  iter.each(x => {
      #|    exb.write_string(x.to_string())
      #|    exb.write_char('\n')
      #|    i = i + 1
      #|  })
      #|  assert_eq(i, arr.length())
      #|  inspect(
      #|    exb,
      #|    content=(
      #|      #|1
      #|      #|2
      #|      #|3
      #|      #|4
      #|      #|5
      #|      #|
      #|    ),
      #|  )
      #|}
      #|pub fn[T] FixedArray::from_iter(iter : Iter[T]) -> FixedArray[T] {
      #|  FixedArray::from_array(iter.collect())
      #|}
      #|pub fn[A] FixedArray::last(self : FixedArray[A]) -> A? {
      #|  match self {
      #|    [] => None
      #|    [.., last] => Some(last)
      #|  }
      #|}
      #|pub fn FixedArray::join(
      #|  self : FixedArray[String],
      #|  separator : @string.View,
      #|) -> String {
      #|  let len = self.length()
      #|  if len == 0 {
      #|    return ""
      #|  }
      #|  let first = self[0]
      #|  let mut size_hint = first.length()
      #|  for i in 1.. X::arbitrary(i, rs))
      #|}
    ),
    "fixedarray_sort.mbt": (
      #|pub fn[T : Compare] FixedArray::stable_sort(self : FixedArray[T]) -> Unit {
      #|  timsort({ array: self, start: 0, end: self.length() })
      #|}
      #|priv struct TimSortRun {
      #|  len : Int
      #|  start : Int
      #|}
      #|fn[T : Compare] timsort(arr : FixedArraySlice[T]) -> Unit {
      #|  let max_insertion = 20
      #|  let len = arr.length()
      #|  if len <= max_insertion {
      #|    FixedArraySlice::insertion_sort(arr)
      #|  }
      #|  let mut end = 0
      #|  let mut start = 0
      #|  let runs : Array[TimSortRun] = []
      #|  while end < len {
      #|    let (streak_end, was_reversed) = find_streak(arr.slice(start, arr.end))
      #|    end += streak_end
      #|    if was_reversed {
      #|      arr.slice(start, end).rev_inplace()
      #|    }
      #|    end = provide_sorted_batch(arr, start, end)
      #|    runs.push({ start, len: end - start })
      #|    start = end
      #|    while true {
      #|      guard collapse(runs, len) is Some(r) else { break }
      #|      let left = runs[r]
      #|      let right = runs[r + 1]
      #|      merge(arr.slice(left.start, right.start + right.len), left.len)
      #|      runs[r + 1] = { start: left.start, len: left.len + right.len }
      #|      runs.remove(r) |> ignore
      #|    }
      #|  }
      #|}
      #|fn[T : Compare] FixedArraySlice::insertion_sort(
      #|  arr : FixedArraySlice[T],
      #|) -> Unit {
      #|  for i in 1.. 0 && arr[j] < arr[j - 1]; j = j - 1 {
      #|      arr.swap(j, j - 1)
      #|    }
      #|  }
      #|}
      #|fn[T : Compare] merge(arr : FixedArraySlice[T], mid : Int) -> Unit {
      #|  let buf_len = arr.length() - mid
      #|  let buf : FixedArray[T] = FixedArray::make(buf_len, arr[mid])
      #|  for i in 0..=
      #|                         0 &&
      #|                         p2 >= 0; {
      #|    if arr[p1] > buf[p2] {
      #|      arr[p] = arr[p1]
      #|      continue p1 - 1, p2, p - 1
      #|    } else {
      #|      arr[p] = buf[p2]
      #|      continue p1, p2 - 1, p - 1
      #|    }
      #|  } else {
      #|    p2
      #|  }
      #|  for i = buf_remaining; i >= 0; i = i - 1 {
      #|    arr[i] = buf[i]
      #|  }
      #|}
      #|fn[T : Compare] find_streak(arr : FixedArraySlice[T]) -> (Int, Bool) {
      #|  let len = arr.length()
      #|  if len < 2 {
      #|    return (len, false)
      #|  }
      #|  let assume_reverse = arr[1] < arr[0]
      #|  if assume_reverse {
      #|    for end = 2 {
      #|      if end < len && arr[end] < arr[end - 1] {
      #|        continue end + 1
      #|      } else {
      #|        break (end, true)
      #|      }
      #|    }
      #|  } else {
      #|    for end = 2 {
      #|      if end < len && arr[end] >= arr[end - 1] {
      #|        continue end + 1
      #|      } else {
      #|        break (end, false)
      #|      }
      #|    }
      #|  }
      #|}
      #|fn[T : Compare] provide_sorted_batch(
      #|  arr : FixedArraySlice[T],
      #|  start : Int,
      #|  end : Int,
      #|) -> Int {
      #|  let len = arr.length()
      #|  let min_insertion_run = 10
      #|  let start_end_diff = end - start
      #|  if start_end_diff < min_insertion_run && end < len {
      #|    let sort_end = minimum(len, start + min_insertion_run)
      #|    FixedArraySlice::insertion_sort(arr.slice(start, sort_end))
      #|    sort_end
      #|  } else {
      #|    end
      #|  }
      #|}
      #|fn collapse(runs : Array[TimSortRun], stop : Int) -> Int? {
      #|  let n : Int = runs.length()
      #|  if n >= 2 &&
      #|    (
      #|      runs[n - 1].start + runs[n - 1].len == stop ||
      #|      runs[n - 2].len <= runs[n - 1].len ||
      #|      (n >= 3 && runs[n - 3].len <= runs[n - 2].len + runs[n - 1].len) ||
      #|      (n >= 4 && runs[n - 4].len <= runs[n - 3].len + runs[n - 2].len)
      #|    ) {
      #|    if n >= 3 && runs[n - 3].len < runs[n - 1].len {
      #|      Some(n - 3)
      #|    } else {
      #|      Some(n - 2)
      #|    }
      #|  } else {
      #|    None
      #|  }
      #|}
      #|pub fn[T : Compare] FixedArray::sort(self : FixedArray[T]) -> Unit {
      #|  fixed_quick_sort(
      #|    { array: self, start: 0, end: self.length() },
      #|    None,
      #|    fixed_get_limit(self.length()),
      #|  )
      #|}
      #|fn[T : Compare] fixed_quick_sort(
      #|  arr : FixedArraySlice[T],
      #|  pred : T?,
      #|  limit : Int,
      #|) -> Unit {
      #|  let mut limit = limit
      #|  let mut arr = arr
      #|  let mut pred = pred
      #|  let mut was_partitioned = true
      #|  let mut balanced = true
      #|  let bubble_sort_len = 16
      #|  while true {
      #|    let len = arr.length()
      #|    if len <= bubble_sort_len {
      #|      if len >= 2 {
      #|        fixed_bubble_sort(arr)
      #|      }
      #|      return
      #|    }
      #|    if limit == 0 {
      #|      fixed_heap_sort(arr)
      #|      return
      #|    }
      #|    let (pivot_index, likely_sorted) = fixed_choose_pivot(arr)
      #|    if was_partitioned && balanced && likely_sorted {
      #|      if fixed_try_bubble_sort(arr) {
      #|        return
      #|      }
      #|    }
      #|    let (pivot, partitioned) = fixed_partition(arr, pivot_index)
      #|    was_partitioned = partitioned
      #|    balanced = minimum(pivot, len - pivot) >= len / 8
      #|    if !balanced {
      #|      limit -= 1
      #|    }
      #|    if pred is Some(pred) {
      #|      if pred == arr[pivot] {
      #|        let mut i = pivot
      #|        while i < len && pred == arr[i] {
      #|          i = i + 1
      #|        }
      #|        arr = arr.slice(i, len)
      #|        continue
      #|      }
      #|    }
      #|    let left = arr.slice(0, pivot)
      #|    let right = arr.slice(pivot + 1, len)
      #|    if left.length() < right.length() {
      #|      fixed_quick_sort(left, pred, limit)
      #|      pred = Some(arr[pivot])
      #|      arr = right
      #|    } else {
      #|      fixed_quick_sort(right, Some(arr[pivot]), limit)
      #|      arr = left
      #|    }
      #|  }
      #|}
      #|fn fixed_get_limit(len : Int) -> Int {
      #|  let mut len = len
      #|  let mut limit = 0
      #|  while len > 0 {
      #|    len = len / 2
      #|    limit += 1
      #|  }
      #|  limit
      #|}
      #|fn[T : Compare] fixed_try_bubble_sort(arr : FixedArraySlice[T]) -> Bool {
      #|  let max_tries = 8
      #|  let mut tries = 0
      #|  for i in 1.. 0 && arr[j - 1] > arr[j]; j = j - 1 {
      #|      sorted = false
      #|      arr.swap(j, j - 1)
      #|    }
      #|    if !sorted {
      #|      tries += 1
      #|      if tries > max_tries {
      #|        return false
      #|      }
      #|    }
      #|  }
      #|  true
      #|}
      #|fn[T : Compare] fixed_bubble_sort(arr : FixedArraySlice[T]) -> Unit {
      #|  for i in 1.. 0 && arr[j - 1] > arr[j]; j = j - 1 {
      #|      arr.swap(j, j - 1)
      #|    }
      #|  }
      #|}
      #|test "fixed_try_bubble_sort" {
      #|  let arr : FixedArray[_] = [8, 7, 6, 5, 4, 3, 2, 1]
      #|  let sorted = fixed_try_bubble_sort({ array: arr, start: 0, end: 8 })
      #|  inspect(sorted, content="true")
      #|  assert_eq(arr, [1, 2, 3, 4, 5, 6, 7, 8])
      #|}
      #|fn[T : Compare] fixed_partition(
      #|  arr : FixedArraySlice[T],
      #|  pivot_index : Int,
      #|) -> (Int, Bool) {
      #|  arr.swap(pivot_index, arr.length() - 1)
      #|  let pivot = arr[arr.length() - 1]
      #|  let mut i = 0
      #|  let mut partitioned = true
      #|  for j in 0..<(arr.length() - 1) {
      #|    if arr[j] < pivot {
      #|      if i != j {
      #|        arr.swap(i, j)
      #|        partitioned = false
      #|      }
      #|      i = i + 1
      #|    }
      #|  }
      #|  arr.swap(i, arr.length() - 1)
      #|  (i, partitioned)
      #|}
      #|fn[T : Compare] fixed_choose_pivot(arr : FixedArraySlice[T]) -> (Int, Bool) {
      #|  let len = arr.length()
      #|  let use_median_of_medians = 50
      #|  let max_swaps = 4 * 3
      #|  let mut swaps = 0
      #|  let b = len / 4 * 2
      #|  if len >= 8 {
      #|    let a = len / 4 * 1
      #|    let c = len / 4 * 3
      #|    let sort_2 = (a : Int, b : Int) => if arr[a] > arr[b] {
      #|      arr.swap(a, b)
      #|      swaps += 1
      #|    }
      #|    let sort_3 = (a : Int, b : Int, c : Int) => {
      #|      sort_2(a, b)
      #|      sort_2(b, c)
      #|      sort_2(a, b)
      #|    }
      #|    if len > use_median_of_medians {
      #|      sort_3(a - 1, a, a + 1)
      #|      sort_3(b - 1, b, b + 1)
      #|      sort_3(c - 1, c, c + 1)
      #|    }
      #|    sort_3(a, b, c)
      #|  }
      #|  if swaps == max_swaps {
      #|    arr.rev_inplace()
      #|    (len - b - 1, true)
      #|  } else {
      #|    (b, swaps == 0)
      #|  }
      #|}
      #|fn[T : Compare] fixed_heap_sort(arr : FixedArraySlice[T]) -> Unit {
      #|  let len = arr.length()
      #|  for i = len / 2 - 1; i >= 0; i = i - 1 {
      #|    fixed_sift_down(arr, i)
      #|  }
      #|  for i = len - 1; i > 0; i = i - 1 {
      #|    arr.swap(0, i)
      #|    fixed_sift_down(arr.slice(0, i), 0)
      #|  }
      #|}
      #|fn[T : Compare] fixed_sift_down(arr : FixedArraySlice[T], index : Int) -> Unit {
      #|  let mut index = index
      #|  let len = arr.length()
      #|  let mut child = index * 2 + 1
      #|  while child < len {
      #|    if child + 1 < len && arr[child] < arr[child + 1] {
      #|      child = child + 1
      #|    }
      #|    if arr[index] >= arr[child] {
      #|      return
      #|    }
      #|    arr.swap(index, child)
      #|    index = child
      #|    child = index * 2 + 1
      #|  }
      #|}
      #|fn fixed_test_sort(f : (FixedArray[Int]) -> Unit) -> Unit raise {
      #|  let arr : FixedArray[_] = [5, 4, 3, 2, 1]
      #|  f(arr)
      #|  assert_eq(arr, [1, 2, 3, 4, 5])
      #|  let arr : FixedArray[_] = [5, 5, 5, 5, 1]
      #|  f(arr)
      #|  assert_eq(arr, [1, 5, 5, 5, 5])
      #|  let arr : FixedArray[_] = [1, 2, 3, 4, 5]
      #|  f(arr)
      #|  assert_eq(arr, [1, 2, 3, 4, 5])
      #|  let arr = FixedArray::make(1000, 0)
      #|  for i in 0..<1000 {
      #|    arr[i] = 1000 - i - 1
      #|  }
      #|  for i = 10; i < 1000; i = i + 10 {
      #|    arr.swap(i, i - 1)
      #|  }
      #|  f(arr)
      #|  let expected = FixedArray::make(1000, 0)
      #|  for i in 0..<1000 {
      #|    expected[i] = i
      #|  }
      #|  assert_eq(arr, expected)
      #|}
      #|test "fixed_heap_sort" {
      #|  fixed_test_sort(arr => fixed_heap_sort({
      #|    array: arr,
      #|    start: 0,
      #|    end: arr.length(),
      #|  }))
      #|}
      #|test "fixed_bubble_sort" {
      #|  fixed_test_sort(arr => fixed_bubble_sort({
      #|    array: arr,
      #|    start: 0,
      #|    end: arr.length(),
      #|  }))
      #|}
      #|test "sort" {
      #|  fixed_test_sort(arr => arr.sort())
      #|}
      #|test "stable_sort" {
      #|  let arr : FixedArray[_] = [5, 1, 3, 4, 2]
      #|  arr.stable_sort()
      #|  assert_eq(arr, [1, 2, 3, 4, 5])
      #|  let arr = FixedArray::make(1000, 0)
      #|  for i in 0..<1000 {
      #|    arr[i] = 1000 - i - 1
      #|  }
      #|  for i = 10; i < 1000; i = i + 10 {
      #|    arr.swap(i, i - 1)
      #|  }
      #|  arr.stable_sort()
      #|  let expected = FixedArray::make(1000, 0)
      #|  for i in 0..<1000 {
      #|    expected[i] = i
      #|  }
      #|  assert_eq(arr, expected)
      #|}
      #|pub fn[T : Compare] FixedArray::is_sorted(arr : FixedArray[T]) -> Bool {
      #|  for i in 1.. acc + x)
      #|  let arr = FixedArray::make(total_len, 0)
      #|  let mut index = 0
      #|  for i in 0.. K,
      #|) -> Unit {
      #|  fixed_quick_sort_by(
      #|    { array: self, start: 0, end: self.length() },
      #|    (a, b) => map(a).compare(map(b)),
      #|    None,
      #|    get_limit(self.length()),
      #|  )
      #|}
      #|test "@array.sort_by_key/basic" {
      #|  let arr : FixedArray[_] = [3, 1, 4, 1, 5]
      #|  arr.sort_by_key(x => x)
      #|  inspect(arr, content="[1, 1, 3, 4, 5]")
      #|  let arr2 : FixedArray[_] = [3, 1, 4, 1, 5]
      #|  arr2.sort_by_key(x => -x)
      #|  inspect(arr2, content="[5, 4, 3, 1, 1]")
      #|}
      #|pub fn[T] FixedArray::sort_by(
      #|  self : FixedArray[T],
      #|  cmp : (T, T) -> Int,
      #|) -> Unit {
      #|  fixed_quick_sort_by(
      #|    { array: self, start: 0, end: self.length() },
      #|    cmp,
      #|    None,
      #|    get_limit(self.length()),
      #|  )
      #|}
      #|test "sort_by: basic functionality" {
      #|  let arr : FixedArray[_] = [5, 3, 2, 4, 1]
      #|  arr.sort_by((a, b) => a - b)
      #|  inspect(arr, content="[1, 2, 3, 4, 5]")
      #|}
      #|test "sort_by: edge cases" {
      #|  let empty_arr : FixedArray[Int] = []
      #|  empty_arr.sort_by((a, b) => a - b)
      #|  inspect(empty_arr, content="[]")
      #|  let single_element_arr : FixedArray[_] = [1]
      #|  single_element_arr.sort_by((a, b) => a - b)
      #|  inspect(single_element_arr, content="[1]")
      #|}
      #|test "sort_by: random cases" {
      #|  let random_arr1 : FixedArray[_] = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
      #|  random_arr1.sort_by((a, b) => a - b)
      #|  inspect(random_arr1, content="[1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9]")
      #|  let random_arr2 : FixedArray[_] = [7, 1, 8, 2, 8, 1, 8, 2, 8, 4, 5, 9]
      #|  random_arr2.sort_by((a, b) => a - b)
      #|  inspect(random_arr2, content="[1, 1, 2, 2, 4, 5, 7, 8, 8, 8, 8, 9]")
      #|  let random_arr3 : FixedArray[_] = [10, -1, 0, 10, -1, 0, 10, -1, 0]
      #|  random_arr3.sort_by((a, b) => a - b)
      #|  inspect(random_arr3, content="[-1, -1, -1, 0, 0, 0, 10, 10, 10]")
      #|}
      #|test "sort_by: large array" {
      #|  let large_arr = FixedArray::makei(1000, i => 1000 - i)
      #|  large_arr.sort_by((a, b) => a - b)
      #|  let expected = FixedArray::makei(1000, i => i + 1)
      #|  inspect(large_arr, content=expected.to_string())
      #|}
      #|test "sort_by: negative numbers" {
      #|  let negative_arr : FixedArray[_] = [-5, -3, -2, -4, -1]
      #|  negative_arr.sort_by((a, b) => a - b)
      #|  inspect(negative_arr, content="[-5, -4, -3, -2, -1]")
      #|}
      #|test "sort_by: mixed positive and negative numbers" {
      #|  let mixed_arr : FixedArray[_] = [-5, 3, -2, 4, -1]
      #|  mixed_arr.sort_by((a, b) => a - b)
      #|  inspect(mixed_arr, content="[-5, -2, -1, 3, 4]")
      #|}
      #|fn[T] fixed_quick_sort_by(
      #|  arr : FixedArraySlice[T],
      #|  cmp : (T, T) -> Int,
      #|  pred : T?,
      #|  limit : Int,
      #|) -> Unit {
      #|  let mut limit = limit
      #|  let mut arr = arr
      #|  let mut pred = pred
      #|  let mut was_partitioned = true
      #|  let mut balanced = true
      #|  let bubble_sort_len = 16
      #|  while true {
      #|    let len = arr.length()
      #|    if len <= bubble_sort_len {
      #|      if len >= 2 {
      #|        fixed_bubble_sort_by(arr, cmp)
      #|      }
      #|      return
      #|    }
      #|    if limit == 0 {
      #|      fixed_heap_sort_by(arr, cmp)
      #|      return
      #|    }
      #|    let (pivot_index, likely_sorted) = fixed_choose_pivot_by(arr, cmp)
      #|    if was_partitioned && balanced && likely_sorted {
      #|      if fixed_try_bubble_sort_by(arr, cmp) {
      #|        return
      #|      }
      #|    }
      #|    let (pivot, partitioned) = fixed_partition_by(arr, cmp, pivot_index)
      #|    was_partitioned = partitioned
      #|    balanced = minimum(pivot, len - pivot) >= len / 8
      #|    if !balanced {
      #|      limit -= 1
      #|    }
      #|    if pred is Some(pred) {
      #|      if cmp(pred, arr[pivot]) == 0 {
      #|        let mut i = pivot
      #|        while i < len && cmp(pred, arr[i]) == 0 {
      #|          i = i + 1
      #|        }
      #|        arr = arr.slice(i, len)
      #|        continue
      #|      }
      #|    }
      #|    let left = arr.slice(0, pivot)
      #|    let right = arr.slice(pivot + 1, len)
      #|    if left.length() < right.length() {
      #|      fixed_quick_sort_by(left, cmp, pred, limit)
      #|      pred = Some(arr[pivot])
      #|      arr = right
      #|    } else {
      #|      fixed_quick_sort_by(right, cmp, Some(arr[pivot]), limit)
      #|      arr = left
      #|    }
      #|  }
      #|}
      #|fn[T] fixed_try_bubble_sort_by(
      #|  arr : FixedArraySlice[T],
      #|  cmp : (T, T) -> Int,
      #|) -> Bool {
      #|  let max_tries = 8
      #|  let mut tries = 0
      #|  for i in 1.. 0 && cmp(arr[j - 1], arr[j]) > 0; j = j - 1 {
      #|      sorted = false
      #|      arr.swap(j, j - 1)
      #|    }
      #|    if !sorted {
      #|      tries += 1
      #|      if tries > max_tries {
      #|        return false
      #|      }
      #|    }
      #|  }
      #|  true
      #|}
      #|fn[T] fixed_bubble_sort_by(
      #|  arr : FixedArraySlice[T],
      #|  cmp : (T, T) -> Int,
      #|) -> Unit {
      #|  for i in 1.. 0 && cmp(arr[j - 1], arr[j]) > 0; j = j - 1 {
      #|      arr.swap(j, j - 1)
      #|    }
      #|  }
      #|}
      #|test "try_bubble_sort" {
      #|  let arr : FixedArray[_] = [8, 7, 6, 5, 4, 3, 2, 1]
      #|  let sorted = fixed_try_bubble_sort_by({ array: arr, start: 0, end: 8 }, (a, b) => a -
      #|    b)
      #|  inspect(sorted, content="true")
      #|  assert_eq(arr, [1, 2, 3, 4, 5, 6, 7, 8])
      #|}
      #|fn[T] fixed_partition_by(
      #|  arr : FixedArraySlice[T],
      #|  cmp : (T, T) -> Int,
      #|  pivot_index : Int,
      #|) -> (Int, Bool) {
      #|  arr.swap(pivot_index, arr.length() - 1)
      #|  let pivot = arr[arr.length() - 1]
      #|  let mut i = 0
      #|  let mut partitioned = true
      #|  for j in 0..<(arr.length() - 1) {
      #|    if cmp(arr[j], pivot) < 0 {
      #|      if i != j {
      #|        arr.swap(i, j)
      #|        partitioned = false
      #|      }
      #|      i = i + 1
      #|    }
      #|  }
      #|  arr.swap(i, arr.length() - 1)
      #|  (i, partitioned)
      #|}
      #|fn[T] fixed_choose_pivot_by(
      #|  arr : FixedArraySlice[T],
      #|  cmp : (T, T) -> Int,
      #|) -> (Int, Bool) {
      #|  let len = arr.length()
      #|  let use_median_of_medians = 50
      #|  let max_swaps = 4 * 3
      #|  let mut swaps = 0
      #|  let b = len / 4 * 2
      #|  if len >= 8 {
      #|    let a = len / 4 * 1
      #|    let c = len / 4 * 3
      #|    let sort_2 = (a : Int, b : Int) => if cmp(arr[a], arr[b]) > 0 {
      #|      arr.swap(a, b)
      #|      swaps += 1
      #|    }
      #|    let sort_3 = (a : Int, b : Int, c : Int) => {
      #|      sort_2(a, b)
      #|      sort_2(b, c)
      #|      sort_2(a, b)
      #|    }
      #|    if len > use_median_of_medians {
      #|      sort_3(a - 1, a, a + 1)
      #|      sort_3(b - 1, b, b + 1)
      #|      sort_3(c - 1, c, c + 1)
      #|    }
      #|    sort_3(a, b, c)
      #|  }
      #|  if swaps == max_swaps {
      #|    arr.rev_inplace()
      #|    (len - b - 1, true)
      #|  } else {
      #|    (b, swaps == 0)
      #|  }
      #|}
      #|fn[T] fixed_heap_sort_by(arr : FixedArraySlice[T], cmp : (T, T) -> Int) -> Unit {
      #|  let len = arr.length()
      #|  for i = len / 2 - 1; i >= 0; i = i - 1 {
      #|    fixed_sift_down_by(arr, i, cmp)
      #|  }
      #|  for i = len - 1; i > 0; i = i - 1 {
      #|    arr.swap(0, i)
      #|    fixed_sift_down_by(arr.slice(0, i), 0, cmp)
      #|  }
      #|}
      #|fn[T] fixed_sift_down_by(
      #|  arr : FixedArraySlice[T],
      #|  index : Int,
      #|  cmp : (T, T) -> Int,
      #|) -> Unit {
      #|  let mut index = index
      #|  let len = arr.length()
      #|  let mut child = index * 2 + 1
      #|  while child < len {
      #|    if child + 1 < len && cmp(arr[child], arr[child + 1]) < 0 {
      #|      child = child + 1
      #|    }
      #|    if cmp(arr[index], arr[child]) >= 0 {
      #|      return
      #|    }
      #|    arr.swap(index, child)
      #|    index = child
      #|    child = index * 2 + 1
      #|  }
      #|}
      #|test "heap_sort" {
      #|  fixed_test_sort(arr => fixed_heap_sort_by(
      #|    { array: arr, start: 0, end: arr.length() },
      #|    (a, b) => a - b,
      #|  ))
      #|}
      #|test "bubble_sort" {
      #|  fixed_test_sort(arr => fixed_bubble_sort_by(
      #|    { array: arr, start: 0, end: arr.length() },
      #|    (a, b) => a - b,
      #|  ))
      #|}
      #|test "sort" {
      #|  fixed_test_sort(arr => arr.sort())
      #|}
      #|test "sort_by" {
      #|  let arr = [5, 1, 3, 4, 2]
      #|  arr.sort_by_key(x => -x)
      #|  assert_eq(arr, [5, 4, 3, 2, 1])
      #|}
      #|test "sort_by_fallback" {
      #|  let arr = FixedArray::makei(100, i => if i % 2 == 0 { 1 } else { 0 })
      #|  arr.sort_by(
      #|    (a, b) => if a < b { -1 } else { 1 },
      #|  )
      #|  assert_true(arr.is_sorted())
      #|}
    ),
    "slice.mbt": (
      #|priv struct FixedArraySlice[T] {
      #|  array : FixedArray[T]
      #|  start : Int
      #|  end : Int
      #|}
      #|fn[T] FixedArraySlice::length(self : FixedArraySlice[T]) -> Int {
      #|  self.end - self.start
      #|}
      #|fn[T] FixedArraySlice::op_get(self : FixedArraySlice[T], index : Int) -> T {
      #|  self.array[self.start + index]
      #|}
      #|fn[T] FixedArraySlice::op_set(
      #|  self : FixedArraySlice[T],
      #|  index : Int,
      #|  value : T,
      #|) -> Unit {
      #|  self.array[self.start + index] = value
      #|}
      #|fn[T] FixedArraySlice::swap(
      #|  self : FixedArraySlice[T],
      #|  a : Int,
      #|  b : Int,
      #|) -> Unit {
      #|  self.array.swap(self.start + a, self.start + b)
      #|}
      #|fn[T] FixedArraySlice::rev_inplace(self : FixedArraySlice[T]) -> Unit {
      #|  let len = self.length()
      #|  let mid_len = len / 2
      #|  for i in 0.. FixedArraySlice[T] {
      #|  { array: self.array, start: self.start + start, end: self.start + end }
      #|}
    ),
    "sort.mbt": (
      #|pub fn[T : Compare] sort(self : Array[T]) -> Unit {
      #|  let len = self.length()
      #|  quick_sort(self[:len], None, get_limit(len))
      #|}
      #|fn[T : Compare] quick_sort(arr : ArrayView[T], pred : T?, limit : Int) -> Unit {
      #|  let mut limit = limit
      #|  let mut arr = arr
      #|  let mut pred = pred
      #|  let mut was_partitioned = true
      #|  let mut balanced = true
      #|  let insertion_sort_len = 16
      #|  while true {
      #|    let len = arr.length()
      #|    if len <= insertion_sort_len {
      #|      if len >= 2 {
      #|        ArrayView::insertion_sort(arr)
      #|      }
      #|      return
      #|    }
      #|    if limit == 0 {
      #|      heap_sort(arr)
      #|      return
      #|    }
      #|    let (pivot_index, likely_sorted) = choose_pivot(arr)
      #|    if was_partitioned && balanced && likely_sorted {
      #|      if try_bubble_sort(arr) {
      #|        return
      #|      }
      #|    }
      #|    let (pivot, partitioned) = partition(arr, pivot_index)
      #|    was_partitioned = partitioned
      #|    balanced = minimum(pivot, len - pivot) >= len / 8
      #|    if !balanced {
      #|      limit -= 1
      #|    }
      #|    if pred is Some(pred) {
      #|      if pred == arr[pivot] {
      #|        let mut i = pivot
      #|        while i < len && pred == arr[i] {
      #|          i = i + 1
      #|        }
      #|        arr = arr[i:len]
      #|        continue
      #|      }
      #|    }
      #|    let left = arr[0:pivot]
      #|    let right = arr[pivot + 1:len]
      #|    if left.length() < right.length() {
      #|      quick_sort(left, pred, limit)
      #|      pred = Some(arr[pivot])
      #|      arr = right
      #|    } else {
      #|      quick_sort(right, Some(arr[pivot]), limit)
      #|      arr = left
      #|    }
      #|  }
      #|}
      #|fn get_limit(len : Int) -> Int {
      #|  let mut len = len
      #|  let mut limit = 0
      #|  while len > 0 {
      #|    len = len / 2
      #|    limit += 1
      #|  }
      #|  limit
      #|}
      #|fn[T : Compare] try_bubble_sort(arr : ArrayView[T]) -> Bool {
      #|  let max_tries = 8
      #|  let mut tries = 0
      #|  for i in 1.. 0 && arr[j - 1] > arr[j]; j = j - 1 {
      #|      sorted = false
      #|      arr.swap(j, j - 1)
      #|    }
      #|    if !sorted {
      #|      tries += 1
      #|      if tries > max_tries {
      #|        return false
      #|      }
      #|    }
      #|  }
      #|  true
      #|}
      #|fn[T : Compare] ArrayView::insertion_sort(arr : ArrayView[T]) -> Unit {
      #|  for i in 1.. 0 && arr[j - 1] > arr[j]; j = j - 1 {
      #|      arr.swap(j, j - 1)
      #|    }
      #|  }
      #|}
      #|fn[T : Compare] partition(arr : ArrayView[T], pivot_index : Int) -> (Int, Bool) {
      #|  arr.swap(pivot_index, arr.length() - 1)
      #|  let pivot = arr[arr.length() - 1]
      #|  let mut i = 0
      #|  let mut partitioned = true
      #|  for j in 0..<(arr.length() - 1) {
      #|    if arr[j] < pivot {
      #|      if i != j {
      #|        arr.swap(i, j)
      #|        partitioned = false
      #|      }
      #|      i = i + 1
      #|    }
      #|  }
      #|  arr.swap(i, arr.length() - 1)
      #|  (i, partitioned)
      #|}
      #|fn[T : Compare] choose_pivot(arr : ArrayView[T]) -> (Int, Bool) {
      #|  let len = arr.length()
      #|  let use_median_of_medians = 50
      #|  let max_swaps = 4 * 3
      #|  let mut swaps = 0
      #|  let b = len / 4 * 2
      #|  if len >= 8 {
      #|    let a = len / 4 * 1
      #|    let c = len / 4 * 3
      #|    let sort_2 = (a : Int, b : Int) => if arr[a] > arr[b] {
      #|      arr.swap(a, b)
      #|      swaps += 1
      #|    }
      #|    let sort_3 = (a : Int, b : Int, c : Int) => {
      #|      sort_2(a, b)
      #|      sort_2(b, c)
      #|      sort_2(a, b)
      #|    }
      #|    if len > use_median_of_medians {
      #|      sort_3(a - 1, a, a + 1)
      #|      sort_3(b - 1, b, b + 1)
      #|      sort_3(c - 1, c, c + 1)
      #|    }
      #|    sort_3(a, b, c)
      #|  }
      #|  if swaps == max_swaps {
      #|    arr.rev_inplace()
      #|    (len - b - 1, true)
      #|  } else {
      #|    (b, swaps == 0)
      #|  }
      #|}
      #|fn[T : Compare] heap_sort(arr : ArrayView[T]) -> Unit {
      #|  let len = arr.length()
      #|  for i = len / 2 - 1; i >= 0; i = i - 1 {
      #|    sift_down(arr, i)
      #|  }
      #|  for i = len - 1; i > 0; i = i - 1 {
      #|    arr.swap(0, i)
      #|    sift_down(arr[0:i], 0)
      #|  }
      #|}
      #|fn[T : Compare] sift_down(arr : ArrayView[T], index : Int) -> Unit {
      #|  let mut index = index
      #|  let len = arr.length()
      #|  let mut child = index * 2 + 1
      #|  while child < len {
      #|    if child + 1 < len && arr[child] < arr[child + 1] {
      #|      child = child + 1
      #|    }
      #|    if arr[index] >= arr[child] {
      #|      return
      #|    }
      #|    arr.swap(index, child)
      #|    index = child
      #|    child = index * 2 + 1
      #|  }
      #|}
      #|fn test_sort(f : (Array[Int]) -> Unit) -> Unit raise {
      #|  let arr = [5, 4, 3, 2, 1]
      #|  f(arr)
      #|  assert_eq(arr, [1, 2, 3, 4, 5])
      #|  let arr = [5, 5, 5, 5, 1]
      #|  f(arr)
      #|  assert_eq(arr, [1, 5, 5, 5, 5])
      #|  let arr = [1, 2, 3, 4, 5]
      #|  f(arr)
      #|  assert_eq(arr, [1, 2, 3, 4, 5])
      #|  let arr = Array::new(capacity=1000)
      #|  for i in 0..<1000 {
      #|    arr.push(1000 - i - 1)
      #|  }
      #|  for i = 10; i < 1000; i = i + 10 {
      #|    arr.swap(i, i - 1)
      #|  }
      #|  f(arr)
      #|  let expected = Array::new(capacity=1000)
      #|  for i in 0..<1000 {
      #|    expected.push(i)
      #|  }
      #|  assert_eq(arr, expected)
      #|}
      #|test "try_bubble_sort" {
      #|  let arr = [8, 7, 6, 5, 4, 3, 2, 1]
      #|  let sorted = try_bubble_sort(arr[0:8])
      #|  inspect(sorted, content="true")
      #|  assert_eq(arr, [1, 2, 3, 4, 5, 6, 7, 8])
      #|}
      #|test "heap_sort" {
      #|  test_sort(arr => heap_sort(arr[:]))
      #|}
      #|test "insertion_sort" {
      #|  test_sort(arr => ArrayView::insertion_sort(arr[:]))
      #|}
      #|test "sort" {
      #|  test_sort(arr => arr.sort())
      #|}
      #|test "sort with same pivot optimization" {
      #|  let arr = [
      #|    35, 43, 72, 83, 39, 4, 83, 18, 43, 25, 88, 51, 43, 60, 83, 6, 36, 68, 79, 86,
      #|  ]
      #|  arr.sort()
      #|  assert_eq(arr, [
      #|    4, 6, 18, 25, 35, 36, 39, 43, 43, 43, 51, 60, 68, 72, 79, 83, 83, 83, 86, 88,
      #|  ])
      #|}
      #|test "heap_sort coverage" {
      #|  let arr = [5, 4, 3, 2, 1]
      #|  heap_sort(arr[:])
      #|  assert_eq(arr, [1, 2, 3, 4, 5])
      #|  let arr2 = [1, 2, 3, 4, 5]
      #|  heap_sort(arr2[:])
      #|  assert_eq(arr2, [1, 2, 3, 4, 5])
      #|  let arr2 = [1, 2, 3, 4, 5]
      #|  heap_sort(arr2[:])
      #|  assert_eq(arr2, [1, 2, 3, 4, 5])
      #|  let arr3 = [5, 5, 5, 5, 1]
      #|  heap_sort(arr3[:])
      #|  assert_eq(arr3, [1, 5, 5, 5, 5])
      #|}
      #|test "quick_sort limit check" {
      #|  let arr = [5, 4, 3, 2, 1]
      #|  quick_sort(arr[:], None, 0)
      #|  assert_eq(arr, [1, 2, 3, 4, 5])
      #|  let arr2 = [1, 2, 3, 4, 5]
      #|  quick_sort(arr2[:], None, 0)
      #|  assert_eq(arr2, [1, 2, 3, 4, 5])
      #|  let arr3 = [5, 5, 5, 5, 1]
      #|  quick_sort(arr3[:], None, 0)
      #|  assert_eq(arr3, [1, 5, 5, 5, 5])
      #|}
      #|test "quick_sort with pred check" {
      #|  let arr = []
      #|  for i = 16; i >= 0; i = i - 1 {
      #|    arr.push(i)
      #|  }
      #|  quick_sort(arr[:], Some(8), 0)
      #|  assert_eq(arr, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])
      #|  let arr = [5, 4, 3, 2, 1]
      #|  quick_sort(arr[:], Some(3), 0)
      #|  assert_eq(arr, [1, 2, 3, 4, 5])
      #|  let arr2 = [1, 2, 3, 4, 5]
      #|  quick_sort(arr2[:], Some(3), 0)
      #|  assert_eq(arr2, [1, 2, 3, 4, 5])
      #|  let arr3 = [5, 5, 5, 5, 1]
      #|  quick_sort(arr3[:], Some(3), 0)
      #|  assert_eq(arr3, [1, 5, 5, 5, 5])
      #|}
      #|test "quick_sort with unbalanced partitions" {
      #|  let arr = []
      #|  for i = 16; i >= 0; i = i - 1 {
      #|    arr.push(if i >= 8 { i } else { 8 })
      #|  }
      #|  quick_sort(arr[:], Some(8), 42)
      #|  assert_eq(arr, [8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 12, 13, 14, 15, 16])
      #|  let arr = [5, 4, 3, 2, 1]
      #|  quick_sort(arr[:], None, 1)
      #|  assert_eq(arr, [1, 2, 3, 4, 5])
      #|  let arr2 = [1, 2, 3, 4, 5]
      #|  quick_sort(arr2[:], None, 1)
      #|  assert_eq(arr2, [1, 2, 3, 4, 5])
      #|  let arr3 = [5, 5, 5, 5, 1]
      #|  quick_sort(arr3[:], None, 1)
      #|  assert_eq(arr3, [1, 5, 5, 5, 5])
      #|}
      #|test "quick_sort with pivot equal to pred" {
      #|  let arr = [5, 4, 3, 2, 1]
      #|  quick_sort(arr[:], Some(3), 0)
      #|  assert_eq(arr, [1, 2, 3, 4, 5])
      #|}
      #|test "quick_sort with pred less than all elements" {
      #|  let arr = [5, 4, 3, 2, 1]
      #|  quick_sort(arr[:], Some(0), 0)
      #|  assert_eq(arr, [1, 2, 3, 4, 5])
      #|}
      #|test "quick_sort with pred greater than all elements" {
      #|  let arr = [5, 4, 3, 2, 1]
      #|  quick_sort(arr[:], Some(6), 0)
      #|  assert_eq(arr, [1, 2, 3, 4, 5])
      #|}
    ),
    "sort_by.mbt": (
      #|pub fn[T, K : Compare] sort_by_key(self : Array[T], map : (T) -> K) -> Unit {
      #|  quick_sort_by(
      #|    self[:],
      #|    (a, b) => map(a).compare(map(b)),
      #|    None,
      #|    get_limit(self.length()),
      #|  )
      #|}
      #|pub fn[T] sort_by(self : Array[T], cmp : (T, T) -> Int) -> Unit {
      #|  quick_sort_by(self[:], cmp, None, get_limit(self.length()))
      #|}
      #|fn[T] quick_sort_by(
      #|  arr : ArrayView[T],
      #|  cmp : (T, T) -> Int,
      #|  pred : T?,
      #|  limit : Int,
      #|) -> Unit {
      #|  let mut limit = limit
      #|  let mut arr = arr
      #|  let mut pred = pred
      #|  let mut was_partitioned = true
      #|  let mut balanced = true
      #|  let bubble_sort_len = 16
      #|  while true {
      #|    let len = arr.length()
      #|    if len <= bubble_sort_len {
      #|      if len >= 2 {
      #|        bubble_sort_by(arr, cmp)
      #|      }
      #|      return
      #|    }
      #|    if limit == 0 {
      #|      heap_sort_by(arr, cmp)
      #|      return
      #|    }
      #|    let (pivot_index, likely_sorted) = choose_pivot_by(arr, cmp)
      #|    if was_partitioned && balanced && likely_sorted {
      #|      if try_bubble_sort_by(arr, cmp) {
      #|        return
      #|      }
      #|    }
      #|    let (pivot, partitioned) = partition_by(arr, cmp, pivot_index)
      #|    was_partitioned = partitioned
      #|    balanced = minimum(pivot, len - pivot) >= len / 8
      #|    if !balanced {
      #|      limit -= 1
      #|    }
      #|    if pred is Some(pred) {
      #|      if cmp(pred, arr[pivot]) == 0 {
      #|        let mut i = pivot
      #|        while i < len && cmp(pred, arr[i]) == 0 {
      #|          i = i + 1
      #|        }
      #|        arr = arr[i:len]
      #|        continue
      #|      }
      #|    }
      #|    let left = arr[0:pivot]
      #|    let right = arr[pivot + 1:len]
      #|    if left.length() < right.length() {
      #|      quick_sort_by(left, cmp, pred, limit)
      #|      pred = Some(arr[pivot])
      #|      arr = right
      #|    } else {
      #|      quick_sort_by(right, cmp, Some(arr[pivot]), limit)
      #|      arr = left
      #|    }
      #|  }
      #|}
      #|fn[T] try_bubble_sort_by(arr : ArrayView[T], cmp : (T, T) -> Int) -> Bool {
      #|  let max_tries = 8
      #|  let mut tries = 0
      #|  for i in 1.. 0 && cmp(arr[j - 1], arr[j]) > 0; j = j - 1 {
      #|      sorted = false
      #|      arr.swap(j, j - 1)
      #|    }
      #|    if !sorted {
      #|      tries += 1
      #|      if tries > max_tries {
      #|        return false
      #|      }
      #|    }
      #|  }
      #|  true
      #|}
      #|fn[T] bubble_sort_by(arr : ArrayView[T], cmp : (T, T) -> Int) -> Unit {
      #|  for i in 1.. 0 && cmp(arr[j - 1], arr[j]) > 0; j = j - 1 {
      #|      arr.swap(j, j - 1)
      #|    }
      #|  }
      #|}
      #|fn[T] partition_by(
      #|  arr : ArrayView[T],
      #|  cmp : (T, T) -> Int,
      #|  pivot_index : Int,
      #|) -> (Int, Bool) {
      #|  arr.swap(pivot_index, arr.length() - 1)
      #|  let pivot = arr[arr.length() - 1]
      #|  let mut i = 0
      #|  let mut partitioned = true
      #|  for j in 0..<(arr.length() - 1) {
      #|    if cmp(arr[j], pivot) < 0 {
      #|      if i != j {
      #|        arr.swap(i, j)
      #|        partitioned = false
      #|      }
      #|      i = i + 1
      #|    }
      #|  }
      #|  arr.swap(i, arr.length() - 1)
      #|  (i, partitioned)
      #|}
      #|fn[T] choose_pivot_by(arr : ArrayView[T], cmp : (T, T) -> Int) -> (Int, Bool) {
      #|  let len = arr.length()
      #|  let use_median_of_medians = 50
      #|  let max_swaps = 4 * 3
      #|  let mut swaps = 0
      #|  let b = len / 4 * 2
      #|  if len >= 8 {
      #|    let a = len / 4 * 1
      #|    let c = len / 4 * 3
      #|    let sort_2 = (a : Int, b : Int) => if cmp(arr[a], arr[b]) > 0 {
      #|      arr.swap(a, b)
      #|      swaps += 1
      #|    }
      #|    let sort_3 = (a : Int, b : Int, c : Int) => {
      #|      sort_2(a, b)
      #|      sort_2(b, c)
      #|      sort_2(a, b)
      #|    }
      #|    if len > use_median_of_medians {
      #|      sort_3(a - 1, a, a + 1)
      #|      sort_3(b - 1, b, b + 1)
      #|      sort_3(c - 1, c, c + 1)
      #|    }
      #|    sort_3(a, b, c)
      #|  }
      #|  if swaps == max_swaps {
      #|    arr.rev_inplace()
      #|    (len - b - 1, true)
      #|  } else {
      #|    (b, swaps == 0)
      #|  }
      #|}
      #|fn[T] heap_sort_by(arr : ArrayView[T], cmp : (T, T) -> Int) -> Unit {
      #|  let len = arr.length()
      #|  for i = len / 2 - 1; i >= 0; i = i - 1 {
      #|    sift_down_by(arr, i, cmp)
      #|  }
      #|  for i = len - 1; i > 0; i = i - 1 {
      #|    arr.swap(0, i)
      #|    sift_down_by(arr[0:i], 0, cmp)
      #|  }
      #|}
      #|fn[T] sift_down_by(
      #|  arr : ArrayView[T],
      #|  index : Int,
      #|  cmp : (T, T) -> Int,
      #|) -> Unit {
      #|  let mut index = index
      #|  let len = arr.length()
      #|  let mut child = index * 2 + 1
      #|  while child < len {
      #|    if child + 1 < len && cmp(arr[child], arr[child + 1]) < 0 {
      #|      child = child + 1
      #|    }
      #|    if cmp(arr[index], arr[child]) >= 0 {
      #|      return
      #|    }
      #|    arr.swap(index, child)
      #|    index = child
      #|    child = index * 2 + 1
      #|  }
      #|}
      #|test "try_bubble_sort" {
      #|  let arr = [8, 7, 6, 5, 4, 3, 2, 1]
      #|  let sorted = try_bubble_sort_by(arr[0:8], (a, b) => a - b)
      #|  inspect(sorted, content="true")
      #|  assert_eq(arr, [1, 2, 3, 4, 5, 6, 7, 8])
      #|}
      #|test "heap_sort" {
      #|  test_sort(arr => heap_sort_by(arr[:], (a, b) => a - b))
      #|}
      #|test "bubble_sort" {
      #|  test_sort(arr => bubble_sort_by(arr[:], (a, b) => a - b))
      #|}
      #|test "sort_by_key" {
      #|  let arr = [5, 1, 3, 4, 2]
      #|  arr.sort_by_key(x => -x)
      #|  assert_eq(arr, [5, 4, 3, 2, 1])
      #|}
      #|test "sort_by" {
      #|  test_sort(arr => arr.sort_by((a, b) => a - b))
      #|}
    ),
    "utils.mbt": (
      #|fn minimum(x : Int, y : Int) -> Int {
      #|  if x > y {
      #|    y
      #|  } else {
      #|    x
      #|  }
      #|}
    ),
    "view.mbt": (
      #|pub typealias ArrayView as View
      #|pub fn[T] View::rev_inplace(self : View[T]) -> Unit {
      #|  let mid_len = self.length() / 2
      #|  for i in 0.. Unit raise?) -> Unit raise? {
      #|  for v in self {
      #|    f(v)
      #|  }
      #|}
      #|pub fn[T] View::eachi(
      #|  self : View[T],
      #|  f : (Int, T) -> Unit raise?,
      #|) -> Unit raise? {
      #|  for i, v in self {
      #|    f(i, v)
      #|  }
      #|}
      #|pub fn[T] View::all(self : View[T], f : (T) -> Bool raise?) -> Bool raise? {
      #|  for v in self {
      #|    if !f(v) {
      #|      return false
      #|    }
      #|  }
      #|  true
      #|}
      #|pub fn[T] View::any(self : View[T], f : (T) -> Bool raise?) -> Bool raise? {
      #|  for v in self {
      #|    if f(v) {
      #|      return true
      #|    }
      #|  }
      #|  false
      #|}
      #|pub fn[T : Eq] View::contains(self : View[T], value : T) -> Bool {
      #|  for v in self {
      #|    if v == value {
      #|      break true
      #|    }
      #|  } else {
      #|    false
      #|  }
      #|}
      #|pub fn[A] View::iter(self : View[A]) -> Iter[A] {
      #|  Iter::new(yield_ => for v in self {
      #|    guard yield_(v) is IterContinue else { break IterEnd }
      #|  } else {
      #|    IterContinue
      #|  })
      #|}
      #|pub fn[A] View::iter2(self : View[A]) -> Iter2[Int, A] {
      #|  Iter2::new(yield_ => for i, v in self {
      #|    guard yield_(i, v) is IterContinue else { break IterEnd }
      #|  } else {
      #|    IterContinue
      #|  })
      #|}
      #|pub fn[A, B] View::fold(
      #|  self : View[A],
      #|  init~ : B,
      #|  f : (B, A) -> B raise?,
      #|) -> B raise? {
      #|  for i = 0, acc = init; i < self.length(); {
      #|    continue i + 1, f(acc, self[i])
      #|  } else {
      #|    acc
      #|  }
      #|}
      #|pub fn[A, B] View::rev_fold(
      #|  self : View[A],
      #|  init~ : B,
      #|  f : (B, A) -> B raise?,
      #|) -> B raise? {
      #|  for i = self.length() - 1, acc = init; i >= 0; {
      #|    continue i - 1, f(acc, self[i])
      #|  } else {
      #|    acc
      #|  }
      #|}
      #|pub fn[A, B] View::foldi(
      #|  self : View[A],
      #|  init~ : B,
      #|  f : (Int, B, A) -> B raise?,
      #|) -> B raise? {
      #|  for i = 0, acc = init; i < self.length(); {
      #|    continue i + 1, f(i, acc, self[i])
      #|  } else {
      #|    acc
      #|  }
      #|}
      #|pub fn[A, B] View::rev_foldi(
      #|  self : View[A],
      #|  init~ : B,
      #|  f : (Int, B, A) -> B raise?,
      #|) -> B raise? {
      #|  let len = self.length()
      #|  for i = len - 1, acc = init; i >= 0; {
      #|    continue i - 1, f(len - i - 1, acc, self[i])
      #|  } else {
      #|    acc
      #|  }
      #|}
      #|pub fn[T, U] View::map(self : View[T], f : (T) -> U raise?) -> Array[U] raise? {
      #|  if self.length() == 0 {
      #|    return []
      #|  }
      #|  Array::makei(self.length(), i => f(self[i]))
      #|}
      #|pub fn[T] View::map_inplace(self : View[T], f : (T) -> T raise?) -> Unit raise? {
      #|  for i, v in self {
      #|    self[i] = f(v)
      #|  }
      #|}
      #|pub fn[T, U] View::mapi(
      #|  self : View[T],
      #|  f : (Int, T) -> U raise?,
      #|) -> Array[U] raise? {
      #|  if self.length() == 0 {
      #|    return []
      #|  }
      #|  Array::makei(self.length(), i => f(i, self[i]))
      #|}
      #|pub fn[T] View::mapi_inplace(
      #|  self : View[T],
      #|  f : (Int, T) -> T raise?,
      #|) -> Unit raise? {
      #|  for i, v in self {
      #|    self[i] = f(i, v)
      #|  }
      #|}
      #|pub fn[T] View::filter(
      #|  self : View[T],
      #|  f : (T) -> Bool raise?,
      #|) -> Array[T] raise? {
      #|  let arr = []
      #|  for v in self {
      #|    if f(v) {
      #|      arr.push(v)
      #|    }
      #|  }
      #|  arr
      #|}
      #|pub fn[T] View::to_array(self : View[T]) -> Array[T] {
      #|  let len = self.length()
      #|  if len == 0 {
      #|    []
      #|  } else {
      #|    let arr = Array::make(len, self[0])
      #|    for i, v in self {
      #|      arr[i] = v
      #|    }
      #|    arr
      #|  }
      #|}
      #|pub fn[A : @string.ToStringView] View::join(
      #|  self : ArrayView[A],
      #|  separator : @string.View,
      #|) -> String {
      #|  match self {
      #|    [] => ""
      #|    [hd, .. tl] => {
      #|      let hd = hd.to_string_view()
      #|      let mut size_hint = hd.length()
      #|      for s in tl {
      #|        size_hint += s.to_string_view().length() + separator.length()
      #|      }
      #|      size_hint = size_hint << 1
      #|      let buf = StringBuilder::new(size_hint~)
      #|      buf.write_substring(hd.data(), hd.start_offset(), hd.length())
      #|      if separator is "" {
      #|        for s in tl {
      #|          let s = s.to_string_view()
      #|          buf.write_substring(s.data(), s.start_offset(), s.length())
      #|        }
      #|      } else {
      #|        for s in tl {
      #|          let s = s.to_string_view()
      #|          buf.write_substring(
      #|            separator.data(),
      #|            separator.start_offset(),
      #|            separator.length(),
      #|          )
      #|          buf.write_substring(s.data(), s.start_offset(), s.length())
      #|        }
      #|      }
      #|      buf.to_string()
      #|    }
      #|  }
      #|}
      #|pub impl[X : Show] Show for View[X] with output(self, logger) {
      #|  logger.write_iter(self.iter())
      #|}
      #|pub impl[T : Eq] Eq for View[T] with op_equal(self, other) -> Bool {
      #|  if self.length() != other.length() {
      #|    return false
      #|  }
      #|  for i in 0.. Int {
      #|  let len_self = self.length()
      #|  let len_other = other.length()
      #|  let cmp = len_self.compare(len_other)
      #|  guard cmp == 0 else { return cmp }
      #|  for i in 0.. Unit, k : Int) -> Double {
      #|  let ts = monotonic_clock_start()
      #|  for i in 0.. Unit, count : UInt) -> Summary {
      #|  let count = count.land(0x7FFFFFFF).reinterpret_as_int()
      #|  let threshold = 100000.0 // 100 ms
      #|  let target_batch_size = loop 1 {
      #|    trial => {
      #|      let single_us = iter_n_microseconds(inner, trial) / trial.to_double()
      #|      let target_batch_size = threshold /
      #|        (if single_us < 1.0 { 1.0 } else { single_us })
      #|      if trial.to_double() * single_us > threshold {
      #|        break target_batch_size
      #|      }
      #|      continue trial * 2
      #|    }
      #|  }
      #|  let batch_size = if target_batch_size < 1.0 {
      #|    1
      #|  } else {
      #|    target_batch_size.ceil().to_int()
      #|  }
      #|  let samples = Array::makei(count, _ => iter_n_microseconds(inner, batch_size) /
      #|    batch_size.to_double())
      #|  samples.sort()
      #|  winsorize(sorted_data=samples, 5.0)
      #|  Summary::new(name?, sorted_data=samples, batch_size)
      #|}
      #|pub fn bench(
      #|  self : T,
      #|  name? : String,
      #|  f : () -> Unit,
      #|  count? : UInt = 10,
      #|) -> Unit {
      #|  let summary = iter_count(name?, f, count)
      #|  if !self.buffer.is_empty() {
      #|    self.buffer.write_char(',')
      #|  }
      #|  self.buffer.write_string(summary.to_json().stringify(escape_slash=true))
      #|  self.summaries.push(summary)
      #|}
      #|pub fn single_bench(
      #|  name? : String,
      #|  f : () -> Unit,
      #|  count? : UInt = 10,
      #|) -> Summary {
      #|  iter_count(name?, f, count)
      #|}
      #|pub fn[Any] keep(self : T, value : Any) -> Unit {
      #|  let trait_object : &OpaqueValue = value
      #|  self._storage = trait_object
      #|}
      #|#coverage.skip
      #|pub fn dump_summaries(self : T) -> String {
      #|  "[\{self.buffer.to_string()}]"
      #|}
      #|test "bench - single_bench basic functionality" {
      #|  let bench_result = single_bench(
      #|    () => {
      #|      let x = 1 + 1
      #|      ignore(x)
      #|    },
      #|    count=2,
      #|  )
      #|  inspect(bench_result.runs, content="2")
      #|  inspect(bench_result.batch_size > 0, content="true")
      #|  inspect(bench_result.sum > 0.0, content="true")
      #|  inspect(bench_result.min <= bench_result.max, content="true")
      #|}
      #|test "bench - Summary struct properties" {
      #|  let bench_result = single_bench(
      #|    () => {
      #|      let x = 1
      #|      ignore(x)
      #|    },
      #|    count=5,
      #|  )
      #|  inspect(bench_result.mean >= 0, content="true")
      #|  inspect(bench_result.median >= 0, content="true")
      #|  inspect(bench_result.std_dev >= 0, content="true")
      #|  inspect(bench_result.std_dev_pct >= 0, content="true")
      #|  inspect(bench_result.median_abs_dev >= 0, content="true")
      #|  inspect(bench_result.median_abs_dev_pct >= 0, content="true")
      #|  let (q1, q2, q3) = bench_result.quartiles
      #|  inspect(q1 <= q2, content="true")
      #|  inspect(q2 <= q3, content="true")
      #|  inspect((q3 - q1 - bench_result.iqr).abs() < 0.001, content="true")
      #|}
      #|test "bench - T struct and bench method" {
      #|  let bench_obj = new()
      #|  inspect(bench_obj.buffer.is_empty(), content="true")
      #|  inspect(bench_obj.summaries.is_empty(), content="true")
      #|  bench_obj.bench(
      #|    () => {
      #|      let x = 20 * 20
      #|      ignore(x)
      #|    },
      #|    count=2,
      #|  )
      #|  inspect(bench_obj.buffer.is_empty(), content="false")
      #|  inspect(bench_obj.summaries.length(), content="1")
      #|  bench_obj.bench(
      #|    () => {
      #|      let y = 30 * 30
      #|      ignore(y)
      #|    },
      #|    count=2,
      #|  )
      #|  inspect(bench_obj.summaries.length(), content="2")
      #|}
      #|test "bench - monotonic clock functionality" {
      #|  let start = monotonic_clock_start()
      #|  let mut result = 0
      #|  for _ in 0..<1000 {
      #|    result += 1
      #|  }
      #|  ignore(result)
      #|  let elapsed = monotonic_clock_end(start)
      #|  inspect(elapsed >= 0.0, content="true")
      #|}
      #|test "bench - keep stores value" {
      #|  let b = new()
      #|  assert_eq(b.summaries.length(), 0)
      #|  b.keep(123)
      #|  assert_eq(b.summaries.length(), 0)
      #|  b.keep(456)
      #|  assert_eq(b.summaries.length(), 0)
      #|}
    ),
    "monotonic_clock_js.mbt": (
      #|type Timestamp
      #|pub extern "js" fn monotonic_clock_start() -> Timestamp =
      #|  #| () => performance.now()
      #|pub extern "js" fn monotonic_clock_end(ts : Timestamp) -> Double =
      #|  #| (ts) => (performance.now() - ts) * 1000.0
    ),
    "monotonic_clock_native.mbt": (
      #|#external
      #|type Timestamp
      #|pub extern "C" fn monotonic_clock_start() -> Timestamp = "moonbit_monotonic_clock_start"
      #|pub extern "C" fn monotonic_clock_end(ts : Timestamp) -> Double = "moonbit_monotonic_clock_stop"
    ),
    "monotonic_clock_wasm.mbt": (
      #|#external
      #|type Timestamp
      #|fn instant_elapsed_as_secs_f64(x : Timestamp) -> Double = "__moonbit_time_unstable" "instant_elapsed_as_secs_f64"
      #|pub fn monotonic_clock_start() -> Timestamp = "__moonbit_time_unstable" "instant_now"
      #|pub fn monotonic_clock_end(ts : Timestamp) -> Double {
      #|  let elapsed_secs : Double = instant_elapsed_as_secs_f64(ts)
      #|  elapsed_secs * 1000000.0
      #|}
    ),
    "stats.mbt": (
      #|struct Summary {
      #|  name : String?
      #|  sum : Double
      #|  min : Double
      #|  max : Double
      #|  mean : Double
      #|  median : Double
      #|  variance : Double
      #|  std_dev : Double
      #|  std_dev_pct : Double
      #|  median_abs_dev : Double
      #|  median_abs_dev_pct : Double
      #|  quartiles : (Double, Double, Double)
      #|  iqr : Double
      #|  batch_size : Int
      #|  runs : Int
      #|} derive(ToJson)
      #|fn Summary::new(
      #|  name? : String,
      #|  sorted_data~ : Array[Double],
      #|  batch_size : Int,
      #|) -> Summary {
      #|  let sum = sum(sorted_data)
      #|  let min = min(sorted_data~)
      #|  let max = max(sorted_data~)
      #|  let mean = mean(sorted_data, sum~)
      #|  let median = median(sorted_data~)
      #|  let variance = variance(sorted_data, mean~)
      #|  let std_dev = std_dev(variance~)
      #|  let std_dev_pct = std_dev_pct(mean~, std_dev~)
      #|  let median_abs_dev = median_abs_dev(sorted_data, median_=median)
      #|  let median_abs_dev_pct = median_abs_dev_pct(median~, median_abs_dev~)
      #|  let quartiles = quartiles(sorted_data~)
      #|  let iqr = iqr(quartiles~)
      #|  {
      #|    name,
      #|    sum,
      #|    min,
      #|    max,
      #|    mean,
      #|    median,
      #|    variance,
      #|    std_dev,
      #|    std_dev_pct,
      #|    median_abs_dev,
      #|    median_abs_dev_pct,
      #|    quartiles,
      #|    iqr,
      #|    batch_size,
      #|    runs: sorted_data.length(),
      #|  }
      #|}
      #|fn sum(data : Array[Double]) -> Double {
      #|  let mut sum = 0.0
      #|  for i in data {
      #|    sum += i
      #|  }
      #|  sum
      #|}
      #|fn min(sorted_data~ : Array[Double]) -> Double {
      #|  sorted_data[0]
      #|}
      #|fn max(sorted_data~ : Array[Double]) -> Double {
      #|  sorted_data[sorted_data.length() - 1]
      #|}
      #|fn mean(data : Array[Double], sum~ : Double) -> Double {
      #|  let count = data.length()
      #|  sum / count.to_double()
      #|}
      #|fn median(sorted_data~ : Array[Double]) -> Double {
      #|  percentile(sorted_data~, pct=50.0)
      #|}
      #|fn variance(data : Array[Double], mean~ : Double) -> Double {
      #|  if data.length() < 2 {
      #|    return 0.0
      #|  }
      #|  let mut v = 0.0
      #|  for i in data {
      #|    let d = i - mean
      #|    v += d * d
      #|  }
      #|  v / (data.length() - 1).to_double()
      #|}
      #|fn std_dev(variance~ : Double) -> Double {
      #|  variance.sqrt()
      #|}
      #|fn std_dev_pct(mean~ : Double, std_dev~ : Double) -> Double {
      #|  if mean == 0.0 {
      #|    return 0.0
      #|  }
      #|  std_dev / mean * 100.0
      #|}
      #|fn median_abs_dev(data : Array[Double], median_~ : Double) -> Double {
      #|  let abs_devs = data.map(x => (median_ - x).abs())
      #|  abs_devs.sort()
      #|  median(sorted_data=abs_devs) * 1.4826
      #|}
      #|fn median_abs_dev_pct(median~ : Double, median_abs_dev~ : Double) -> Double {
      #|  if median == 0.0 {
      #|    return 0.0
      #|  }
      #|  median_abs_dev / median * 100.0
      #|}
      #|fn quartiles(sorted_data~ : Array[Double]) -> (Double, Double, Double) {
      #|  let q1 = percentile(sorted_data~, pct=25.0)
      #|  let q2 = percentile(sorted_data~, pct=50.0)
      #|  let q3 = percentile(sorted_data~, pct=75.0)
      #|  (q1, q2, q3)
      #|}
      #|fn iqr(quartiles~ : (Double, Double, Double)) -> Double {
      #|  let (q1, _, q3) = quartiles
      #|  q3 - q1
      #|}
      #|fn percentile(sorted_data~ : Array[Double], pct~ : Double) -> Double {
      #|  guard sorted_data.length() > 0
      #|  guard pct >= 0.0 && pct <= 100.0
      #|  if sorted_data.length() == 1 {
      #|    return sorted_data[0]
      #|  }
      #|  if pct == 100.0 {
      #|    return sorted_data[sorted_data.length() - 1]
      #|  }
      #|  let length = (sorted_data.length() - 1).to_double()
      #|  let rank = pct / 100 * length
      #|  let lrank = rank.floor()
      #|  let d = rank - lrank
      #|  let n = lrank.to_int()
      #|  let lo = sorted_data[n]
      #|  let hi = sorted_data[n + 1]
      #|  lo + (hi - lo) * d
      #|}
      #|fn winsorize(sorted_data~ : Array[Double], pct : Double) -> Unit {
      #|  let lo = percentile(sorted_data~, pct~)
      #|  let hi = percentile(sorted_data~, pct=100.0 - pct)
      #|  for i, samp in sorted_data {
      #|    if samp > hi {
      #|      sorted_data[i] = hi
      #|    } else if samp < lo {
      #|      sorted_data[i] = lo
      #|    }
      #|  }
      #|}
      #|test {
      #|  let data = [1.1, 21.4, 2.2, 3.3, 4.5, 12.5, 33.3, 14.4]
      #|  data.sort()
      #|  let summary = Summary::new(sorted_data=data, 3)
      #|  assert_true(summary.sum.is_close(92.7))
      #|  assert_true(summary.min.is_close(1.1))
      #|  assert_true(summary.max.is_close(33.3))
      #|  assert_true(summary.mean.is_close(11.5875))
      #|  assert_true(summary.median.is_close(8.5))
      #|  assert_true(summary.variance.is_close(127.64125))
      #|  assert_true(summary.std_dev.is_close(11.297842714430043))
      #|  assert_true(summary.std_dev_pct.is_close(97.50026075020534))
      #|  assert_true(summary.median_abs_dev.is_close(9.04386))
      #|  assert_true(summary.median_abs_dev_pct.is_close(106.39835294117646))
      #|  let (q1, q2, q3) = summary.quartiles
      #|  assert_true(q1.is_close(3.025))
      #|  assert_true(q2.is_close(8.5))
      #|  assert_true(q3.is_close(16.15))
      #|  assert_true(summary.iqr.is_close(13.125))
      #|  assert_true(summary.batch_size == 3)
      #|  assert_true(summary.runs == 8)
      #|  @json.inspect(summary, content={
      #|    "sum": 92.69999999999999,
      #|    "min": 1.1,
      #|    "max": 33.3,
      #|    "mean": 11.587499999999999,
      #|    "median": 8.5,
      #|    "variance": 127.64124999999999,
      #|    "std_dev": 11.297842714430042,
      #|    "std_dev_pct": 97.50026075020534,
      #|    "median_abs_dev": 9.043859999999999,
      #|    "median_abs_dev_pct": 106.39835294117646,
      #|    "quartiles": [3.025, 8.5, 16.15],
      #|    "iqr": 13.124999999999998,
      #|    "batch_size": 3,
      #|    "runs": 8,
      #|  })
      #|}
      #|test "std_dev_pct zero mean" {
      #|  assert_eq(std_dev_pct(mean=0.0, std_dev=5.0), 0.0)
      #|}
      #|test "median_abs_dev_pct zero median" {
      #|  assert_eq(median_abs_dev_pct(median=0.0, median_abs_dev=3.0), 0.0)
      #|}
      #|test "percentile edge cases" {
      #|  assert_eq(percentile(sorted_data=[42.0], pct=50.0), 42.0)
      #|  assert_eq(percentile(sorted_data=[1.0, 2.0, 3.0], pct=100.0), 3.0)
      #|}
    ),
    "types.mbt": (
      #|priv trait OpaqueValue {}
      #|struct T {
      #|  buffer : StringBuilder
      #|  summaries : Array[Summary]
      #|  mut _storage : &OpaqueValue
      #|}
      #|pub fn new() -> T {
      #|  let buffer = StringBuilder::new()
      #|  let summaries = Array::new()
      #|  { buffer, summaries, _storage: () }
      #|}
    ),
  },
)

///|
let moonbitlang_core_bigint_module : RuntimePackage = RuntimePackage::new(
  "moonbitlang/core/bigint",
  deps={
    "moonbitlang/core/builtin": moonbitlang_core_builtin_module,
    "moonbitlang/core/char": moonbitlang_core_char_module,
    "moonbitlang/core/uint": moonbitlang_core_uint_module,
    "moonbitlang/core/json": moonbitlang_core_json_module,
    "moonbitlang/core/quickcheck": moonbitlang_core_quickcheck_module,
    "moonbitlang/core/quickcheck/splitmix": moonbitlang_core_quickcheck_splitmix_module,
    "moonbitlang/core/string": moonbitlang_core_string_module,
  },
  files={
    "moon.pkg.json": (
      #|{
      #|  "import": [
      #|    "moonbitlang/core/builtin",
      #|    "moonbitlang/core/char",
      #|    "moonbitlang/core/uint",
      #|    "moonbitlang/core/json",
      #|    "moonbitlang/core/quickcheck",
      #|    "moonbitlang/core/quickcheck/splitmix",
      #|    "moonbitlang/core/string"
      #|  ],
      #|  "targets": {
      #|    "bigint_js.mbt": ["js"],
      #|    "bigint_nonjs.mbt": ["not", "js"],
      #|    "bigint_js_wbtest.mbt": ["js"],
      #|    "bigint_nonjs_wbtest.mbt": ["not", "js"]
      #|  },
      #|  "warn-list": "-29"
      #|}
    ),
    "bigint.mbt": (
      #|pub impl ToJson for BigInt with to_json(self : BigInt) -> Json {
      #|  Json::string(self.to_string())
      #|}
      #|pub impl @json.FromJson for BigInt with from_json(json, path) {
      #|  guard json is String(s) else {
      #|    raise @json.JsonDecodeError(
      #|      (path, "BigInt::from_json: expected number in string representation"),
      #|    )
      #|  }
      #|  BigInt::from_string(s)
      #|}
      #|pub impl @quickcheck.Arbitrary for BigInt with arbitrary(size, rs) {
      #|  if size == 0 {
      #|    0
      #|  } else {
      #|    rs.next_int64() |> BigInt::from_int64
      #|  }
      #|}
      #|pub impl Default for BigInt with default() {
      #|  zero
      #|}
      #|pub fn BigInt::equal_int(self : BigInt, other : Int) -> Bool {
      #|  can_convert_to_int(self) && self.to_int() == other
      #|}
      #|pub fn BigInt::equal_int64(self : BigInt, other : Int64) -> Bool {
      #|  can_convert_to_int64(self) && self.to_int64() == other
      #|}
      #|pub fn BigInt::compare_int(self : BigInt, other : Int) -> Int {
      #|  guard can_convert_to_int(self) else {
      #|    return if is_neg(self) { -1 } else { 1 }
      #|  }
      #|  let self = self.to_int()
      #|  Int::compare(self, other)
      #|}
      #|pub fn BigInt::compare_int64(self : BigInt, other : Int64) -> Int {
      #|  guard can_convert_to_int64(self) else {
      #|    return if is_neg(self) { -1 } else { 1 }
      #|  }
      #|  let self = self.to_int64()
      #|  Int64::compare(self, other)
      #|}
      #|test "can_convert_to_int" {
      #|  assert_true(can_convert_to_int(0N))
      #|  assert_true(can_convert_to_int(1N))
      #|  assert_true(can_convert_to_int(-1N))
      #|  assert_true(can_convert_to_int(2147483647N)) // Int.max_value
      #|  assert_true(can_convert_to_int(-2147483648N)) // Int.min_value
      #|  assert_false(can_convert_to_int(2147483648N)) // Int.max_value + 1
      #|  assert_false(can_convert_to_int(-2147483649N)) // Int.min_value - 1
      #|  assert_false(can_convert_to_int(4294967295N)) // 2^32 - 1
      #|  assert_false(can_convert_to_int(-4294967295N)) // -(2^32 - 1)
      #|  assert_false(can_convert_to_int(4294967296N)) // 2^32
      #|  assert_false(can_convert_to_int(-4294967296N)) // -2^32
      #|}
      #|test "can_convert_to_int64" {
      #|  assert_true(can_convert_to_int64(0N))
      #|  assert_true(can_convert_to_int64(1N))
      #|  assert_true(can_convert_to_int64(-1N))
      #|  assert_true(can_convert_to_int64(2147483647N)) // Int.max_value
      #|  assert_true(can_convert_to_int64(-2147483648N)) // Int.min_value
      #|  assert_true(can_convert_to_int64(2147483648N)) // Int.max_value + 1
      #|  assert_true(can_convert_to_int64(-2147483649N)) // Int.min_value - 1
      #|  assert_true(can_convert_to_int64(4294967295N)) // 2^32 - 1
      #|  assert_true(can_convert_to_int64(-4294967295N)) // -(2^32 - 1)
      #|  assert_true(can_convert_to_int64(4294967296N)) // 2^32
      #|  assert_true(can_convert_to_int64(-4294967296N)) // -2^32
      #|  assert_true(can_convert_to_int64(9223372036854775807N)) // Int64.max_value
      #|  assert_true(can_convert_to_int64(-9223372036854775808N)) // Int64.min_value
      #|  assert_false(can_convert_to_int64(9223372036854775808N)) // Int64.max_value + 1
      #|  assert_false(can_convert_to_int64(-9223372036854775809N)) // Int64.min_value - 1
      #|  assert_false(can_convert_to_int64(18446744073709551615N)) // 2^64 - 1
      #|  assert_false(can_convert_to_int64(-18446744073709551615N)) // -(2^64 - 1)
      #|  assert_false(can_convert_to_int64(18446744073709551616N)) // 2^64
      #|  assert_false(can_convert_to_int64(-18446744073709551616N)) // -2^64
      #|}
      #|pub impl Hash for BigInt with hash_combine(self, hasher) {
      #|  hasher.combine(self.signum())
      #|  for limb in self.limbs() {
      #|    hasher.combine(limb)
      #|  }
      #|}
      #|fn BigInt::signum(self : Self) -> Int {
      #|  if self.is_zero() {
      #|    0
      #|  } else if is_neg(self) {
      #|    -1
      #|  } else {
      #|    1
      #|  }
      #|}
      #|pub fn BigInt::to_uint16(self : BigInt) -> UInt16 {
      #|  self.to_int().to_uint16()
      #|}
      #|pub fn BigInt::to_int16(self : BigInt) -> Int16 {
      #|  self.to_int().to_int16()
      #|}
    ),
    "bigint_js.mbt": (
      #|type BigInt
      #|let zero = 0N
      #|pub fn BigInt::from_string(str : String) -> BigInt {
      #|  if str.length() == 0 {
      #|    abort("empty string")
      #|  }
      #|  BigInt::js_from_string(str)
      #|}
      #|extern "js" fn BigInt::js_from_string(str : String) -> BigInt =
      #|  #|(x) => BigInt(x)
      #|pub impl Show for BigInt with output(self, logger) {
      #|  logger.write_string(self.to_string())
      #|}
      #|pub extern "js" fn BigInt::to_string(self : BigInt) -> String =
      #|  #|(x) => String(x)
      #|pub extern "js" fn BigInt::from_hex(str : String) -> BigInt =
      #|  #|(x) => x.startsWith('-') ? -BigInt(`0x${x.slice(1)}`) : BigInt(`0x${x}`)
      #|pub extern "js" fn BigInt::to_hex(
      #|  self : BigInt,
      #|  uppercase? : Bool = true,
      #|) -> String =
      #|  #|(x, uppercase) => {
      #|  #|  const r = x.toString(16);
      #|  #|  return uppercase ? r.toUpperCase() : r;
      #|  #|}
      #|extern "js" fn hex2(b : Byte) -> String =
      #|  #|(x) => x.toString(16).padStart(2, '0')
      #|pub fn BigInt::from_octets(octets : Bytes, signum? : Int = 1) -> BigInt {
      #|  if signum < 0 {
      #|    return -1N * BigInt::from_octets(octets, signum=1)
      #|  }
      #|  if signum == 0 {
      #|    return 0N
      #|  }
      #|  let str = StringBuilder::new()
      #|  str.write_string("0x")
      #|  for octet in octets {
      #|    str.write_string(hex2(octet))
      #|  }
      #|  BigInt::from_string(str.to_string())
      #|}
      #|pub fn BigInt::to_octets(self : BigInt, length? : Int) -> Bytes {
      #|  if self < 0 {
      #|    abort("negative BigInt")
      #|  }
      #|  if self == 0 {
      #|    return match length {
      #|      Some(len) => Bytes::make(len, 0)
      #|      None => [0]
      #|    }
      #|  }
      #|  let buf = []
      #|  loop self {
      #|    v =>
      #|      if v > 0 {
      #|        buf.push(v.to_byte())
      #|        continue v >> 8
      #|      }
      #|  }
      #|  let buf_len = buf.length()
      #|  match length {
      #|    Some(len) => {
      #|      if len <= 0 {
      #|        abort("negative length")
      #|      }
      #|      if len > buf_len {
      #|        Bytes::makei(len, i => {
      #|          let padding = len - buf_len
      #|          if i < padding {
      #|            0
      #|          } else {
      #|            buf[buf_len - (i - padding) - 1]
      #|          }
      #|        })
      #|      } else {
      #|        Bytes::makei(buf_len, i => buf[buf_len - i - 1])
      #|      }
      #|    }
      #|    None => Bytes::makei(buf_len, i => buf[buf_len - i - 1])
      #|  }
      #|}
      #|extern "js" fn BigInt::compare(self : BigInt, other : BigInt) -> Int =
      #|  #|(x, y) => x < y ? -1 : x > y ? 1 : 0
      #|pub impl Compare for BigInt with compare(self, other) {
      #|  self.compare(other)
      #|}
      #|extern "js" fn BigInt::equal(self : BigInt, other : BigInt) -> Bool =
      #|  #|(x, y) => x === y
      #|pub impl Eq for BigInt with op_equal(self, other) {
      #|  self.equal(other)
      #|}
      #|pub extern "js" fn BigInt::from_int(x : Int) -> BigInt =
      #|  #|(x) => BigInt(x)
      #|pub extern "js" fn BigInt::from_uint(x : UInt) -> BigInt =
      #|  #|(x) => BigInt(x >>> 0)
      #|pub extern "js" fn BigInt::from_int64(x : Int64) -> BigInt =
      #|  #|(x) => BigInt(x.hi) * 0x100000000n + BigInt(x.lo >>> 0)
      #|pub extern "js" fn BigInt::from_uint64(x : UInt64) -> BigInt =
      #|  #|(x) => BigInt(x.hi >>> 0) * 0x100000000n + BigInt(x.lo >>> 0)
      #|pub extern "js" fn BigInt::is_zero(self : BigInt) -> Bool =
      #|  #|(x) => x === 0n
      #|extern "js" fn BigInt::op_neg_ffi(self : BigInt) -> BigInt =
      #|  #|(x) => -x
      #|pub impl Neg for BigInt with op_neg(self) {
      #|  self.op_neg_ffi()
      #|}
      #|extern "js" fn BigInt::op_add_ffi(self : BigInt, other : BigInt) -> BigInt =
      #|  #|(x, y) => x + y
      #|pub impl Add for BigInt with op_add(self, other) {
      #|  self.op_add_ffi(other)
      #|}
      #|extern "js" fn BigInt::op_sub_ffi(self : BigInt, other : BigInt) -> BigInt =
      #|  #|(x, y) => x - y
      #|pub impl Sub for BigInt with op_sub(self, other) {
      #|  self.op_sub_ffi(other)
      #|}
      #|extern "js" fn BigInt::op_mul_ffi(self : BigInt, other : BigInt) -> BigInt =
      #|  #|(x, y) => x * y
      #|pub impl Mul for BigInt with op_mul(self, other) {
      #|  self.op_mul_ffi(other)
      #|}
      #|extern "js" fn BigInt::op_div_ffi(self : BigInt, other : BigInt) -> BigInt =
      #|  #|(x, y) => x / y
      #|pub impl Div for BigInt with op_div(self, other) {
      #|  self.op_div_ffi(other)
      #|}
      #|extern "js" fn BigInt::op_mod_ffi(self : BigInt, other : BigInt) -> BigInt =
      #|  #|(x, y) => x % y
      #|pub impl Mod for BigInt with op_mod(self, other) {
      #|  self.op_mod_ffi(other)
      #|}
      #|extern "js" fn BigInt::modpow_ffi(
      #|  self : BigInt,
      #|  exponent : BigInt,
      #|  modulus : BigInt,
      #|) -> BigInt =
      #|  #|(x, y, z) => {
      #|  #|  if (z === 1n) return 0n;
      #|  #|  let result = 1n;
      #|  #|  x = x % z;
      #|  #|  while (y > 0n) {
      #|  #|    if (y & 1n) {
      #|  #|       result = (result * x) % z;
      #|  #|    }
      #|  #|    y >>= 1n;
      #|  #|    x = (x * x) % z;
      #|  #|  }
      #|  #|  return result;
      #|  #|}
      #|extern "js" fn BigInt::pow_ffi(self : BigInt, exponent : BigInt) -> BigInt =
      #|  #|(x, y) => x ** y
      #|pub fn BigInt::pow(
      #|  self : BigInt,
      #|  exponent : BigInt,
      #|  modulus? : BigInt,
      #|) -> BigInt {
      #|  if exponent < 0 {
      #|    abort("negative exponent")
      #|  }
      #|  match modulus {
      #|    Some(modulus) =>
      #|      if modulus <= 0 {
      #|        abort("non-positive modulus")
      #|      } else {
      #|        self.modpow_ffi(exponent, modulus)
      #|      }
      #|    None => self.pow_ffi(exponent)
      #|  }
      #|}
      #|extern "js" fn BigInt::to_byte(self : BigInt) -> Byte =
      #|  #|(x) => Number(BigInt.asUintN(8, x)) | 0
      #|pub impl Shl for BigInt with op_shl(self : BigInt, n : Int) -> BigInt {
      #|  if n < 0 {
      #|    abort("negative shift count")
      #|  }
      #|  self.js_shl(n)
      #|}
      #|pub impl Shr for BigInt with op_shr(self : BigInt, n : Int) -> BigInt {
      #|  if n < 0 {
      #|    abort("negative shift count")
      #|  }
      #|  self.js_shr(n)
      #|}
      #|extern "js" fn BigInt::js_shl(self : BigInt, other : Int) -> BigInt =
      #|  #|(x, y) => x << BigInt(y)
      #|extern "js" fn BigInt::js_shr(self : BigInt, other : Int) -> BigInt =
      #|  #|(x, y) => x >> BigInt(y)
      #|extern "js" fn BigInt::js_land(self : BigInt, other : BigInt) -> BigInt =
      #|  #|(x, y) => x & y
      #|pub impl BitAnd for BigInt with land(self, other) {
      #|  self.js_land(other)
      #|}
      #|extern "js" fn BigInt::js_lor(self : BigInt, other : BigInt) -> BigInt =
      #|  #|(x, y) => x | y
      #|pub impl BitOr for BigInt with lor(self, other) {
      #|  self.js_lor(other)
      #|}
      #|extern "js" fn BigInt::js_lxor(self : BigInt, other : BigInt) -> BigInt =
      #|  #|(x, y) => x ^ y
      #|pub impl BitXOr for BigInt with lxor(self, other) {
      #|  self.js_lxor(other)
      #|}
      #|pub extern "js" fn BigInt::to_uint(self : BigInt) -> UInt =
      #|  #|(x) => Number(BigInt.asUintN(32, x)) | 0
      #|pub extern "js" fn BigInt::to_int(self : BigInt) -> Int =
      #|  #|(x) => Number(BigInt.asIntN(32, x))
      #|pub fn BigInt::to_uint64(self : BigInt) -> UInt64 {
      #|  let hi = (self >> 32).to_uint()
      #|  let lo = self.to_uint()
      #|  (hi.to_uint64() << 32) | lo.to_uint64()
      #|}
      #|pub fn BigInt::to_int64(self : BigInt) -> Int64 {
      #|  let hi = (self >> 32).to_uint()
      #|  let lo = self.to_uint()
      #|  (hi.to_int64() << 32) | lo.to_int64()
      #|}
      #|pub extern "js" fn BigInt::bit_length(self : BigInt) -> Int =
      #|  #|(n) => {
      #|  #|  if (n >= 0) {
      #|  #|    return n === 0n ? 0 : n.toString(2).length;
      #|  #|  } else {
      #|  #|    const absN = -n;
      #|  #|    const absMinus1 = absN - 1n;
      #|  #|    return absMinus1 === 0n ? 0 : absMinus1.toString(2).length;
      #|  #|  }
      #|  #|}
      #|pub extern "js" fn BigInt::ctz(self : BigInt) -> Int =
      #|  #|(n) => {
      #|  #|  if (n === 0n) return 0;
      #|  #|  let absN = n < 0n ? -n : n;
      #|  #|  let count = 0;
      #|  #|  while ((absN & 1n) === 0n) {
      #|  #|    absN >>= 1n;
      #|  #|    count++;
      #|  #|  }
      #|  #|  return count;
      #|  #|}
      #|extern "js" fn can_convert_to_int(x : BigInt) -> Bool =
      #|  #|(x) => x >= -(2n ** 31n) && x < 2n ** 31n
      #|extern "js" fn can_convert_to_int64(x : BigInt) -> Bool =
      #|  #|(x) => x >= -(2n ** 63n) && x < 2n ** 63n
      #|extern "js" fn is_neg(x : BigInt) -> Bool =
      #|  #|(x) => x < 0n
      #|fn BigInt::limbs(self : Self) -> Iter[UInt] {
      #|  guard !self.is_zero() else { Iter::singleton(0) }
      #|  Iter::new(yield_ => for n = self * BigInt::from_int(self.signum())
      #|                          n > 0
      #|                          n = n >> 32 {
      #|    let limb = n.to_uint()
      #|    guard yield_(limb) is IterContinue else { break IterEnd }
      #|  } else {
      #|    IterContinue
      #|  })
      #|}
    ),
    "bigint_nonjs.mbt": (
      #|struct BigInt {
      #|  limbs : FixedArray[UInt] // Note: do not use limbs.length(), use len instead because of leading zeros
      #|  sign : Sign
      #|  len : Int
      #|}
      #|priv enum Sign {
      #|  Positive
      #|  Negative
      #|} derive(Eq)
      #|let radix_bit_len = 32
      #|let radix : UInt64 = 1UL << radix_bit_len // TODO: This can be generalized once we have const generics
      #|let radix_mask : UInt64 = radix - 1
      #|let decimal_ratio = 0.302 // log10(2)
      #|let karatsuba_threshold = 50
      #|let zero : BigInt = 0N
      #|let one : BigInt = 1N
      #|pub fn BigInt::from_int(n : Int) -> BigInt {
      #|  BigInt::from_int64(n.to_int64())
      #|}
      #|pub fn BigInt::from_uint(n : UInt) -> BigInt {
      #|  BigInt::from_uint64(n.to_uint64())
      #|}
      #|pub fn BigInt::from_int64(n : Int64) -> BigInt {
      #|  if n < 0L {
      #|    -BigInt::from_uint64((-n).reinterpret_as_uint64())
      #|  } else {
      #|    BigInt::from_uint64(n.reinterpret_as_uint64())
      #|  }
      #|}
      #|pub fn BigInt::from_uint64(n : UInt64) -> BigInt {
      #|  if n == 0UL {
      #|    return { limbs: FixedArray::make(1, 0), sign: Positive, len: 1 }
      #|  }
      #|  let limbs = FixedArray::make(64 / radix_bit_len, 0U)
      #|  let mut m = n
      #|  let mut i = 0
      #|  while m > 0 {
      #|    limbs[i] = (m % radix).to_uint()
      #|    m /= radix
      #|    i += 1
      #|  }
      #|  { limbs, sign: Positive, len: i }
      #|}
      #|pub impl Neg for BigInt with op_neg(self : BigInt) -> BigInt {
      #|  if self.is_zero() {
      #|    return zero
      #|  }
      #|  { ..self, sign: if self.sign == Positive { Negative } else { Positive } }
      #|}
      #|pub impl Add for BigInt with op_add(self : BigInt, other : BigInt) -> BigInt {
      #|  if self.sign == Negative {
      #|    if other.sign == Negative {
      #|      return -(-other + -self)
      #|    } else {
      #|      return other - -self
      #|    }
      #|  } else if other.sign == Negative {
      #|    return self - -other
      #|  }
      #|  let self_len = self.len
      #|  let other_len = other.len
      #|  let limbs = FixedArray::make(1 + max(self_len, other_len), 0U)
      #|  let mut carry = 0UL
      #|  let mut i = 0
      #|  while i < self_len || i < other_len || carry != 0 {
      #|    let a = if i < self_len { self.limbs[i].to_uint64() } else { 0 }
      #|    let b = if i < other_len { other.limbs[i].to_uint64() } else { 0 }
      #|    let sum = a + b + carry
      #|    limbs[i] = (sum % radix).to_uint()
      #|    carry = sum / radix
      #|    i += 1
      #|  }
      #|  { limbs, sign: Positive, len: i }
      #|}
      #|pub impl Sub for BigInt with op_sub(self : BigInt, other : BigInt) -> BigInt {
      #|  if self.sign == Negative {
      #|    if other.sign == Negative {
      #|      return -other - -self
      #|    } else {
      #|      return -(other + -self)
      #|    }
      #|  } else if other.sign == Negative {
      #|    return self + -other
      #|  }
      #|  if self < other {
      #|    return -(other - self)
      #|  }
      #|  let self_len = self.len
      #|  let other_len = other.len
      #|  let limbs = FixedArray::make(max(self_len, other_len), 0U)
      #|  let mut borrow = 0L
      #|  let mut i = 0
      #|  while i < self_len || i < other_len || borrow != 0L {
      #|    let a = if i < self_len { self.limbs[i].to_int64() } else { 0 }
      #|    let b = if i < other_len { other.limbs[i].to_int64() } else { 0 }
      #|    let diff = a - b - borrow // 0 <= a < radix, 0 <= b < radix, 0 <= borrow <= 1 => -radix <= diff < radix
      #|    if diff < 0L {
      #|      limbs[i] = (diff + radix.reinterpret_as_int64())
      #|        .reinterpret_as_uint64()
      #|        .to_uint() // -radix <= diff < 0, so we don't need to mod by radix
      #|      borrow = 1L
      #|    } else {
      #|      limbs[i] = diff.reinterpret_as_uint64().to_uint() // 0 <= diff < radix, so we don't need to mod by radix
      #|      borrow = 0L
      #|    }
      #|    i += 1
      #|  }
      #|  while i > 1 && limbs[i - 1] == 0 {
      #|    i -= 1
      #|  }
      #|  { limbs, sign: Positive, len: i }
      #|}
      #|pub impl Mul for BigInt with op_mul(self : BigInt, other : BigInt) -> BigInt {
      #|  if self.is_zero() || other.is_zero() {
      #|    return zero
      #|  }
      #|  let ret = if self.len < karatsuba_threshold || other.len < karatsuba_threshold {
      #|    self.grade_school_mul(other)
      #|  } else {
      #|    self.karatsuba_mul(other)
      #|  }
      #|  { ..ret, sign: if self.sign == other.sign { Positive } else { Negative } }
      #|}
      #|fn BigInt::grade_school_mul(self : BigInt, other : BigInt) -> BigInt {
      #|  let self_len = self.len
      #|  let other_len = other.len
      #|  let mut len = self_len + other_len
      #|  let limbs = FixedArray::make(len, 0U)
      #|  for i in 0.. BigInt {
      #|  let half = (max(self.len, other.len) + 1) / 2
      #|  let (xl, xh) = self.split(half)
      #|  let (yl, yh) = other.split(half)
      #|  let p1 = xh * yh
      #|  let p2 = xl * yl
      #|  let p3 = (xh + xl) * (yh + yl)
      #|  (p1 << (radix_bit_len * 2 * half)) +
      #|  ((p3 - p1 - p2) << (radix_bit_len * half)) +
      #|  p2
      #|}
      #|fn BigInt::split(self : BigInt, half : Int) -> (BigInt, BigInt) {
      #|  if self.len <= half {
      #|    return ({ ..self, sign: Positive }, zero)
      #|  }
      #|  let lower_len = for i = half - 1; i > 0; i = i - 1 {
      #|    if self.limbs[i] > 0 {
      #|      break i + 1
      #|    }
      #|  } else {
      #|    1
      #|  }
      #|  let lower = FixedArray::make(lower_len, 0U)
      #|  lower.unsafe_blit(0, self.limbs, 0, lower_len)
      #|  let upper = FixedArray::make(self.len - half, 0U)
      #|  upper.unsafe_blit(0, self.limbs, half, self.len - half)
      #|  (
      #|    { limbs: lower, sign: Positive, len: lower_len },
      #|    { limbs: upper, sign: Positive, len: self.len - half },
      #|  )
      #|}
      #|pub impl Div for BigInt with op_div(self : BigInt, other : BigInt) -> BigInt {
      #|  if other is 0 {
      #|    abort("division by zero")
      #|  }
      #|  if self.sign == Negative {
      #|    if other.sign == Negative {
      #|      BigInt::grade_school_div(-self, -other).0
      #|    } else {
      #|      -BigInt::grade_school_div(-self, other).0
      #|    }
      #|  } else if other.sign == Negative {
      #|    -BigInt::grade_school_div(self, -other).0
      #|  } else {
      #|    return BigInt::grade_school_div(self, other).0
      #|  }
      #|}
      #|pub impl Mod for BigInt with op_mod(self : BigInt, other : BigInt) -> BigInt {
      #|  if other == zero {
      #|    abort("division by zero")
      #|  }
      #|  if self.sign == Negative {
      #|    if other.sign == Negative {
      #|      -BigInt::grade_school_div(-self, -other).1
      #|    } else {
      #|      -BigInt::grade_school_div(-self, other).1
      #|    }
      #|  } else if other.sign == Negative {
      #|    BigInt::grade_school_div(self, -other).1
      #|  } else {
      #|    BigInt::grade_school_div(self, other).1
      #|  }
      #|}
      #|fn BigInt::grade_school_div(self : BigInt, other : BigInt) -> (BigInt, BigInt) {
      #|  if self < other {
      #|    return (zero, self)
      #|  } else if self == other {
      #|    return (one, zero)
      #|  }
      #|  if other.len == 1 {
      #|    let number = other.limbs[0]
      #|    let ret = self.copy()
      #|    if number == 1 {
      #|      return (ret, zero)
      #|    }
      #|    let a = ret.limbs
      #|    let x = number.to_uint64()
      #|    let mut y = 0UL
      #|    for i = self.len - 1; i >= 0; i = i - 1 {
      #|      y = y << radix_bit_len
      #|      y += a[i].to_uint64()
      #|      a[i] = ((y / x) & radix_mask).to_uint()
      #|      y %= x
      #|    }
      #|    if ret.limbs[ret.len - 1] == 0 {
      #|      return (
      #|        { ..ret, len: ret.len - 1 },
      #|        { limbs: FixedArray::make(1, y.to_uint()), sign: Positive, len: 1 },
      #|      )
      #|    }
      #|    return (
      #|      ret,
      #|      { limbs: FixedArray::make(1, y.to_uint()), sign: Positive, len: 1 },
      #|    )
      #|  }
      #|  let dividend = self
      #|  let divisor = other
      #|  let lshift = max(
      #|    0,
      #|    radix_bit_len - (64 - divisor.limbs[divisor.len - 1].to_int64().clz()),
      #|  )
      #|  let a_len = dividend.len
      #|  let dividend = dividend << lshift
      #|  let divisor = divisor << lshift
      #|  let b_len = divisor.len
      #|  let b = FixedArray::make(b_len, 0UL)
      #|  for i in 0.. i {
      #|      a[i] = dividend.limbs[i].to_uint64()
      #|    }
      #|  }
      #|  let a_len = a_len + 1
      #|  let v1 = b[b_len - 1]
      #|  let v2 = b[b_len - 2]
      #|  let q = FixedArray::make(a_len - b_len, 0U)
      #|  for i = q.length() - 1; i >= 0; i = i - 1 {
      #|    let u0 = a[i + b_len]
      #|    let u1 = a[i + b_len - 1]
      #|    let u2 = a[i + b_len - 2]
      #|    let mut qh = (u0 * radix + u1) / v1
      #|    if qh * v2 > radix * (u0 * radix + u1 - qh * v1) + u2 {
      #|      qh -= 1
      #|    }
      #|    let mut borrow = 0L
      #|    let mut carry = 0UL
      #|    for j in 0..> radix_bit_len
      #|      carry = carry >> radix_bit_len
      #|    }
      #|    borrow = borrow + a[i + b_len].reinterpret_as_int64()
      #|    borrow -= carry.reinterpret_as_int64()
      #|    a[i + b_len] = (borrow & radix_mask.reinterpret_as_int64()).reinterpret_as_uint64()
      #|    borrow = borrow >> radix_bit_len
      #|    if borrow < 0L {
      #|      carry = 0UL
      #|      for j in 0..> radix_bit_len
      #|      }
      #|      carry += a[i + b_len]
      #|      a[i + b_len] = carry & radix_mask
      #|      carry = carry >> radix_bit_len
      #|      borrow += carry.reinterpret_as_int64()
      #|      qh -= 1
      #|    }
      #|    q[i] = qh.to_uint()
      #|  }
      #|  let len = if q[q.length() - 1] == 0 { q.length() - 1 } else { q.length() }
      #|  let mut i = a.length() - 1
      #|  while i >= 0 && a[i] == 0 {
      #|    i -= 1
      #|  }
      #|  if i < 0 {
      #|    i = 1
      #|  } else {
      #|    i += 1
      #|  }
      #|  let modulo = FixedArray::make(i, 0U)
      #|  for j in 0..> lshift)
      #|}
      #|pub impl Shl for BigInt with op_shl(self : BigInt, n : Int) -> BigInt {
      #|  if n < 0 {
      #|    abort("negative shift count")
      #|  }
      #|  if !self.is_zero() {
      #|    let new_limbs = FixedArray::make(
      #|      self.len + (n + radix_bit_len - 1) / radix_bit_len, // ceiling(n / radix_bit_len)
      #|      0U,
      #|    )
      #|    let a = self.limbs
      #|    let r = n % radix_bit_len
      #|    let lz = n / radix_bit_len // number of leading zeros
      #|    let mut len = self.len + lz
      #|    if r != 0 {
      #|      let mut carry = 0UL
      #|      for i in 0..> radix_bit_len
      #|      }
      #|      if carry != 0 {
      #|        new_limbs[self.len + lz] = carry.to_uint()
      #|        len += 1
      #|      }
      #|    } else {
      #|      new_limbs.unsafe_blit(lz, self.limbs, 0, self.len)
      #|    }
      #|    { limbs: new_limbs, sign: self.sign, len }
      #|  } else {
      #|    zero
      #|  }
      #|}
      #|pub impl Shr for BigInt with op_shr(self : BigInt, n : Int) -> BigInt {
      #|  if n < 0 {
      #|    abort("negative shift count")
      #|  }
      #|  let r = n % radix_bit_len
      #|  let lz = n / radix_bit_len
      #|  if lz >= self.len {
      #|    match self.sign {
      #|      Positive => return zero
      #|      Negative =>
      #|        return { limbs: FixedArray::make(1, 1), sign: Negative, len: 1 }
      #|    }
      #|  }
      #|  let mut new_len = self.len - lz
      #|  if r == 0 {
      #|    let new_limbs = FixedArray::make(new_len, 0U)
      #|    new_limbs.unsafe_blit(0, self.limbs, lz, new_len)
      #|    { limbs: new_limbs, sign: self.sign, len: new_len }
      #|  } else {
      #|    let new_limbs = FixedArray::make(new_len, 0U)
      #|    let a = self.limbs
      #|    let mut carry = 0UL
      #|    for i = self.len - 1; i >= lz; i = i - 1 {
      #|      let x = a[i].to_uint64()
      #|      new_limbs[i - lz] = ((x >> r) | carry).to_uint()
      #|      carry = (x << (radix_bit_len - r)) % radix
      #|    }
      #|    if new_len > 1 && new_limbs[new_len - 1] == 0 {
      #|      new_len -= 1
      #|    }
      #|    if self.sign == Negative && (carry & (1UL << r)) != carry {
      #|      { limbs: new_limbs, sign: self.sign, len: new_len } - 1
      #|    } else {
      #|      { limbs: new_limbs, sign: self.sign, len: new_len }
      #|    }
      #|  }
      #|}
      #|pub fn BigInt::is_zero(self : BigInt) -> Bool {
      #|  self.len == 1 && self.limbs[0] == 0
      #|}
      #|pub impl Compare for BigInt with compare(self, other) {
      #|  if self.sign != other.sign {
      #|    return if self.sign == Positive { 1 } else { -1 }
      #|  }
      #|  let self_len = self.len
      #|  let other_len = other.len
      #|  if self_len != other_len {
      #|    return if self.sign == Positive {
      #|      self_len - other_len
      #|    } else {
      #|      other_len - self_len
      #|    }
      #|  }
      #|  for i = self_len - 1; i >= 0; i = i - 1 {
      #|    if self.limbs[i] != other.limbs[i] {
      #|      return if self.sign == Positive {
      #|        self.limbs[i].compare(other.limbs[i])
      #|      } else {
      #|        other.limbs[i].compare(self.limbs[i])
      #|      }
      #|    }
      #|  }
      #|  0
      #|}
      #|pub impl Eq for BigInt with op_equal(self, other) {
      #|  if self.sign != other.sign || self.len != other.len {
      #|    return false
      #|  }
      #|  for i in 0.. String {
      #|  if self.is_zero() {
      #|    return "0"
      #|  }
      #|  let decimal_radix_bit_len = 19 - 1 - (1 + radix_bit_len) / 3 // < len(9,223,372,036,854,775,807) - len(2^radix_bit_len). len means the number of digits in decimal.
      #|  let decimal_mask = 10_000_000L // 10^(decimal_radix_bit_len). TODO: compute it when we have power function.
      #|  let decimal_len = unchecked_double_to_int(
      #|    (self.len * radix_bit_len).to_double() *
      #|    decimal_ratio /
      #|    decimal_radix_bit_len.to_double() +
      #|    1,
      #|  )
      #|  let s = if self.sign == Negative { "-" } else { "" }
      #|  let v = Array::make(decimal_len, 0L)
      #|  let mut v_idx = 0
      #|  for i = self.len - 1; i >= 0; i = i - 1 {
      #|    let mut x = self.limbs[i].to_int64()
      #|    for j in 0.. 0L {
      #|      v[v_idx] = x % decimal_mask
      #|      v_idx += 1
      #|      x /= decimal_mask
      #|    }
      #|  }
      #|  let mut ret = ""
      #|  for i in 0..<(v_idx - 1) {
      #|    for j in 0.. 0L {
      #|    let y = x % 10L
      #|    x /= 10L
      #|    ret = y.to_string() + ret
      #|  }
      #|  s + ret
      #|}
      #|pub impl Show for BigInt with output(self, logger) {
      #|  logger.write_string(self.to_string())
      #|}
      #|pub fn BigInt::from_string(input : String) -> BigInt {
      #|  let len = input.length()
      #|  if len == 0 {
      #|    abort("empty string")
      #|  }
      #|  let sign : Sign = if input.unsafe_charcode_at(0) == '-' {
      #|    Negative
      #|  } else {
      #|    Positive
      #|  }
      #|  let mut b_len = (
      #|      unchecked_double_to_int(len.to_double() / decimal_ratio) +
      #|      1 +
      #|      radix_bit_len
      #|    ) /
      #|    radix_bit_len +
      #|    1
      #|  let b = FixedArray::make(b_len, 0U)
      #|  for
      #|    i in (match sign {
      #|      Negative => 1
      #|      Positive => 0
      #|    }).. 9 {
      #|      abort("invalid character")
      #|    }
      #|    let mut carry = x.reinterpret_as_uint().to_uint64()
      #|    for j in 0.. 1 {
      #|    b_len -= 1
      #|  }
      #|  { limbs: b, sign, len: b_len }
      #|}
      #|pub fn BigInt::from_hex(input : String) -> BigInt {
      #|  fn char_from_hex(x : Int) -> UInt {
      #|    (match x {
      #|      '0'..='9' => x - '0'
      #|      'A'..='F' => x + (10 - 'A')
      #|      'a'..='f' => x + (10 - 'a')
      #|      _ => abort("invalid character")
      #|    }).reinterpret_as_uint()
      #|  }
      #|  let len = input.length()
      #|  if len == 0 {
      #|    abort("empty string")
      #|  }
      #|  let (sign, number_len) = if input.unsafe_charcode_at(0) == '-' {
      #|    (Negative, len - 1)
      #|  } else {
      #|    (Positive, len)
      #|  }
      #|  let nb_char = radix_bit_len / 4 // number of char per limb
      #|  let quotient = number_len / nb_char
      #|  let mod = number_len % nb_char
      #|  let mut b_len = if mod == 0 { quotient } else { quotient + 1 }
      #|  let b = FixedArray::make(b_len, 0U)
      #|  if mod != 0 {
      #|    let start = len - quotient * nb_char - mod
      #|    for i in 0.. 1 {
      #|    b_len -= 1
      #|  }
      #|  { limbs: b, sign, len: b_len }
      #|}
      #|pub fn BigInt::to_hex(self : BigInt, uppercase? : Bool = true) -> String {
      #|  if self.is_zero() {
      #|    return "0"
      #|  }
      #|  let digits_per_limb = radix_bit_len / 4
      #|  let buf = if self.sign is Negative {
      #|    let builder = StringBuilder::new(size_hint=self.len * digits_per_limb + 2)
      #|    builder.write_char('-')
      #|    builder
      #|  } else {
      #|    StringBuilder::new(size_hint=self.len * digits_per_limb)
      #|  }
      #|  for i = self.len - 1; i >= 0; i = i - 1 { // TODO: reverse iteration would be a bit faster.
      #|    let mut x = self.limbs[i]
      #|    let digits = FixedArray::make(digits_per_limb, '0')
      #|    let mut idx = 0
      #|    while x > 0 {
      #|      let y = x % 16
      #|      x /= 16
      #|      digits[idx] = if y < 10 {
      #|        (y.reinterpret_as_int() + '0'.to_int()).unsafe_to_char()
      #|      } else if uppercase {
      #|        (y.reinterpret_as_int() - 10 + 'A'.to_int()).unsafe_to_char()
      #|      } else {
      #|        (y.reinterpret_as_int() - 10 + 'a'.to_int()).unsafe_to_char()
      #|      }
      #|      idx += 1
      #|    }
      #|    if i != self.len - 1 {
      #|      idx = digits_per_limb
      #|    }
      #|    for j in 0.. BigInt {
      #|  let new_limbs = FixedArray::make(self.len, 0U)
      #|  new_limbs.unsafe_blit(0, self.limbs, 0, self.len)
      #|  { limbs: new_limbs, sign: self.sign, len: self.len }
      #|}
      #|fn[T : Compare] max(a : T, b : T) -> T {
      #|  if a > b {
      #|    a
      #|  } else {
      #|    b
      #|  }
      #|}
      #|pub fn BigInt::pow(self : BigInt, exp : BigInt, modulus? : BigInt) -> BigInt {
      #|  if exp.sign == Negative {
      #|    abort("negative exponent")
      #|  }
      #|  match modulus {
      #|    None => {
      #|      let mut result = 1N
      #|      let mut base = self
      #|      let mut exp = exp
      #|      while exp > 0 {
      #|        if exp % 2 == 1 {
      #|          result = result * base
      #|        }
      #|        base = base * base
      #|        exp = exp / 2
      #|      }
      #|      result
      #|    }
      #|    Some(modulus) => {
      #|      guard !(modulus.is_zero() || modulus.sign == Negative)
      #|      let mut result = 1N
      #|      let mut base = self
      #|      let mut exp = exp
      #|      while exp > 0 {
      #|        if exp % 2 == 1 {
      #|          result = result * base % modulus
      #|        }
      #|        base = base * base % modulus
      #|        exp = exp / 2
      #|      }
      #|      result
      #|    }
      #|  }
      #|}
      #|pub fn BigInt::from_octets(input : Bytes, signum? : Int = 1) -> BigInt {
      #|  let len = input.length() // number of bytes
      #|  if signum == 0 {
      #|    return zero
      #|  } else if signum < 0 {
      #|    return -BigInt::from_octets(input)
      #|  }
      #|  if len == 0 {
      #|    abort("empty octet string")
      #|  }
      #|  let div = len * 8 / radix_bit_len
      #|  let mod = len * 8 % radix_bit_len // number of bits in the first limb
      #|  let limbs_len = if mod == 0 { div } else { div + 1 }
      #|  let limbs = FixedArray::make(limbs_len, 0U)
      #|  for i in 0..<(mod / 8) {
      #|    limbs[limbs_len - 1] = (limbs[limbs_len - 1] << 8) | input[i].to_uint()
      #|  }
      #|  let byte_per_limb = radix_bit_len / 8
      #|  for i in 0..
Bytes { #| let length = match length { #| None => 1 #| Some(l) => if l <= 0 { abort("negative length") } else { l } #| } #| if self.is_zero() { #| return Bytes::new(max(1, length)) #| } #| if self.sign == Negative { #| abort("negative BigInt") #| } #| let head_bits = 32 - self.limbs[self.len - 1].reinterpret_as_int().clz() #| let tail_len = self.len - 1 #| let len = (head_bits + 7) / 8 + tail_len * (radix_bit_len / 8) #| let len = max(length, len) #| let result = FixedArray::make(len, Byte::default()) #| for i = 0; i < len && i / 4 < self.len; i = i + 1 { #| result[len - 1 - i] = ((self.limbs[i / 4] >> (i % 4 * 8)) & 0xffU) #| .reinterpret_as_int() #| .to_byte() #| } #| unsafe_fixedarray_to_bytes(result) #|} #|pub impl BitAnd for BigInt with land(self : BigInt, other : BigInt) -> BigInt { #| let max_length = if self.limbs.length() < other.limbs.length() { #| other.limbs.length() + 1 #| } else { #| self.limbs.length() + 1 #| } #| let x_limbs = FixedArray::make(max_length, 0U) #| x_limbs..unsafe_blit(0, self.limbs, 0, self.limbs.length()) #| let y_limbs = FixedArray::make(max_length, 0U) #| y_limbs..unsafe_blit(0, other.limbs, 0, other.limbs.length()) #| if self.sign == Negative { #| for i in 0.. other.len { #| self.len #| } else { #| other.len #| }, #| } #|} #|pub impl BitOr for BigInt with lor(self : BigInt, other : BigInt) -> BigInt { #| let max_length = if self.limbs.length() < other.limbs.length() { #| other.limbs.length() + 1 #| } else { #| self.limbs.length() + 1 #| } #| let x_limbs = FixedArray::make(max_length, 0U) #| x_limbs.unsafe_blit(0, self.limbs, 0, self.limbs.length()) #| let y_limbs = FixedArray::make(max_length, 0U) #| y_limbs.unsafe_blit(0, other.limbs, 0, other.limbs.length()) #| if self.sign == Negative { #| for i in 0.. other.len { #| self.len #| } else { #| other.len #| }, #| } #|} #|pub impl BitXOr for BigInt with lxor(self : BigInt, other : BigInt) -> BigInt { #| let max_length = if self.limbs.length() < other.limbs.length() { #| other.limbs.length() + 1 #| } else { #| self.limbs.length() + 1 #| } #| let x_limbs = FixedArray::make(max_length, 0U) #| x_limbs..unsafe_blit(0, self.limbs, 0, self.limbs.length()) #| let y_limbs = FixedArray::make(max_length, 0U) #| y_limbs..unsafe_blit(0, other.limbs, 0, other.limbs.length()) #| if self.sign == Negative { #| for i in 0.. other.len { #| self.len #| } else { #| other.len #| }, #| } #|} #|pub fn BigInt::to_int(self : BigInt) -> Int { #| self.to_uint().reinterpret_as_int() #|} #|pub fn BigInt::to_uint(self : BigInt) -> UInt { #| let value = if self.sign == Negative { (1N << 32) + self } else { self } #| value.limbs[0] #|} #|pub fn BigInt::to_int64(self : BigInt) -> Int64 { #| self.to_uint64().reinterpret_as_int64() #|} #|pub fn BigInt::to_uint64(self : BigInt) -> UInt64 { #| let value = if self.sign == Negative { (1N << 64) + self } else { self } #| let len = 64 / radix_bit_len #| let len = if value.len < len { value.len } else { len } #| let mut result = 0UL #| for i = len - 1; i >= 0; i = i - 1 { #| result = result << radix_bit_len #| result = result | (value.limbs[i].to_uint64() & radix_mask) #| } #| result #|} #|pub fn BigInt::bit_length(self : BigInt) -> Int { #| if self.len == 0 { #| return 0 #| } #| let mut bit_length = (self.len - 1) * radix_bit_len + #| (radix_bit_len - self.limbs[self.len - 1].clz()) #| if self.sign == Negative { #| let mut pow2 = self.limbs[0].popcnt() == 1 #| for i = 1; i < self.len && pow2; i = i + 1 { #| pow2 = self.limbs[i] == 0 #| } #| if pow2 { #| bit_length -= 1 #| } #| } #| bit_length #|} #|pub fn BigInt::ctz(self : BigInt) -> Int { #| if self.is_zero() { #| return 0 #| } #| let mut i = 0 #| while i < self.len && self.limbs[i] == 0 { #| i = i + 1 #| } #| radix_bit_len * i + self.limbs[i].ctz() #|} #|fn unchecked_double_to_int(d : Double) -> Int = "%f64_to_i32" #|fn unsafe_fixedarray_to_bytes(arr : FixedArray[Byte]) -> Bytes = "%identity" #|fn can_convert_to_int(x : BigInt) -> Bool { #| x.len == 1 && #| (if x.sign == Negative { #| x.limbs[0] <= 0x80000000 #| } else { #| x.limbs[0] < 0x80000000 #| }) #|} #|fn can_convert_to_int64(x : BigInt) -> Bool { #| x.len <= 2 && #| (if x.sign == Negative { #| x.limbs[1] < 0x80000000 || (x.limbs[1] == 0x80000000 && x.limbs[0] == 0) #| } else { #| x.limbs[1] < 0x80000000 #| }) #|} #|fn is_neg(x : BigInt) -> Bool { #| x.sign == Negative #|} #|test "limb length" { #| inspect(0N.len, content="1") #| inspect(1N.len, content="1") #| inspect((-1N).len, content="1") #| inspect(2147483647N.len, content="1") // Int.max_value #| inspect((-2147483648N).len, content="1") // Int.min_value #| inspect(2147483648N.len, content="1") // Int.max_value + 1 #| inspect((-2147483649N).len, content="1") // Int.min_value - 1 #| inspect(4294967295N.len, content="1") // 2^32 - 1 #| inspect((-4294967295N).len, content="1") // -(2^32 - 1) #| inspect(4294967296N.len, content="2") // 2^32 #| inspect((-4294967296N).len, content="2") // -2^32 #|} #|fn BigInt::limbs(self : Self) -> Iter[UInt] { #| self.limbs.iter().take(self.len) #|} ), "deprecated.mbt": ( #|#deprecated("Use infix bitwise operator `>>` instead") #|#coverage.skip #|pub fn BigInt::asr(self : BigInt, n : Int) -> BigInt { #| self >> n #|} #|#deprecated("Use infix bitwise operator `<<` instead") #|#coverage.skip #|pub fn BigInt::shl(self : BigInt, n : Int) -> BigInt { #| self << n #|} #|#deprecated("Use infix bitwise operator `<<` instead") #|#coverage.skip #|pub fn BigInt::lsl(self : BigInt, n : Int) -> BigInt { #| self << n #|} #|#deprecated("Use infix bitwise operator `>>` instead") #|#coverage.skip #|pub fn BigInt::shr(self : BigInt, n : Int) -> BigInt { #| self >> n #|} ), }, ) ///| let moonbitlang_core_bool_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/bool", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module }, files={ "moon.pkg.json": ( #|{ #| "import": ["moonbitlang/core/builtin"], #| "test-import": [ "moonbitlang/core/char" ] #|} ), "bool.mbt": ( #|pub fn to_int(self : Bool) -> Int { #| if self { #| 1 #| } else { #| 0 #| } #|} #|pub fn to_int64(self : Bool) -> Int64 { #| if self { #| 1 #| } else { #| 0 #| } #|} #|pub fn to_uint(self : Bool) -> UInt { #| if self { #| 1 #| } else { #| 0 #| } #|} #|pub fn to_uint64(self : Bool) -> UInt64 { #| if self { #| 1 #| } else { #| 0 #| } #|} #|pub impl Hash for Bool with hash(self) { #| self.to_int() #|} #|pub impl Hash for Bool with hash_combine(self, hasher) { #| hasher.combine_bool(self) #|} #|pub fn to_uint16(self : Bool) -> UInt16 { #| if self { #| 1 #| } else { #| 0 #| } #|} #|pub fn to_int16(self : Bool) -> Int16 { #| if self { #| 1 #| } else { #| 0 #| } #|} ), }, ) ///| let moonbitlang_core_buffer_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/buffer", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/bytes": moonbitlang_core_bytes_module, "moonbitlang/core/array": moonbitlang_core_array_module, "moonbitlang/core/string": moonbitlang_core_string_module, }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/builtin", #| "moonbitlang/core/bytes", #| "moonbitlang/core/array", #| "moonbitlang/core/string" #| ] #|} ), "buffer.mbt": ( #|struct T { #| mut data : FixedArray[Byte] #| mut len : Int #| initial_data : FixedArray[Byte] #|} #|fn grow_if_necessary(self : T, required : Int) -> Unit { #| let start = if self.data.length() <= 0 { 1 } else { self.data.length() } #| let enough_space = for space = start { #| if space >= required { #| break space #| } #| continue space * 2 #| } #| if enough_space != self.data.length() { #| let new_data = FixedArray::make(enough_space, Byte::default()) #| new_data.unsafe_blit(0, self.data, 0, self.len) #| self.data = new_data #| } #|} #|pub fn length(self : T) -> Int { #| self.len #|} #|pub fn is_empty(self : T) -> Bool { #| self.len == 0 #|} #|pub fn contents(self : T) -> Bytes { #| @bytes.from_fixedarray(self.data, len=self.len) #|} #|pub fn new(size_hint? : Int = 0) -> T { #| let initial = if size_hint < 1 { 1 } else { size_hint } #| let data = FixedArray::make(initial, Byte::default()) #| { data, len: 0, initial_data: data } #|} #|pub fn from_bytes(bytes : Bytes) -> T { #| let val_len = bytes.length() #| let buf = new(size_hint=val_len) #| buf.data.blit_from_bytes(0, bytes, 0, val_len) #| buf.len = val_len #| buf #|} #|pub fn from_array(arr : Array[Byte]) -> T { #| let buf = new(size_hint=arr.length()) #| for byte in arr { #| buf.data[buf.len] = byte #| buf.len += 1 #| } #| buf #|} #|pub fn from_iter(iter : Iter[Byte]) -> T { #| let buf = new() #| let mut capacity = buf.data.length() #| for byte in iter { #| if buf.len == capacity { #| buf.grow_if_necessary(capacity + 1) #| capacity = buf.data.length() #| } #| buf.data[buf.len] = byte #| buf.len += 1 #| } #| buf #|} #|pub impl Logger for T with write_string(self, value) { #| self.grow_if_necessary(self.len + value.length() * 2) #| self.data.blit_from_string(self.len, value, 0, value.length()) #| self.len += value.length() * 2 #|} #|pub fn write_uint64_be(self : T, value : UInt64) -> Unit { #| self.write_byte((value >> 56).to_byte()) #| self.write_byte((value >> 48).to_byte()) #| self.write_byte((value >> 40).to_byte()) #| self.write_byte((value >> 32).to_byte()) #| self.write_byte((value >> 24).to_byte()) #| self.write_byte((value >> 16).to_byte()) #| self.write_byte((value >> 8).to_byte()) #| self.write_byte(value.to_byte()) #|} #|pub fn write_uint64_le(self : T, value : UInt64) -> Unit { #| self.write_byte(value.to_byte()) #| self.write_byte((value >> 8).to_byte()) #| self.write_byte((value >> 16).to_byte()) #| self.write_byte((value >> 24).to_byte()) #| self.write_byte((value >> 32).to_byte()) #| self.write_byte((value >> 40).to_byte()) #| self.write_byte((value >> 48).to_byte()) #| self.write_byte((value >> 56).to_byte()) #|} #|pub fn write_int64_be(self : T, value : Int64) -> Unit { #| self.write_uint64_be(value.reinterpret_as_uint64()) #|} #|pub fn write_int64_le(self : T, value : Int64) -> Unit { #| self.write_uint64_le(value.reinterpret_as_uint64()) #|} #|pub fn write_uint_be(self : T, value : UInt) -> Unit { #| self.write_byte((value >> 24).to_byte()) #| self.write_byte((value >> 16).to_byte()) #| self.write_byte((value >> 8).to_byte()) #| self.write_byte(value.to_byte()) #|} #|pub fn write_uint_le(self : T, value : UInt) -> Unit { #| self.write_byte(value.to_byte()) #| self.write_byte((value >> 8).to_byte()) #| self.write_byte((value >> 16).to_byte()) #| self.write_byte((value >> 24).to_byte()) #|} #|pub fn write_int_be(self : T, value : Int) -> Unit { #| self.write_uint_be(value.reinterpret_as_uint()) #|} #|pub fn write_int_le(self : T, value : Int) -> Unit { #| self.write_uint_le(value.reinterpret_as_uint()) #|} #|pub fn write_double_be(self : T, value : Double) -> Unit { #| self.write_uint64_be(value.reinterpret_as_uint64()) #|} #|pub fn write_double_le(self : T, value : Double) -> Unit { #| self.write_uint64_le(value.reinterpret_as_uint64()) #|} #|pub fn write_float_be(self : T, value : Float) -> Unit { #| self.write_uint_be(value.reinterpret_as_uint()) #|} #|pub fn write_float_le(self : T, value : Float) -> Unit { #| self.write_uint_le(value.reinterpret_as_uint()) #|} #|pub fn write_object(self : T, value : &Show) -> Unit { #| self.write_string(value.to_string()) #|} #|pub fn write_bytes(self : T, value : Bytes) -> Unit { #| let val_len = value.length() #| self.grow_if_necessary(self.len + val_len) #| self.data.blit_from_bytes(self.len, value, 0, val_len) #| self.len += val_len #|} #|pub fn write_bytesview(self : T, value : @bytes.View) -> Unit { #| let val_len = value.length() #| self.grow_if_necessary(self.len + val_len) #| self.data.blit_from_bytes( #| self.len, #| value.data(), #| value.start_offset(), #| value.length(), #| ) #| self.len += val_len #|} #|pub impl Logger for T with write_substring( #| self : T, #| value : String, #| start : Int, #| len : Int, #|) -> Unit { #| guard start >= 0 && len >= 0 && start + len <= value.length() #| self.grow_if_necessary(self.len + len * 2) #| self.data.blit_from_string(self.len, value, start, len) #| self.len += len * 2 #|} #|pub fn write_stringview(self : T, value : @string.View) -> Unit { #| let len = value.length() #| self.grow_if_necessary(self.len + len * 2) #| for i = 0, j = self.len; i < len; i = i + 1, j = j + 2 { #| let c = value.unsafe_charcode_at(i).reinterpret_as_uint() #| self.data[j] = (c & 0xff).to_byte() #| self.data[j + 1] = (c >> 8).to_byte() #| } #| self.len += len * 2 #|} #|pub impl Logger for T with write_char(self : T, value : Char) -> Unit { #| self.grow_if_necessary(self.len + 4) #| let inc = self.data.set_utf16le_char(self.len, value) #| self.len += inc #|} #|pub fn write_byte(self : T, value : Byte) -> Unit { #| self.grow_if_necessary(self.len + 1) #| self.data[self.len] = value #| self.len += 1 #|} #|pub fn write_iter(self : T, iter : Iter[Byte]) -> Unit { #| for byte in iter { #| self.write_byte(byte) #| } #|} #|pub fn reset(self : T) -> Unit { #| self.data = self.initial_data #| self.len = 0 #|} #|pub fn to_bytes(self : T) -> Bytes { #| @bytes.from_fixedarray(self.data, len=self.len) #|} #|pub impl Show for T with output(self, logger) { #| logger.write_string(self.contents().to_unchecked_string()) #|} ), "deprecated.mbt": ( #|#deprecated("Use type `T` instead") #|pub typealias T as Buffer ), }, ) ///| let moonbitlang_core_builtin_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/builtin", deps={ "moonbitlang/core/abort": moonbitlang_core_abort_module }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/abort" #| ], #| "test-import": [ #| "moonbitlang/core/char", #| "moonbitlang/core/string", #| "moonbitlang/core/bytes", #| "moonbitlang/core/int", #| "moonbitlang/core/double", #| "moonbitlang/core/uint64", #| "moonbitlang/core/array", #| "moonbitlang/core/int64", #| "moonbitlang/core/uint", #| "moonbitlang/core/json", #| "moonbitlang/core/bigint" #| ], #| "targets": { #| "int64_js.mbt": ["js"], #| "int64_nonjs.mbt": ["not", "js"], #| "arraycore_js.mbt": ["js"], #| "arraycore_nonjs.mbt": ["not", "js"], #| "panic_test.mbt": ["not", "native", "llvm"], #| "panic_wbtest.mbt": ["not", "native", "llvm"], #| "panic_nonjs_test.mbt": ["wasm", "wasm-gc"], #| "array_nonjs_test.mbt": ["not", "js"], #| "stringbuilder_buffer.mbt": ["not", "js"], #| "stringbuilder_concat.mbt": ["js"], #| "double_to_int64_js.mbt": ["js"], #| "double_to_int64_native.mbt": ["native", "llvm"], #| "double_to_int64_wasm.mbt": ["wasm", "wasm-gc"], #| "double_to_int.mbt": ["not", "wasm", "wasm-gc"], #| "double_to_int_wasm.mbt": ["wasm", "wasm-gc"] #| } #|} ), "array.mbt": ( #|pub fn[T] Array::from_fixed_array(arr : FixedArray[T]) -> Array[T] { #| let len = arr.length() #| let arr2 = Array::make_uninit(len) #| UninitializedArray::unsafe_blit_fixed(arr2.buffer(), 0, arr, 0, len) #| arr2 #|} #|pub fn[T] Array::make(len : Int, elem : T) -> Array[T] { #| let arr = Array::make_uninit(len) #| for i in 0.. Int { #| self.buffer().0.length() #|} #|#intrinsic("%array.unsafe_get") #|pub fn[T] Array::unsafe_get(self : Array[T], idx : Int) -> T { #| self.buffer()[idx] #|} #|#intrinsic("%array.get") #|pub fn[T] Array::op_get(self : Array[T], index : Int) -> T { #| let len = self.length() #| guard index >= 0 && index < len #| self.buffer()[index] #|} #|pub fn[T] Array::get(self : Array[T], index : Int) -> T? { #| let len = self.length() #| guard index >= 0 && index < len else { None } #| Some(self.unsafe_get(index)) #|} #|#intrinsic("%array.unsafe_set") #|fn[T] Array::unsafe_set(self : Array[T], idx : Int, val : T) -> Unit { #| self.buffer()[idx] = val #|} #|#intrinsic("%array.set") #|pub fn[T] Array::op_set(self : Array[T], index : Int, value : T) -> Unit { #| let len = self.length() #| guard index >= 0 && index < len #| self.buffer()[index] = value #|} #|pub impl[T : Eq] Eq for Array[T] with op_equal(self, other) { #| let self_len = self.length() #| let other_len = other.length() #| guard self_len == other_len else { return false } #| for i in 0.. Unit { #| other.blit_to( #| self, #| len=other.length(), #| src_offset=0, #| dst_offset=self.length(), #| ) #|} #|#locals(f) #|pub fn[T] Array::each(self : Array[T], f : (T) -> Unit raise?) -> Unit raise? { #| for v in self { #| f(v) #| } #|} #|#locals(f) #|pub fn[T] Array::rev_each(self : Array[T], f : (T) -> Unit) -> Unit { #| let len = self.length() #| for i in 0.. Unit raise?, #|) -> Unit raise? { #| let len = self.length() #| for i in 0.. Unit raise?, #|) -> Unit raise? { #| for i, v in self { #| f(i, v) #| } #|} #|pub fn[T] Array::clear(self : Array[T]) -> Unit { #| self.unsafe_truncate_to_length(0) #|} #|#locals(f) #|pub fn[T, U] Array::map( #| self : Array[T], #| f : (T) -> U raise?, #|) -> Array[U] raise? { #| let arr = Array::make_uninit(self.length()) #| for i, v in self { #| arr.unsafe_set(i, f(v)) #| } #| arr #|} #|#locals(f) #|pub fn[T] Array::map_inplace( #| self : Array[T], #| f : (T) -> T raise?, #|) -> Unit raise? { #| for i, v in self { #| self[i] = f(v) #| } #|} #|#locals(f) #|pub fn[T, U] Array::mapi( #| self : Array[T], #| f : (Int, T) -> U raise?, #|) -> Array[U] raise? { #| if self.length() == 0 { #| return [] #| } #| let arr = Array::make_uninit(self.length()) #| for i, v in self { #| arr.unsafe_set(i, f(i, v)) #| } #| arr #|} #|#locals(f) #|pub fn[T] Array::mapi_inplace( #| self : Array[T], #| f : (Int, T) -> T raise?, #|) -> Unit raise? { #| for i, v in self { #| self[i] = f(i, v) #| } #|} #|#locals(f) #|pub fn[T] Array::filter( #| self : Array[T], #| f : (T) -> Bool raise?, #|) -> Array[T] raise? { #| let arr = [] #| for v in self { #| if f(v) { #| arr.push(v) #| } #| } #| arr #|} #|pub fn[T] Array::is_empty(self : Array[T]) -> Bool { #| self.length() == 0 #|} #|pub fn[T : Compare] Array::is_sorted(self : Array[T]) -> Bool { #| for i = 1 { #| if i >= self.length() { #| break true #| } #| if self[i - 1] > self[i] { #| break false #| } #| continue i + 1 #| } #|} #|pub fn[T] Array::rev_inplace(self : Array[T]) -> Unit { #| let len = self.length() #| for i in 0..<(len / 2) { #| let temp = self.unsafe_get(i) #| self.unsafe_set(i, self.unsafe_get(len - i - 1)) #| self.unsafe_set(len - i - 1, temp) #| } #|} #|pub fn[T] Array::rev(self : Array[T]) -> Array[T] { #| let len = self.length() #| let arr = Array::make_uninit(len) #| for i in 0.. (Array[T], Array[T]) { #| if index < 0 || index > self.length() { #| let len = self.length() #| abort( #| "index out of bounds: the len is from 0 to \{len} but the index is \{index}", #| ) #| } #| let v1 = Array::make_uninit(index) #| let v2 = Array::make_uninit(self.length() - index) #| UninitializedArray::unsafe_blit(v1.buffer(), 0, self.buffer(), 0, index) #| if index != self.length() { #| UninitializedArray::unsafe_blit( #| v2.buffer(), #| 0, #| self.buffer(), #| index, #| self.length() - index, #| ) #| } #| (v1, v2) #|} #|pub fn[T : Eq] Array::contains(self : Array[T], value : T) -> Bool { #| for v in self { #| if v == value { #| break true #| } #| } else { #| false #| } #|} #|pub fn[T : Eq] Array::starts_with(self : Array[T], prefix : Array[T]) -> Bool { #| if prefix.length() > self.length() { #| return false #| } #| for i in 0.. Bool { #| if suffix.length() > self.length() { #| return false #| } #| for i in 0.. Array[T]? { #| if self.starts_with(prefix) { #| let v = Array::make_uninit(self.length() - prefix.length()) #| UninitializedArray::unsafe_blit( #| v.buffer(), #| 0, #| self.buffer(), #| prefix.length(), #| self.length() - prefix.length(), #| ) #| Some(v) #| } else { #| None #| } #|} #|pub fn[T : Eq] Array::strip_suffix( #| self : Array[T], #| suffix : Array[T], #|) -> Array[T]? { #| if self.ends_with(suffix) { #| let v = Array::make_uninit(self.length() - suffix.length()) #| let len = self.length() - suffix.length() #| UninitializedArray::unsafe_blit(v.buffer(), 0, self.buffer(), 0, len) #| Some(v) #| } else { #| None #| } #|} #|pub fn[T : Eq] Array::search(self : Array[T], value : T) -> Int? { #| for i, v in self { #| if v == value { #| break Some(i) #| } #| } else { #| None #| } #|} #|#locals(f) #|pub fn[T] Array::search_by(self : Array[T], f : (T) -> Bool) -> Int? { #| for i, v in self { #| if f(v) { #| break Some(i) #| } #| } else { #| None #| } #|} #|pub fn[T : Compare] Array::binary_search( #| self : Array[T], #| value : T, #|) -> Result[Int, Int] { #| let len = self.length() #| for i = 0, j = len; i < j; { #| let h = i + (j - i) / 2 #| if self.unsafe_get(h) < value { #| continue h + 1, j #| } else { #| continue i, h #| } #| } else { #| if i < len && self.unsafe_get(i) == value { #| Ok(i) #| } else { #| Err(i) #| } #| } #|} #|#locals(cmp) #|pub fn[T] Array::binary_search_by( #| self : Array[T], #| cmp : (T) -> Int, #|) -> Result[Int, Int] { #| let len = self.length() #| for i = 0, j = len; i < j; { #| let h = i + (j - i) / 2 #| if cmp(self.unsafe_get(h)) < 0 { #| continue h + 1, j #| } else { #| continue i, h #| } #| } else { #| if i < len && cmp(self.unsafe_get(i)) == 0 { #| Ok(i) #| } else { #| Err(i) #| } #| } #|} #|pub fn[T] Array::swap(self : Array[T], i : Int, j : Int) -> Unit { #| if i >= self.length() || j >= self.length() || i < 0 || j < 0 { #| let len = self.length() #| abort( #| "index out of bounds: the len is from 0 to \{len} but the index is (\{i}, \{j})", #| ) #| } #| let temp = self.unsafe_get(i) #| self.unsafe_set(i, self.unsafe_get(j)) #| self.unsafe_set(j, temp) #|} #|#locals(f) #|pub fn[T] Array::retain(self : Array[T], f : (T) -> Bool raise?) -> Unit raise? { #| let len = self.length() #| for i = 0, j = 0; i < len; { #| let item = self.unsafe_get(i) #| if f(item) { #| self.unsafe_set(j, item) #| continue i + 1, j + 1 #| } #| continue i + 1, j #| } else { #| self.unsafe_truncate_to_length(j) #| } #|} #|pub fn[T] Array::resize(self : Array[T], new_len : Int, f : T) -> Unit { #| if new_len < 0 { #| abort("negative new length") #| } #| if new_len < self.length() { #| self.unsafe_truncate_to_length(new_len) #| } else { #| let len = self.length() #| for _ in len.. Array[T] { #| let mut len = 0 #| for x in self { #| len += x.length() #| } #| let res = Array::make_uninit(len) #| let mut i = 0 #| for xs in self { #| res.unsafe_blit(i, xs, 0, xs.length()) #| i += xs.length() #| } #| res #|} #|pub fn[T] Array::repeat(self : Array[T], times : Int) -> Array[T] { #| let v = Array::new(capacity=self.length() * times) #| for i in 0.. B raise?, #|) -> B raise? { #| for i = 0, acc = init; i < self.length(); { #| continue i + 1, f(acc, self[i]) #| } else { #| acc #| } #|} #|#locals(f) #|pub fn[A, B] Array::rev_fold( #| self : Array[A], #| init~ : B, #| f : (B, A) -> B raise?, #|) -> B raise? { #| for i = self.length() - 1, acc = init; i >= 0; { #| continue i - 1, f(acc, self[i]) #| } else { #| acc #| } #|} #|#locals(f) #|pub fn[A, B] Array::foldi( #| self : Array[A], #| init~ : B, #| f : (Int, B, A) -> B raise?, #|) -> B raise? { #| for i = 0, acc = init; i < self.length(); { #| continue i + 1, f(i, acc, self[i]) #| } else { #| acc #| } #|} #|#locals(f) #|pub fn[A, B] Array::rev_foldi( #| self : Array[A], #| init~ : B, #| f : (Int, B, A) -> B raise?, #|) -> B raise? { #| let len = self.length() #| for i = len - 1, acc = init; i >= 0; { #| continue i - 1, f(len - i - 1, acc, self[i]) #| } else { #| acc #| } #|} #|pub fn[T : Eq] Array::dedup(self : Array[T]) -> Unit { #| if self.is_empty() { #| return #| } #| let mut w = 1 #| for i in 1.. Bool) -> Array[T] { #| let v = [] #| let indices = [] #| for i in 0.. ignore #| } #| v #|} #|pub fn[T] Array::chunks(self : Array[T], size : Int) -> Array[Array[T]] { #| guard size > 0 #| let chunks = [] #| let mut i = 0 #| while i < self.length() { #| let chunk = Array::new(capacity=size) #| for j = 0; j < size && i < self.length(); j = j + 1 { #| chunk.push(self[i]) #| i = i + 1 #| } #| chunks.push(chunk) #| } #| chunks #|} #|#locals(pred) #|pub fn[T] Array::chunk_by( #| self : Array[T], #| pred : (T, T) -> Bool raise?, #|) -> Array[Array[T]] raise? { #| let chunks = [] #| let mut i = 0 #| while i < self.length() { #| let chunk = [] #| chunk.push(self[i]) #| i = i + 1 #| while i < self.length() && pred(self[i - 1], self[i]) { #| chunk.push(self[i]) #| i = i + 1 #| } #| chunks.push(chunk) #| } #| chunks #|} #|pub fn[T] Array::windows(self : Array[T], size : Int) -> Array[ArrayView[T]] { #| guard size > 0 #| let len = self.length() - size + 1 #| if len < 1 { #| return [] #| } #| let windows = Array::new(capacity=len) #| for i in 0.. Bool raise?, #|) -> Array[Array[T]] raise? { #| let chunks = [] #| let mut i = 0 #| while i < self.length() { #| let chunk = [] #| while i < self.length() && !pred(self[i]) { #| chunk.push(self[i]) #| i = i + 1 #| } #| chunks.push(chunk) #| i = i + 1 #| } #| chunks #|} #|pub fn[T] Array::iter(self : Array[T]) -> Iter[T] { #| Iter::new(yield_ => for v in self { #| guard yield_(v) is IterContinue else { break IterEnd } #| } else { #| IterContinue #| }) #|} #|pub fn[T] Array::rev_iter(self : Array[T]) -> Iter[T] { #| Iter::new(yield_ => for i = self.length() - 1; i >= 0; i = i - 1 { #| guard yield_(self.unsafe_get(i)) is IterContinue else { break IterEnd } #| } else { #| IterContinue #| }) #|} #|pub fn[A] Array::iter2(self : Array[A]) -> Iter2[Int, A] { #| Iter2::new(yield_ => for i, v in self { #| guard yield_(i, v) is IterContinue else { break IterEnd } #| } else { #| IterContinue #| }) #|} #|pub impl[T] Default for Array[T] with default() { #| [] #|} #|#internal(unsafe, "Panic if the array is empty on non-JS backend.") #|pub fn[A] Array::unsafe_pop_back(self : Array[A]) -> Unit { #| self.unsafe_pop() |> ignore #|} #|pub fn[A] Array::truncate(self : Array[A], len : Int) -> Unit { #| guard len >= 0 && len < self.length() else { return } #| self.unsafe_truncate_to_length(len) #|} #|pub fn[A] Array::retain_map(self : Array[A], f : (A) -> A?) -> Unit { #| if self.is_empty() { #| return #| } #| let buf = self.buffer() #| let len = self.length() #| let mut write_idx = 0 #| for read_idx in 0.. { #| buf[write_idx] = new_val #| write_idx += 1 #| } #| None => () #| } #| } #| self.unsafe_truncate_to_length(write_idx) #|} ), "array_block.mbt": ( #|#internal(unsafe, "Panic if the indices or length are out of bounds") #|pub fn[A] Array::unsafe_blit( #| dst : Array[A], #| dst_offset : Int, #| src : Array[A], #| src_offset : Int, #| len : Int, #|) -> Unit { #| FixedArray::unsafe_blit( #| dst.buffer().0, #| dst_offset, #| src.buffer().0, #| src_offset, #| len, #| ) #|} #|pub fn[A] Array::unsafe_blit_fixed( #| dst : Array[A], #| dst_offset : Int, #| src : FixedArray[A], #| src_offset : Int, #| len : Int, #|) -> Unit { #| UninitializedArray::unsafe_blit_fixed( #| dst.buffer(), #| dst_offset, #| src, #| src_offset, #| len, #| ) #|} #|pub fn[A] Array::blit_to( #| self : Array[A], #| dst : Array[A], #| len~ : Int, #| src_offset? : Int = 0, #| dst_offset? : Int = 0, #|) -> Unit { #| guard len >= 0 && #| dst_offset >= 0 && #| src_offset >= 0 && #| dst_offset <= dst.length() && #| src_offset + len <= self.length() #| if dst_offset + len > dst.length() { #| dst.unsafe_grow_to_length(dst_offset + len) #| } #| Array::unsafe_blit(dst, dst_offset, self, src_offset, len) #|} #|test "Array::blit_to/basic" { #| let src = [1, 2, 3, 4, 5] #| let dst = [0, 0, 0, 0, 0] #| Array::blit_to(src, dst, len=3, src_offset=1, dst_offset=2) #| inspect(dst, content="[0, 0, 2, 3, 4]") #|} #|test "Array::blit_to/basic" { #| let src = [1, 2, 3, 4, 5] #| let dst = [0, 0, 0, 0, 0] #| Array::blit_to(src, dst, len=3) #| inspect(dst, content="[1, 2, 3, 0, 0]") #|} #|test "Array::blit_to/zero_length" { #| let src = [1, 2, 3] #| let dst = [4, 5, 6] #| Array::blit_to(src, dst, len=0) #| inspect(dst, content="[4, 5, 6]") #|} #|test "Array::blit_to/grow_destination" { #| let src = [1, 2, 3, 4, 5] #| let dst = [0, 0] #| Array::blit_to(src, dst, len=3, dst_offset=1) #| inspect(dst, content="[0, 1, 2, 3]") #|} #|test "Array::blit_to/edge_cases" { #| let src = [1, 2, 3, 4, 5] #| let dst = [0, 0, 0, 0, 0] #| Array::blit_to(src, dst, len=2, src_offset=1, dst_offset=2) #| inspect(dst, content="[0, 0, 2, 3, 0]") #| Array::blit_to(src, src, len=2, src_offset=0, dst_offset=3) #| inspect(src, content="[1, 2, 3, 1, 2]") #| Array::blit_to(src, dst, len=0, src_offset=0, dst_offset=0) #| inspect(dst, content="[0, 0, 2, 3, 0]") #| Array::blit_to(src, dst, len=5) #| inspect(dst, content="[1, 2, 3, 1, 2]") #|} #|test "Array::blit_to/edge_cases" { #| let src = [1, 2, 3, 4, 5] #| let dst = [0, 0, 0, 0, 0] #| Array::blit_to(src, dst, len=0, src_offset=0, dst_offset=0) #| inspect(dst, content="[0, 0, 0, 0, 0]") #| Array::blit_to(src, dst, len=5, src_offset=0, dst_offset=0) #| inspect(dst, content="[1, 2, 3, 4, 5]") #|} #|test "panic Array::blit_to/boundary_cases" { #| let src = [1, 2, 3, 4, 5] #| let dst = [0, 0, 0, 0, 0] #| ignore(Array::blit_to(src, dst, len=-1)) #|} #|test "panic Array::blit_to/boundary_cases" { #| let src = [1, 2, 3, 4, 5] #| let dst = [0, 0, 0, 0, 0] #| ignore(Array::blit_to(src, dst, len=2, src_offset=-1)) #|} #|test "panic Array::blit_to/boundary_cases" { #| let src = [1, 2, 3, 4, 5] #| let dst = [0, 0, 0, 0, 0] #| ignore(Array::blit_to(src, dst, len=6)) #|} #|test "panic Array::blit_to/boundary_cases" { #| let src = [1, 2, 3, 4, 5] #| let dst = [0, 0, 0, 0, 0] #| ignore(Array::blit_to(src, dst, len=5, dst_offset=6)) #|} #|test "Array::blit_to - random cases" { #| let src = [10, 20, 30, 40, 50] #| let dst = [0, 0, 0, 0, 0] #| Array::blit_to(src, dst, len=2, src_offset=2, dst_offset=1) #| inspect(dst, content="[0, 30, 40, 0, 0]") #| Array::blit_to(src, dst, len=3, src_offset=1, dst_offset=2) #| inspect(dst, content="[0, 30, 20, 30, 40]") #| Array::blit_to(src, dst, len=1, src_offset=4, dst_offset=4) #| inspect(dst, content="[0, 30, 20, 30, 50]") #|} #|test "Array::blit_to - boundary cases" { #| let src = [1, 2, 3, 4, 5] #| let dst = [0, 0, 0, 0, 0] #| Array::blit_to(src, dst, len=1, src_offset=4, dst_offset=0) #| inspect(dst, content="[5, 0, 0, 0, 0]") #| Array::blit_to(src, dst, len=1, src_offset=0, dst_offset=4) #| inspect(dst, content="[5, 0, 0, 0, 1]") #| Array::blit_to(src, dst, len=2, src_offset=3, dst_offset=3) #| inspect(dst, content="[5, 0, 0, 4, 5]") #|} #|test "Array::unsafe_blit_fixed" { #| let src = FixedArray::make(3, 1) // Create a FixedArray with 3 elements of value 1 #| let dst = Array::make(5, 0) // Create an Array with 5 elements of value 0 #| Array::unsafe_blit_fixed(dst, 1, src, 0, 2) // Copy 2 elements from src[0] to dst[1] #| inspect(dst, content="[0, 1, 1, 0, 0]") #|} ), "arraycore_js.mbt": ( #|#external #|priv type JSValue #|fn[T] JSValue::ofAny(array : T) -> JSValue = "%identity" #|fn[T] JSValue::toAny(self : JSValue) -> T = "%identity" #|#external #|priv type JSArray #|fn[T] JSArray::ofAnyArray(array : Array[T]) -> JSArray = "%identity" #|fn[T] JSArray::toAnyArray(self : JSArray) -> Array[T] = "%identity" #|extern "js" fn JSArray::set_length(self : JSArray, new_len : Int) -> Unit = #| #| (arr, len) => { arr.length = len; } #|extern "js" fn JSArray::push(self : JSArray, value : JSValue) -> Unit = #| #| (arr, val) => { arr.push(val); } #|extern "js" fn JSArray::pop(self : JSArray) -> JSValue = #| #| (arr) => arr.pop() #|extern "js" fn JSArray::splice( #| self : JSArray, #| index : Int, #| count : Int, #|) -> JSArray = #| #| (arr, idx, cnt) => arr.splice(idx, cnt) #|extern "js" fn JSArray::splice1( #| self : JSArray, #| index : Int, #| count : Int, #| value : JSValue, #|) -> JSArray = #| #| (arr, idx, cnt, val) => arr.splice(idx, cnt, val) #|extern "js" fn JSArray::fill( #| self : JSArray, #| value : JSValue, #| start : Int, #| end : Int, #|) -> Unit = #| #| (arr, val, start, end) => arr.fill(val, start, end) #|#external #|type Array[T] #|fn[T] Array::make_uninit(len : Int) -> Array[T] = "%fixedarray.make_uninit" #|pub fn[T] Array::new(capacity? : Int = 0) -> Array[T] { #| ignore(capacity) #| [] #|} #|pub fn[T] Array::length(self : Array[T]) -> Int = "%fixedarray.length" #|fn[T] Array::unsafe_truncate_to_length(self : Array[T], new_len : Int) -> Unit { #| JSArray::ofAnyArray(self).set_length(new_len) #|} #|fn[T] Array::buffer(self : Array[T]) -> UninitializedArray[T] = "%identity" #|test "array_unsafe_blit_fixed" { #| let src = FixedArray::make(5, 0) #| let dst = UninitializedArray::make(5) #| for i in 0..<5 { #| src[i] = i + 1 #| } #| UninitializedArray::unsafe_blit_fixed(dst, 0, src, 0, 5) #| for i in 0..<5 { #| assert_eq(dst[i], src[i]) #| } #|} #|test "UninitializedArray::unsafe_blit_fixed" { #| let src = FixedArray::make(5, 0) #| let dst = UninitializedArray::make(5) #| for i in 0..<5 { #| src[i] = i + 1 #| } #| UninitializedArray::unsafe_blit_fixed(dst, 0, src, 0, 5) #| for i in 0..<5 { #| assert_eq(dst[i], src[i]) #| } #|} #|test "UninitializedArray::unsafe_blit_fixed" { #| let src = FixedArray::make(5, 0) #| let dst = UninitializedArray::make(5) #| for i in 0..<5 { #| src[i] = i + 1 #| } #| UninitializedArray::unsafe_blit_fixed(dst, 0, src, 0, 5) #| for i in 0..<5 { #| assert_eq(dst[i], src[i]) #| } #|} #|pub fn[T] Array::reserve_capacity(self : Array[T], capacity : Int) -> Unit { #| ignore(self) #| ignore(capacity) #|} #|pub fn[T] Array::shrink_to_fit(self : Array[T]) -> Unit { #| ignore(self) #|} #|pub fn[T] Array::push(self : Array[T], value : T) -> Unit { #| JSArray::ofAnyArray(self).push(JSValue::ofAny(value)) #|} #|pub fn[T] Array::pop(self : Array[T]) -> T? { #| if self.length() == 0 { #| None #| } else { #| let v = self.unsafe_pop() #| Some(v) #| } #|} #|#internal(unsafe, "Panic if the array is empty.") #|pub fn[T] Array::unsafe_pop(self : Array[T]) -> T { #| JSArray::ofAnyArray(self).pop().toAny() #|} #|pub fn[T] Array::remove(self : Array[T], index : Int) -> T { #| guard index >= 0 && index < self.length() else { #| abort( #| "index out of bounds: the len is from 0 to \{self.length()} but the index is \{index}", #| ) #| } #| let value = self.buffer()[index] #| let _ = JSArray::ofAnyArray(self).splice(index, 1) #| value #|} #|pub fn[T] Array::drain(self : Array[T], begin : Int, end : Int) -> Array[T] { #| guard begin >= 0 && end <= self.length() && begin <= end else { #| abort( #| "index out of bounds: the len is \{self.length()} but the index is (\{begin}, \{end})", #| ) #| } #| JSArray::ofAnyArray(self).splice(begin, end - begin).toAnyArray() #|} #|pub fn[T] Array::insert(self : Array[T], index : Int, value : T) -> Unit { #| guard index >= 0 && index <= self.length() else { #| abort( #| "index out of bounds: the len is from 0 to \{self.length()} but the index is \{index}", #| ) #| } #| let _ = JSArray::ofAnyArray(self).splice1(index, 0, JSValue::ofAny(value)) #|} #|fn[T] Array::unsafe_grow_to_length(self : Array[T], new_len : Int) -> Unit { #| guard new_len >= self.length() #| JSArray::ofAnyArray(self).set_length(new_len) #|} #|pub fn[A] Array::fill( #| self : Array[A], #| value : A, #| start? : Int = 0, #| end? : Int, #|) -> Unit { #| let array_length = self.length() #| guard array_length > 0 else { return } #| guard start >= 0 && start < array_length #| let end = match end { #| None => array_length #| Some(e) => { #| guard e >= 0 && e <= array_length #| e #| } #| } #| JSArray::ofAnyArray(self).fill(JSValue::ofAny(value), start, end) #|} ), "arraycore_nonjs.mbt": ( #|fn[T] set_null(self : UninitializedArray[T], index : Int) = "%fixedarray.set_null" #|struct Array[T] { #| mut buf : UninitializedArray[T] #| mut len : Int #|} #|fn[T] Array::make_uninit(len : Int) -> Array[T] { #| { buf: UninitializedArray::make(len), len } #|} #|pub fn[T] Array::new(capacity? : Int = 0) -> Array[T] { #| if capacity == 0 { #| [] #| } else { #| { buf: UninitializedArray::make(capacity), len: 0 } #| } #|} #|#intrinsic("%array.length") #|pub fn[T] Array::length(self : Array[T]) -> Int { #| self.len #|} #|fn[T] Array::unsafe_truncate_to_length(self : Array[T], new_len : Int) -> Unit { #| let len = self.length() #| guard new_len <= len #| for i in new_len.. UninitializedArray[T] { #| self.buf #|} #|fn[T] Array::resize_buffer(self : Array[T], new_capacity : Int) -> Unit { #| let new_buf = UninitializedArray::make(new_capacity) #| let old_buf = self.buf #| let old_cap = old_buf.0.length() #| let copy_len = if old_cap < new_capacity { old_cap } else { new_capacity } #| UninitializedArray::unsafe_blit(new_buf, 0, old_buf, 0, copy_len) #| self.buf = new_buf #|} #|test "array_unsafe_blit_fixed" { #| let src = FixedArray::make(5, 0) #| let dst = UninitializedArray::make(5) #| for i in 0..<5 { #| src[i] = i + 1 #| } #| UninitializedArray::unsafe_blit_fixed(dst, 0, src, 0, 5) #| for i in 0..<5 { #| assert_eq(dst[i], src[i]) #| } #|} #|test "UninitializedArray::unsafe_blit_fixed" { #| let src = FixedArray::make(5, 0) #| let dst = UninitializedArray::make(5) #| for i in 0..<5 { #| src[i] = i + 1 #| } #| UninitializedArray::unsafe_blit_fixed(dst, 0, src, 0, 5) #| for i in 0..<5 { #| assert_eq(dst[i], src[i]) #| } #|} #|test "UninitializedArray::unsafe_blit_fixed" { #| let src = FixedArray::make(5, 0) #| let dst = UninitializedArray::make(5) #| for i in 0..<5 { #| src[i] = i + 1 #| } #| UninitializedArray::unsafe_blit_fixed(dst, 0, src, 0, 5) #| for i in 0..<5 { #| assert_eq(dst[i], src[i]) #| } #|} #|test "Array::resize_buffer" { #| let arr = Array::new(capacity=2) #| arr.push(1) #| arr.push(2) #| arr.resize_buffer(4) #| assert_eq(arr.buffer().0.length() >= 4, true) #| arr.push(3) #| arr.push(4) #| assert_eq(arr.length(), 4) #| assert_eq(arr[0], 1) #| assert_eq(arr[1], 2) #| assert_eq(arr[2], 3) #| assert_eq(arr[3], 4) #|} #|fn[T] Array::realloc(self : Array[T]) -> Unit { #| let old_cap = self.length() #| let new_cap = if old_cap == 0 { 8 } else { old_cap * 2 } #| self.resize_buffer(new_cap) #|} #|pub fn[T] Array::reserve_capacity(self : Array[T], capacity : Int) -> Unit { #| if self.capacity() >= capacity { #| return #| } #| self.resize_buffer(capacity) #|} #|pub fn[T] Array::shrink_to_fit(self : Array[T]) -> Unit { #| if self.capacity() <= self.length() { #| return #| } #| self.resize_buffer(self.length()) #|} #|pub fn[T] Array::push(self : Array[T], value : T) -> Unit { #| if self.length() == self.buffer().0.length() { #| self.realloc() #| } #| let length = self.length() #| self.unsafe_set(length, value) #| self.len = length + 1 #|} #|pub fn[T] Array::pop(self : Array[T]) -> T? { #| let len = self.length() #| if len == 0 { #| None #| } else { #| let index = len - 1 #| let v = self.unsafe_get(index) #| self.buf.set_null(index) #| self.len = index #| Some(v) #| } #|} #|#internal(unsafe, "Panic if the array is empty.") #|pub fn[T] Array::unsafe_pop(self : Array[T]) -> T { #| let len = self.length() #| guard len != 0 #| let index = len - 1 #| let v = self.unsafe_get(index) #| self.buf.set_null(index) #| self.len = index #| v #|} #|pub fn[T] Array::remove(self : Array[T], index : Int) -> T { #| guard index >= 0 && index < self.length() else { #| abort( #| "index out of bounds: the len is from 0 to \{self.length()} but the index is \{index}", #| ) #| } #| let value = self.unsafe_get(index) #| UninitializedArray::unsafe_blit( #| self.buffer(), #| index, #| self.buffer(), #| index + 1, #| self.length() - index - 1, #| ) #| self.unsafe_truncate_to_length(self.length() - 1) #| value #|} #|pub fn[T] Array::drain(self : Array[T], begin : Int, end : Int) -> Array[T] { #| guard begin >= 0 && end <= self.length() && begin <= end #| let num = end - begin #| let v = Array::make_uninit(num) #| UninitializedArray::unsafe_blit(v.buffer(), 0, self.buffer(), begin, num) #| UninitializedArray::unsafe_blit( #| self.buffer(), #| begin, #| self.buffer(), #| end, #| self.length() - end, #| ) #| self.unsafe_truncate_to_length(self.length() - num) #| v #|} #|pub fn[T] Array::insert(self : Array[T], index : Int, value : T) -> Unit { #| guard index >= 0 && index <= self.length() else { #| abort( #| "index out of bounds: the len is from 0 to \{self.length()} but the index is \{index}", #| ) #| } #| if self.length() == self.buffer().0.length() { #| self.realloc() #| } #| UninitializedArray::unsafe_blit( #| self.buffer(), #| index + 1, #| self.buffer(), #| index, #| self.length() - index, #| ) #| let length = self.length() #| self.unsafe_set(index, value) #| self.len = length + 1 #|} #|fn[T] Array::unsafe_grow_to_length(self : Array[T], new_len : Int) -> Unit { #| guard new_len >= self.length() #| let new_buf = UninitializedArray::make(new_len) #| UninitializedArray::unsafe_blit(new_buf, 0, self.buf, 0, self.len) #| self.len = new_len #| self.buf = new_buf #|} #|pub fn[A] Array::fill( #| self : Array[A], #| value : A, #| start? : Int = 0, #| end? : Int, #|) -> Unit { #| let array_length = self.length() #| guard array_length > 0 else { return } #| guard start >= 0 && start < array_length #| let length = match end { #| None => array_length #| Some(e) => { #| guard e >= start && e <= array_length #| e #| } #| } #| self.buf.unchecked_fill(start, value, length - start) #|} ), "arrayview.mbt": ( #|#deprecated("use @array.View instead") #|#builtin.valtype #|type ArrayView[T] #|fn[T] ArrayView::buf(self : ArrayView[T]) -> UninitializedArray[T] = "%arrayview.buf" #|fn[T] ArrayView::start(self : ArrayView[T]) -> Int = "%arrayview.start" #|fn[T] ArrayView::len(self : ArrayView[T]) -> Int = "%arrayview.len" #|fn[T] ArrayView::make( #| buf : UninitializedArray[T], #| start : Int, #| len : Int, #|) -> ArrayView[T] = "%arrayview.make" #|pub fn[T] ArrayView::length(self : ArrayView[T]) -> Int { #| self.len() #|} #|pub fn[T] ArrayView::op_get(self : ArrayView[T], index : Int) -> T { #| guard index >= 0 && index < self.len() else { #| abort( #| "index out of bounds: the len is from 0 to \{self.len()} but the index is \{index}", #| ) #| } #| self.buf()[self.start() + index] #|} #|#intrinsic("%arrayview.unsafe_get") #|#internal(unsafe, "Panic if index is out of bounds") #|pub fn[T] ArrayView::unsafe_get(self : ArrayView[T], index : Int) -> T { #| self.buf()[self.start() + index] #|} #|pub fn[T] ArrayView::op_set( #| self : ArrayView[T], #| index : Int, #| value : T, #|) -> Unit { #| guard index >= 0 && index < self.len() else { #| abort( #| "index out of bounds: the len is from 0 to \{self.len()} but the index is \{index}", #| ) #| } #| self.buf()[self.start() + index] = value #|} #|pub fn[T] ArrayView::swap(self : ArrayView[T], i : Int, j : Int) -> Unit { #| guard i >= 0 && i < self.len() && j >= 0 && j < self.len() else { #| abort( #| "index out of bounds: the len is from 0 to \{self.len()} but the index is (\{i}, \{j})", #| ) #| } #| let temp = self.buf()[self.start() + i] #| self.buf()[self.start() + i] = self.buf()[self.start() + j] #| self.buf()[self.start() + j] = temp #|} #|pub fn[T] Array::op_as_view( #| self : Array[T], #| start? : Int = 0, #| end? : Int, #|) -> ArrayView[T] { #| let len = self.length() #| let end = match end { #| None => len #| Some(end) => if end < 0 { len + end } else { end } #| } #| let start = if start < 0 { len + start } else { start } #| guard start >= 0 && start <= end && end <= len else { #| abort("View index out of bounds") #| } #| ArrayView::make(self.buffer(), start, end - start) #|} #|pub fn[T] ArrayView::op_as_view( #| self : ArrayView[T], #| start? : Int = 0, #| end? : Int, #|) -> ArrayView[T] { #| let len = self.length() #| let end = match end { #| None => len #| Some(end) => if end < 0 { len + end } else { end } #| } #| let start = if start < 0 { len + start } else { start } #| guard start >= 0 && start <= end && end <= len else { #| abort("View index out of bounds") #| } #| ArrayView::make(self.buf(), self.start() + start, end - start) #|} ), "assert.mbt": ( #|fn[T : Show] debug_string(t : T) -> String { #| let buf = StringBuilder::new(size_hint=50) #| t.output(buf) #| buf.to_string() #|} #|#callsite(autofill(loc)) #|#coverage.skip #|pub fn[T : Eq + Show] assert_eq( #| a : T, #| b : T, #| msg? : String, #| loc~ : SourceLoc, #|) -> Unit raise { #| if a != b { #| let fail_msg = match msg { #| Some(msg) => msg #| None => "`\{debug_string(a)} != \{debug_string(b)}`" #| } #| fail(fail_msg, loc~) #| } #|} #|#callsite(autofill(loc)) #|#coverage.skip #|pub fn[T : Eq + Show] assert_not_eq( #| a : T, #| b : T, #| msg? : String, #| loc~ : SourceLoc, #|) -> Unit raise { #| if !(a != b) { #| let fail_msg = match msg { #| Some(msg) => msg #| None => "`\{debug_string(a)} == \{debug_string(b)}`" #| } #| fail(fail_msg, loc~) #| } #|} #|#callsite(autofill(loc)) #|#coverage.skip #|pub fn assert_true(x : Bool, msg? : String, loc~ : SourceLoc) -> Unit raise { #| if !x { #| let fail_msg = match msg { #| Some(msg) => msg #| None => "`\{x}` is not true" #| } #| fail(fail_msg, loc~) #| } #|} #|#callsite(autofill(loc)) #|#coverage.skip #|pub fn assert_false(x : Bool, msg? : String, loc~ : SourceLoc) -> Unit raise { #| if x { #| let fail_msg = match msg { #| Some(msg) => msg #| None => "`\{x}` is not false" #| } #| fail(fail_msg, loc~) #| } #|} ), "autoloc.mbt": ( #|pub(all) type SourceLoc #|pub fn SourceLoc::to_string(self : Self) -> String = "%loc_to_string" #|pub impl Show for SourceLoc with output(self, logger) { #| logger.write_string(self.to_string()) #|} #|pub(all) struct ArgsLoc(Array[SourceLoc?]) derive(Show) #|pub fn ArgsLoc::to_json(self : ArgsLoc) -> String { #| let buf = StringBuilder::new(size_hint=10) #| let ArgsLoc(self) = self #| buf.write_char('[') #| for i in 0.. buf.write_string("null") #| Some(loc) => loc.to_string() |> Show::output(buf) #| } #| } #| buf.write_char(']') #| buf.to_string() #|} ), "byte.mbt": ( #|pub impl Mul for Byte with op_mul(self : Byte, that : Byte) -> Byte { #| (self.to_int() * that.to_int()).to_byte() #|} #|pub impl Div for Byte with op_div(self : Byte, that : Byte) -> Byte { #| (self.to_int() / that.to_int()).to_byte() #|} #|pub impl Mod for Byte with op_mod(self : Byte, that : Byte) -> Byte { #| (self.to_int() % that.to_int()).to_byte() #|} #|pub impl Eq for Byte with op_equal(self : Byte, that : Byte) -> Bool { #| self.to_int() == that.to_int() #|} #|pub impl Add for Byte with op_add(self : Byte, that : Byte) -> Byte { #| (self.to_int() + that.to_int()).to_byte() #|} #|pub impl Sub for Byte with op_sub(self : Byte, that : Byte) -> Byte { #| (self.to_int() - that.to_int()).to_byte() #|} #|pub impl Compare for Byte with compare(self : Byte, that : Byte) -> Int { #| self.to_int().compare(that.to_int()) #|} #|fn alphabet(x : Int) -> String { #| match x { #| 0 => "0" #| 1 => "1" #| 2 => "2" #| 3 => "3" #| 4 => "4" #| 5 => "5" #| 6 => "6" #| 7 => "7" #| 8 => "8" #| 9 => "9" #| 10 => "A" #| 11 => "B" #| 12 => "C" #| 13 => "D" #| 14 => "E" #| 15 => "F" #| _ => abort("impossible") #| } #|} #|pub fn Byte::to_string(self : Byte) -> String { #| let i = self.to_int() #| let hi = alphabet(i / 16) #| let lo = alphabet(i % 16) #| "b'\\x\{hi}\{lo}'" #|} #|pub impl Hash for Byte with hash(self) { #| self.to_int() #|} #|pub impl Hash for Byte with hash_combine(self, hasher) { #| hasher.combine_byte(self) #|} #|pub impl Default for Byte with default() { #| b'\x00' #|} #|pub fn Byte::lnot(self : Byte) -> Byte { #| self.to_int().lnot().to_byte() #|} #|pub impl BitAnd for Byte with land(self : Byte, that : Byte) -> Byte { #| (self.to_int() & that.to_int()).to_byte() #|} #|pub impl BitOr for Byte with lor(self : Byte, that : Byte) -> Byte { #| (self.to_int() | that.to_int()).to_byte() #|} #|pub impl BitXOr for Byte with lxor(self : Byte, that : Byte) -> Byte { #| (self.to_int() ^ that.to_int()).to_byte() #|} #|pub fn Byte::to_uint(self : Byte) -> UInt { #| self.to_int().reinterpret_as_uint() #|} #|pub impl Shl for Byte with op_shl(self : Byte, count : Int) -> Byte { #| (self.to_int() << count).to_byte() #|} #|pub impl Shr for Byte with op_shr(self : Byte, count : Int) -> Byte { #| (self.to_uint() >> count).reinterpret_as_int().to_byte() #|} ), "bytes.mbt": ( #|#internal(unsafe, "Creating mutable Bytes") #|pub fn FixedArray::unsafe_reinterpret_as_bytes( #| self : FixedArray[Byte], #|) -> Bytes = "%identity" #|pub fn Bytes::makei(length : Int, value : (Int) -> Byte raise?) -> Bytes raise? { #| if length <= 0 { #| return [] #| } #| let arr = FixedArray::make(length, value(0)) #| for i in 1.. String = "$moonbit.unsafe_bytes_sub_string" #|pub fn Bytes::to_unchecked_string( #| self : Bytes, #| offset? : Int = 0, #| length? : Int, #|) -> String { #| let len = self.length() #| let length = if length is Some(l) { l } else { len - offset } #| guard offset >= 0 && length >= 0 && offset + length <= len #| unsafe_sub_string(self, offset, length) #|} #|pub fn FixedArray::blit_from_string( #| self : FixedArray[Byte], #| bytes_offset : Int, #| str : String, #| str_offset : Int, #| length : Int, #|) -> Unit { #| let s1 = bytes_offset #| let s2 = str_offset #| let e1 = bytes_offset + length * 2 - 1 #| let e2 = str_offset + length - 1 #| let len1 = self.length() #| let len2 = str.length() #| guard length >= 0 && s1 >= 0 && e1 < len1 && s2 >= 0 && e2 < len2 #| let end_str_offset = str_offset + length #| for i = str_offset, j = bytes_offset; i < end_str_offset; i = i + 1, j = j + 2 { #| let c = str.unsafe_charcode_at(i).reinterpret_as_uint() #| self[j] = (c & 0xff).to_byte() #| self[j + 1] = (c >> 8).to_byte() #| } #|} #|fn unsafe_from_bytes(bytes : Bytes) -> FixedArray[Byte] = "%identity" #|pub fn FixedArray::blit_from_bytes( #| self : FixedArray[Byte], #| bytes_offset : Int, #| src : Bytes, #| src_offset : Int, #| length : Int, #|) -> Unit { #| let s1 = bytes_offset #| let s2 = src_offset #| let e1 = bytes_offset + length - 1 #| let e2 = src_offset + length - 1 #| let len1 = self.length() #| let len2 = src.length() #| guard length >= 0 && s1 >= 0 && e1 < len1 && s2 >= 0 && e2 < len2 #| FixedArray::unsafe_blit( #| self, #| bytes_offset, #| unsafe_from_bytes(src), #| src_offset, #| length, #| ) #|} #|pub fn FixedArray::set_utf8_char( #| self : FixedArray[Byte], #| offset : Int, #| value : Char, #|) -> Int { #| let code = value.to_uint() #| match code { #| _..<0x80 => { #| self[offset] = ((code & 0x7F) | 0x00).to_byte() #| 1 #| } #| _..<0x0800 => { #| self[offset] = (((code >> 6) & 0x1F) | 0xC0).to_byte() #| self[offset + 1] = ((code & 0x3F) | 0x80).to_byte() #| 2 #| } #| _..<0x010000 => { #| self[offset] = (((code >> 12) & 0x0F) | 0xE0).to_byte() #| self[offset + 1] = (((code >> 6) & 0x3F) | 0x80).to_byte() #| self[offset + 2] = ((code & 0x3F) | 0x80).to_byte() #| 3 #| } #| _..<0x110000 => { #| self[offset] = (((code >> 18) & 0x07) | 0xF0).to_byte() #| self[offset + 1] = (((code >> 12) & 0x3F) | 0x80).to_byte() #| self[offset + 2] = (((code >> 6) & 0x3F) | 0x80).to_byte() #| self[offset + 3] = ((code & 0x3F) | 0x80).to_byte() #| 4 #| } #| _ => abort("Char out of range") #| } #|} #|pub fn FixedArray::set_utf16le_char( #| self : FixedArray[Byte], #| offset : Int, #| value : Char, #|) -> Int { #| let code = value.to_uint() #| if code < 0x10000 { #| self[offset] = (code & 0xFF).to_byte() #| self[offset + 1] = (code >> 8).to_byte() #| 2 #| } else if code < 0x110000 { #| let hi = code - 0x10000 #| let lo = (hi >> 10) | 0xD800 #| let hi = (hi & 0x3FF) | 0xDC00 #| self[offset] = (lo & 0xFF).to_byte() #| self[offset + 1] = (lo >> 8).to_byte() #| self[offset + 2] = (hi & 0xFF).to_byte() #| self[offset + 3] = (hi >> 8).to_byte() #| 4 #| } else { #| abort("Char out of range") #| } #|} #|pub fn FixedArray::set_utf16be_char( #| self : FixedArray[Byte], #| offset : Int, #| value : Char, #|) -> Int { #| let code = value.to_uint() #| if code < 0x10000 { #| self[offset] = (code >> 8).to_byte() #| self[offset + 1] = (code & 0xFF).to_byte() #| 2 #| } else if code < 0x110000 { #| let hi = code - 0x10000 #| let lo = (hi >> 10) | 0xD800 #| let hi = (hi & 0x3FF) | 0xDC00 #| self[offset] = (lo >> 8).to_byte() #| self[offset + 1] = (lo & 0xFF).to_byte() #| self[offset + 2] = (hi >> 8).to_byte() #| self[offset + 3] = (hi & 0xFF).to_byte() #| 4 #| } else { #| abort("Char out of range") #| } #|} #|pub impl Eq for Bytes with op_equal(self : Bytes, other : Bytes) -> Bool { #| if self.length() != other.length() { #| false #| } else { #| let len = self.length() #| for i in 0.. Unit = "%println" #|fn[T] any_to_string(any : T) -> String = "%any.to_string" #|pub fn[T : Show] println(input : T) -> Unit { #| println_mono(input.to_string()) #|} #|pub(all) suberror InspectError String #|fn base64_encode(data : FixedArray[Byte]) -> String { #| let base64 = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" #| let buf = StringBuilder::new() #| let len = data.length() #| let rem = len % 3 #| for i = 0; i < len - rem; i = i + 3 { #| let b0 = data[i].to_int() #| let b1 = data[i + 1].to_int() #| let b2 = data[i + 2].to_int() #| let x0 = base64[(b0 & 0xFC) >> 2] #| let x1 = base64[((b0 & 0x03) << 4) | ((b1 & 0xF0) >> 4)] #| let x2 = base64[((b1 & 0x0F) << 2) | ((b2 & 0xC0) >> 6)] #| let x3 = base64[b2 & 0x3F] #| buf.write_char(x0.to_char()) #| buf.write_char(x1.to_char()) #| buf.write_char(x2.to_char()) #| buf.write_char(x3.to_char()) #| } #| if rem == 1 { #| let b0 = data[len - 1].to_int() #| let x0 = base64[(b0 & 0xFC) >> 2] #| let x1 = base64[(b0 & 0x03) << 4] #| buf.write_char(x0.to_char()) #| buf.write_char(x1.to_char()) #| buf.write_char('=') #| buf.write_char('=') #| } else if rem == 2 { #| let b0 = data[len - 2].to_int() #| let b1 = data[len - 1].to_int() #| let x0 = base64[(b0 & 0xFC) >> 2] #| let x1 = base64[((b0 & 0x03) << 4) | ((b1 & 0xF0) >> 4)] #| let x2 = base64[(b1 & 0x0F) << 2] #| buf.write_char(x0.to_char()) #| buf.write_char(x1.to_char()) #| buf.write_char(x2.to_char()) #| buf.write_char('=') #| } #| buf.to_string() #|} #|fn base64_encode_string_codepoint(s : String) -> String { #| let codepoint_length = s.char_length() #| let data : FixedArray[Byte] = FixedArray::make(codepoint_length * 4, 0) #| for i = 0, utf16_index = 0 #| i < codepoint_length #| i = i + 1, utf16_index = utf16_index + 1 { #| let c = s.unsafe_char_at(utf16_index).to_int() #| if c > 0xFFFF { #| data[i * 4] = (c & 0xFF).to_byte() #| data[i * 4 + 1] = ((c >> 8) & 0xFF).to_byte() #| data[i * 4 + 2] = ((c >> 16) & 0xFF).to_byte() #| data[i * 4 + 3] = ((c >> 24) & 0xFF).to_byte() #| continue i + 1, utf16_index + 2 #| } else { #| data[i * 4] = (c & 0xFF).to_byte() #| data[i * 4 + 1] = ((c >> 8) & 0xFF).to_byte() #| data[i * 4 + 2] = 0 #| data[i * 4 + 3] = 0 #| } #| } #| base64_encode(data) #|} #|test { #| inspect(base64_encode_string_codepoint("")) #| inspect(base64_encode_string_codepoint("a"), content="YQAAAA==") #| inspect(base64_encode_string_codepoint("ab"), content="YQAAAGIAAAA=") #| inspect(base64_encode_string_codepoint("abc"), content="YQAAAGIAAABjAAAA") #| inspect( #| base64_encode_string_codepoint("abcd"), #| content="YQAAAGIAAABjAAAAZAAAAA==", #| ) #| inspect( #| base64_encode_string_codepoint("abcde"), #| content="YQAAAGIAAABjAAAAZAAAAGUAAAA=", #| ) #| inspect(base64_encode_string_codepoint("a中"), content="YQAAAC1OAAA=") #| inspect( #| base64_encode_string_codepoint("a中🤣"), #| content="YQAAAC1OAAAj+QEA", #| ) #| inspect( #| base64_encode_string_codepoint("a中🤣a"), #| content="YQAAAC1OAAAj+QEAYQAAAA==", #| ) #| inspect( #| base64_encode_string_codepoint("a中🤣中"), #| content="YQAAAC1OAAAj+QEALU4AAA==", #| ) #|} #|#callsite(autofill(args_loc, loc)) #|pub fn inspect( #| obj : &Show, #| content? : String = "", #| loc~ : SourceLoc, #| args_loc~ : ArgsLoc, #|) -> Unit raise InspectError { #| let actual = obj.to_string() #| if actual != content { #| let loc = loc.to_string().escape() #| let args_loc = args_loc.to_json().escape() #| let expect_escaped = content.escape() #| let actual_escaped = actual.escape() #| let expect_base64 = "\"\{base64_encode_string_codepoint(content)}\"" #| let actual_base64 = "\"\{base64_encode_string_codepoint(actual)}\"" #| raise InspectError( #| "@EXPECT_FAILED {\"loc\": \{loc}, \"args_loc\": \{args_loc}, \"expect\": \{expect_escaped}, \"actual\": \{actual_escaped}, \"expect_base64\": \{expect_base64}, \"actual_base64\": \{actual_base64}}", #| ) #| } #|} #|pub(all) suberror SnapshotError String #|pub(all) suberror BenchError String #|test "panic error case of inspect" { #| let x : Int = 42 #| inspect(x, content="100") #|} ), "deprecated.mbt": ( #|#deprecated("Use `..<` in for loop or `until` method instead") #|#coverage.skip #|pub fn Int::upto(self : Int, end : Int, inclusive? : Bool = false) -> Iter[Int] { #| yield_ => { #| let mut i = self #| while i < end || (inclusive && i == end) { #| if yield_(i) == IterEnd { #| break IterEnd #| } #| if i == end { #| break IterContinue #| } #| i += 1 #| } else { #| IterContinue #| } #| } #|} #|#deprecated("Use `..<` in for loop or `until` method instead") #|#coverage.skip #|pub fn UInt::upto( #| self : UInt, #| end : UInt, #| inclusive? : Bool = false, #|) -> Iter[UInt] { #| yield_ => { #| let mut i = self #| while i < end || (inclusive && i == end) { #| if yield_(i) == IterEnd { #| break IterEnd #| } #| if i == end { #| break IterContinue #| } #| i += 1 #| } else { #| IterContinue #| } #| } #|} #|#deprecated("Use `..<` in for loop or `until` method instead") #|#coverage.skip #|pub fn UInt64::upto( #| self : UInt64, #| end : UInt64, #| inclusive? : Bool = false, #|) -> Iter[UInt64] { #| yield_ => { #| let mut i = self #| while i < end || (inclusive && i == end) { #| if yield_(i) == IterEnd { #| break IterEnd #| } #| if i == end { #| break IterContinue #| } #| i += 1 #| } else { #| IterContinue #| } #| } #|} #|#deprecated("Use `..<` in for loop or `until` method instead") #|#coverage.skip #|pub fn Int64::upto( #| self : Int64, #| end : Int64, #| inclusive? : Bool = false, #|) -> Iter[Int64] { #| yield_ => { #| let mut i = self #| while i < end || (inclusive && i == end) { #| if yield_(i) == IterEnd { #| break IterEnd #| } #| if i == end { #| break IterContinue #| } #| i += 1 #| } else { #| IterContinue #| } #| } #|} #|#deprecated("Use `..<` in for loop or `until` method instead") #|#coverage.skip #|pub fn Float::upto( #| self : Float, #| end : Float, #| inclusive? : Bool = false, #|) -> Iter[Float] { #| yield_ => { #| let mut i = self #| while i < end || (inclusive && i == end) { #| if yield_(i) == IterEnd { #| break IterEnd #| } #| if i == end { #| break IterContinue #| } #| i += 1 #| } else { #| IterContinue #| } #| } #|} #|#deprecated("Use `..<` in for loop or `until` method instead") #|#coverage.skip #|pub fn Double::upto( #| self : Double, #| end : Double, #| inclusive? : Bool = false, #|) -> Iter[Double] { #| yield_ => { #| let mut i = self #| while i < end || (inclusive && i == end) { #| if yield_(i) == IterEnd { #| break IterEnd #| } #| if i == end { #| break IterContinue #| } #| i += 1 #| } else { #| IterContinue #| } #| } #|} #|#deprecated("Use `search_by` instead.") #|#coverage.skip #|pub fn[T] Array::find_index(self : Array[T], f : (T) -> Bool) -> Int? { #| self.search_by(f) #|} #|#deprecated("Use `fold` instead.") #|#coverage.skip #|pub fn[T, U] Array::fold_left( #| self : Array[T], #| f : (U, T) -> U raise?, #| init~ : U, #|) -> U raise? { #| self.fold(init~, f) #|} #|#deprecated("Use `rev_fold` instead.") #|#coverage.skip #|pub fn[T, U] Array::fold_right( #| self : Array[T], #| f : (U, T) -> U raise?, #| init~ : U, #|) -> U raise? { #| self.rev_fold(init~, f) #|} #|#deprecated("Use `foldi` instead.") #|#coverage.skip #|pub fn[T, U] Array::fold_lefti( #| self : Array[T], #| f : (Int, U, T) -> U raise?, #| init~ : U, #|) -> U raise? { #| self.foldi(init~, f) #|} #|#deprecated("Use `rev_foldi` instead.") #|#coverage.skip #|pub fn[T, U] Array::fold_righti( #| self : Array[T], #| f : (Int, U, T) -> U raise?, #| init~ : U, #|) -> U raise? { #| self.rev_foldi(init~, f) #|} #|#deprecated("Use `unsafe_pop` instead") #|#coverage.skip #|pub fn[T] Array::pop_exn(self : Array[T]) -> T { #| self.unsafe_pop() #|} #|#deprecated("Use `str.to_bytes()` instead") #|pub fn Bytes::of_string(str : String) -> Bytes { #| FixedArray::make(str.length() * 2, Byte::default()) #| ..blit_from_string(0, str, 0, str.length()) #| .unsafe_reinterpret_as_bytes() #|} #|#deprecated("Bytes are immutable. Use `FixedArray::blit_from_bytes` if it's really necessary.") #|pub fn Bytes::copy(self : Bytes) -> Bytes { #| Bytes::makei(self.length(), i => self[i]) #|} #|#deprecated("Use infix operator `<<` instead") #|#coverage.skip #|pub fn Byte::lsl(self : Byte, count : Int) -> Byte { #| (self.to_int() << count).to_byte() #|} #|#deprecated("Use infix operator `>>` instead") #|#coverage.skip #|pub fn Byte::lsr(self : Byte, count : Int) -> Byte { #| (self.to_uint() >> count).reinterpret_as_int().to_byte() #|} #|#callsite(autofill(loc)) #|#deprecated("This function is for debugging only and should not be used in production") #|pub fn[T] dump(t : T, name? : String, loc~ : SourceLoc) -> T { #| let name = match name { #| Some(name) => name #| None => "" #| } #| println("dump(\{name}@\{loc}) = \{any_to_string(t)}") #| t #|} #|#deprecated("The index will be changed to utf16 index. If you want to access n-th character, use `str.iter().nth(n).unwrap()` instead.") #|pub fn String::codepoint_at(self : String, index : Int) -> Char { #| let charcode_len = self.length() #| guard index >= 0 && index < charcode_len else { abort("index out of bounds") } #| for char_count = 0, utf16_offset = 0 #| char_count < charcode_len && utf16_offset < index #| char_count = char_count + 1, utf16_offset = utf16_offset + 1 { #| let c1 = self.unsafe_charcode_at(char_count) #| if c1.is_leading_surrogate() && char_count + 1 < charcode_len { #| let c2 = self.unsafe_charcode_at(char_count + 1) #| if c2.is_trailing_surrogate() { #| continue char_count + 2, utf16_offset + 1 #| } else { #| abort("invalid surrogate pair") #| } #| } #| } else { #| guard utf16_offset == index && char_count < charcode_len else { #| abort("index out of bounds") #| } #| let c1 = self.unsafe_charcode_at(char_count) #| if c1.is_leading_surrogate() && char_count + 1 < charcode_len { #| let c2 = self.unsafe_charcode_at(char_count + 1) #| if c2.is_trailing_surrogate() { #| code_point_of_surrogate_pair(c1, c2) #| } else { #| abort("invalid surrogate pair") #| } #| } else { #| c1.unsafe_to_char() #| } #| } #|} #|#deprecated("Use `char_length` instead.") #|pub fn String::codepoint_length( #| self : String, #| start_offset? : Int = 0, #| end_offset? : Int, #|) -> Int { #| self.char_length(start_offset~, end_offset?) #|} #|#deprecated("Use `s[i]` instead") #|pub fn String::charcode_at(self : String, index : Int) -> Int { #| self[index] #|} #|#deprecated("Use `s.get_char(i).unwrap()` instead") #|pub fn String::unsafe_char_at(self : String, index : Int) -> Char { #| let c1 = self.unsafe_charcode_at(index) #| if c1.is_leading_surrogate() { #| let c2 = self.unsafe_charcode_at(index + 1) #| code_point_of_surrogate_pair(c1, c2) #| } else { #| c1.unsafe_to_char() #| } #|} ), "double_to_int.mbt": ( #|pub fn Double::to_int(self : Double) -> Int { #| if self != self { #| 0 #| } else if self >= 2147483647 { #| 2147483647 #| } else if self <= -2147483648 { #| -2147483648 #| } else { #| self.to_unchecked_int() #| } #|} #|fn Double::to_unchecked_int(self : Double) -> Int = "%f64_to_i32" ), "double_to_int64_js.mbt": ( #|extern "js" fn MyInt64::from_double(value : Double) -> MyInt64 = #| #|(a) => { #| #| if (isNaN(a)) { #| #| return { hi: 0, lo: 0 }; #| #| } #| #| if (a >= 9223372036854775807) { #| #| return { hi: 0x7fffffff, lo: 0xffffffff }; #| #| } #| #| if (a <= -9223372036854775808) { #| #| return { hi: -2147483648, lo: 0 }; #| #| } #| #| let neg = false; #| #| if (a < 0) { #| #| neg = true; #| #| a = -a; #| #| } #| #| let hi = (a * (1 / 0x100000000)) | 0; #| #| let lo = a >>> 0; #| #| if (neg) { #| #| if (lo === 0) { #| #| hi = ~hi + 1; #| #| } else { #| #| hi = ~hi; #| #| lo = ~lo + 1; #| #| } #| #| } #| #| return { hi, lo }; #| #|} #|pub fn Double::to_int64(self : Double) -> Int64 { #| MyInt64::from_double(self).to_int64() #|} #|extern "js" fn MyInt64::from_double_unsigned(value : Double) -> MyInt64 = #| #|(a) => { #| #| if (isNaN(a)) { #| #| return { hi: 0, lo: 0 }; #| #| } #| #| if (a >= 18446744073709551615) { #| #| return { hi: 0xffffffff, lo: 0xffffffff }; #| #| } #| #| if (a <= 0) { #| #| return { hi: 0, lo: 0 }; #| #| } #| #| let hi = (a * (1 / 0x100000000)) | 0; #| #| let lo = a >>> 0; #| #| return { hi, lo }; #| #|} #|pub fn Double::to_uint64(self : Double) -> UInt64 { #| MyInt64::from_double_unsigned(self).to_uint64() #|} ), "double_to_int64_native.mbt": ( #|fn Double::to_unchecked_int64(self : Double) -> Int64 = "%f64_to_i64" #|pub fn Double::to_int64(self : Double) -> Int64 { #| if self != self { #| 0 #| } else if self >= 9223372036854775807 { #| 9223372036854775807L #| } else if self <= -9223372036854775808 { #| -9223372036854775808L #| } else { #| self.to_unchecked_int64() #| } #|} #|fn Double::to_unchecked_uint64(self : Double) -> UInt64 = "%f64_to_i64" #|pub fn Double::to_uint64(self : Double) -> UInt64 { #| if self != self { #| 0 #| } else if self >= 9223372036854775807 { #| 18446744073709551615UL #| } else if self <= 0 { #| 0UL #| } else { #| self.to_unchecked_uint64() #| } #|} ), "double_to_int64_wasm.mbt": ( #|pub fn Double::to_int64(self : Double) -> Int64 = "%f64_to_i64_saturate" #|pub fn Double::to_uint64(self : Double) -> UInt64 = "%f64.to_u64_saturate" ), "double_to_int_wasm.mbt": ( #|pub fn Double::to_int(self : Double) -> Int = "%f64_to_i32_saturate" ), "failure.mbt": ( #|pub(all) suberror Failure String derive(ToJson(style="flat"), Show) #|#callsite(autofill(loc)) #|pub fn[T] fail(msg : String, loc~ : SourceLoc) -> T raise Failure { #| raise Failure("\{loc} FAILED: \{msg}") #|} ), "fixedarray.mbt": ( #|pub fn[T] FixedArray::get(self : FixedArray[T], idx : Int) -> T? { #| let len = self.length() #| guard idx >= 0 && idx < len else { None } #| Some(self.unsafe_get(idx)) #|} #|#intrinsic("%iter.from_array") #|pub fn[T] FixedArray::iter(self : FixedArray[T]) -> Iter[T] { #| Iter::new(yield_ => for v in self { #| guard yield_(v) is IterContinue else { break IterEnd } #| } else { #| IterContinue #| }) #|} #|pub fn[T] FixedArray::iter2(self : FixedArray[T]) -> Iter2[Int, T] { #| Iter2::new(yield_ => for i, v in self { #| guard yield_(i, v) is IterContinue else { break IterEnd } #| } else { #| IterContinue #| }) #|} #|pub impl[X] Default for FixedArray[X] with default() { #| [] #|} #|pub fn[T] FixedArray::fill( #| self : FixedArray[T], #| value : T, #| start? : Int = 0, #| end? : Int, #|) -> Unit { #| let array_length = self.length() #| guard array_length > 0 else { return } #| guard start >= 0 && start < array_length #| let length = match end { #| None => array_length - start #| Some(e) => { #| guard e >= start && e <= array_length #| e - start #| } #| } #| self.unchecked_fill(start, value, length) #|} #|#intrinsic("%fixedarray.fill") #|fn[T] FixedArray::unchecked_fill( #| self : FixedArray[T], #| start : Int, #| value : T, #| len : Int, #|) -> Unit { #| for i in start..<(start + len) { #| self[i] = value #| } #|} #|pub fn[T] FixedArray::is_empty(self : FixedArray[T]) -> Bool { #| self.length() == 0 #|} #|pub fn[T : Compare] FixedArray::binary_search( #| self : FixedArray[T], #| value : T, #|) -> Result[Int, Int] { #| let len = self.length() #| for i = 0, j = len; i < j; { #| let h = i + (j - i) / 2 #| if self.unsafe_get(h) < value { #| continue h + 1, j #| } else { #| continue i, h #| } #| } else { #| if i < len && self.unsafe_get(i) == value { #| Ok(i) #| } else { #| Err(i) #| } #| } #|} #|#locals(cmp) #|pub fn[T] FixedArray::binary_search_by( #| self : FixedArray[T], #| cmp : (T) -> Int raise?, #|) -> Result[Int, Int] raise? { #| let len = self.length() #| for i = 0, j = len; i < j; { #| let h = i + (j - i) / 2 #| if cmp(self.unsafe_get(h)) < 0 { #| continue h + 1, j #| } else { #| continue i, h #| } #| } else { #| if i < len && cmp(self.unsafe_get(i)) == 0 { #| Ok(i) #| } else { #| Err(i) #| } #| } #|} ), "fixedarray_block.mbt": ( #|#intrinsic("%fixedarray.copy") #|#coverage.skip #|pub fn[A] FixedArray::unsafe_blit( #| dst : FixedArray[A], #| dst_offset : Int, #| src : FixedArray[A], #| src_offset : Int, #| len : Int, #|) -> Unit { #| if physical_equal(dst, src) && dst_offset < src_offset { #| for i in 0..= 0; i = i - 1 { #| dst[dst_offset + i] = src[src_offset + i] #| } #| } #|} #|#intrinsic("%fixedarray.copy") #|#coverage.skip #|fn[T] UninitializedArray::unsafe_blit_fixed( #| dst : UninitializedArray[T], #| dst_offset : Int, #| src : FixedArray[T], #| src_offset : Int, #| len : Int, #|) -> Unit { #| for i = len - 1; i >= 0; i = i - 1 { #| dst[dst_offset + i] = src[src_offset + i] #| } #|} #|pub fn[A] FixedArray::blit_to( #| self : FixedArray[A], #| dst : FixedArray[A], #| len~ : Int, #| src_offset? : Int = 0, #| dst_offset? : Int = 0, #|) -> Unit { #| guard dst_offset >= 0 && #| src_offset >= 0 && #| dst_offset + len <= dst.length() && #| src_offset + len <= self.length() else { #| abort( #| "bounds check failed: dst_offset = \{dst_offset}, src_offset = \{src_offset}, len = \{len}, dst.length = \{dst.length()}, self.length = \{self.length()}", #| ) #| } #| FixedArray::unsafe_blit(dst, dst_offset, self, src_offset, len) #|} ), "hasher.mbt": ( #|const GPRIME1 : UInt = 0x9E3779B1 #|const GPRIMES2 : UInt = 0x85EBCA77 #|const GPRIME3 : UInt = 0xC2B2AE3D #|const GPRIME4 : UInt = 0x27D4EB2F #|const GPRIME5 : UInt = 0x165667B1 #|struct Hasher { #| mut acc : UInt #|} #|pub fn Hasher::new(seed? : Int = 0) -> Hasher { #| { acc: seed.reinterpret_as_uint() + GPRIME5 } #|} #|pub fn[T : Hash] Hasher::combine(self : Hasher, value : T) -> Unit { #| value.hash_combine(self) #|} #|pub fn Hasher::combine_unit(self : Hasher) -> Unit { #| self.combine_uint(0) #|} #|pub fn Hasher::combine_bool(self : Hasher, value : Bool) -> Unit { #| self.combine_uint(if value { 1 } else { 0 }) #|} #|pub fn Hasher::combine_int(self : Hasher, value : Int) -> Unit { #| self.combine_uint(value.reinterpret_as_uint()) #|} #|pub fn Hasher::combine_int64(self : Hasher, value : Int64) -> Unit { #| self.acc += 8 #| self.consume4(value.reinterpret_as_uint64().to_uint()) #| self.consume4((value.reinterpret_as_uint64() >> 32).to_uint()) #|} #|pub fn Hasher::combine_uint(self : Hasher, value : UInt) -> Unit { #| self.acc += 4 #| self.consume4(value) #|} #|pub fn Hasher::combine_uint64(self : Hasher, value : UInt64) -> Unit { #| self.combine_int64(value.reinterpret_as_int64()) #|} #|pub fn Hasher::combine_double(self : Hasher, value : Double) -> Unit { #| self.combine_int64(value.reinterpret_as_int64()) #|} #|pub fn Hasher::combine_float(self : Hasher, value : Float) -> Unit { #| self.combine_uint(value.reinterpret_as_uint()) #|} #|pub fn Hasher::combine_byte(self : Hasher, value : Byte) -> Unit { #| self.consume1(value) #|} #|pub fn Hasher::combine_bytes(self : Hasher, value : Bytes) -> Unit { #| let mut remain = value.length() #| let mut cur = 0 #| while remain >= 4 { #| self.consume4(endian32(value, cur)) #| cur += 4 #| remain -= 4 #| } #| while remain >= 1 { #| self.consume1(value[cur]) #| cur += 1 #| remain -= 1 #| } #|} #|pub fn Hasher::combine_string(self : Hasher, value : String) -> Unit { #| for i in 0.. Unit { #| self.combine_uint(value.to_uint()) #|} #|pub fn Hasher::finalize(self : Hasher) -> Int { #| self.avalanche().reinterpret_as_int() #|} #|fn Hasher::avalanche(self : Hasher) -> UInt { #| let mut acc = self.acc #| acc = acc ^ (acc >> 15) #| acc *= GPRIMES2 #| acc = acc ^ (acc >> 13) #| acc *= GPRIME3 #| acc = acc ^ (acc >> 16) #| acc #|} #|fn Hasher::consume4(self : Hasher, input : UInt) -> Unit { #| self.acc = rotl(self.acc + input * GPRIME3, 17) * GPRIME4 #|} #|fn Hasher::consume1(self : Hasher, input : Byte) -> Unit { #| self.acc = rotl(self.acc + input.to_uint() * GPRIME5, 11) * GPRIME1 #|} #|fn rotl(x : UInt, r : Int) -> UInt { #| (x << r) | (x >> (32 - r)) #|} #|fn endian32(input : Bytes, cur : Int) -> UInt { #| input[cur + 0].to_uint() | #| ( #| (input[cur + 1].to_uint() << 8) | #| (input[cur + 2].to_uint() << 16) | #| (input[cur + 3].to_uint() << 24) #| ) #|} #|pub impl Hash for String with hash_combine(self, hasher) { #| hasher.combine_string(self) #|} #|pub impl Hash for Int with hash(self) { #| let self = self.reinterpret_as_uint() #| let mut x = self ^ (self >> 17) #| x = x * 0xed5ad4bb #| x = x ^ (x >> 11) #| x = x * 0xac4c1b51 #| x = x ^ (x >> 15) #| x = x * 0x31848bab #| x = x ^ (x >> 14) #| x.reinterpret_as_int() #|} #|pub impl Hash for Int with hash_combine(self, hasher) { #| hasher.combine_int(self) #|} #|pub impl Hash for UInt with hash_combine(self, hasher) { #| hasher.combine_uint(self) #|} #|pub impl Hash for UInt64 with hash_combine(self, hasher) { #| hasher.combine_uint64(self) #|} #|pub impl[X : Hash] Hash for X? with hash_combine(self, hasher) { #| match self { #| None => hasher.combine_int(0) #| Some(x) => hasher..combine_int(1)..combine(x) #| } #|} #|pub impl[T : Hash, E : Hash] Hash for Result[T, E] with hash_combine( #| self, #| hasher, #|) { #| match self { #| Ok(x) => hasher..combine_int(0)..combine(x) #| Err(x) => hasher..combine_int(1)..combine(x) #| } #|} ), "int.mbt": ( #|pub fn Int::next_power_of_two(self : Int) -> Int { #| guard self >= 0 #| if self <= 1 { #| return 1 #| } #| let max_power_of_two = 1073741824 // 2^30 #| if self > max_power_of_two { #| return max_power_of_two #| } #| (2147483647 >> ((self - 1).clz() - 1)) + 1 #|} #|pub fn Int::min(self : Int, other : Int) -> Int { #| if self < other { #| self #| } else { #| other #| } #|} #|pub fn Int::max(self : Int, other : Int) -> Int { #| if self > other { #| self #| } else { #| other #| } #|} #|pub fn Int::clamp(self : Int, min~ : Int, max~ : Int) -> Int { #| guard min <= max #| if self < min { #| min #| } else if self > max { #| max #| } else { #| self #| } #|} #|pub fn Int::is_leading_surrogate(self : Int) -> Bool { #| 0xD800 <= self && self <= 0xDBFF #|} #|pub fn Int::is_trailing_surrogate(self : Int) -> Bool { #| 0xDC00 <= self && self <= 0xDFFF #|} #|pub fn Int::is_surrogate(self : Int) -> Bool { #| 0xD800 <= self && self <= 0xDFFF #|} ), "int64_js.mbt": ( #|priv struct MyInt64 { #| hi : Int #| lo : Int #|} #|fn MyInt64::to_int64(self : MyInt64) -> Int64 = "%identity" #|fn MyInt64::from_int64(value : Int64) -> MyInt64 = "%identity" #|impl Neg for MyInt64 with op_neg(self : MyInt64) -> MyInt64 { #| if self.lo == 0 { #| { hi: self.hi.lnot() + 1, lo: 0 } #| } else { #| { hi: self.hi.lnot(), lo: self.lo.lnot() + 1 } #| } #|} #|fn MyInt64::add_hi_lo(self : MyInt64, bhi : Int, blo : Int) -> MyInt64 { #| let { hi: ahi, lo: alo } = self #| let lo = alo + blo #| let s = lo >> 31 #| let as_ = alo >> 31 #| let bs = blo >> 31 #| let c = ((as_ & bs) | (s.lnot() & (as_ ^ bs))) & 1 #| let hi = ahi + bhi + c #| { hi, lo } #|} #|impl Add for MyInt64 with op_add(self : MyInt64, other : MyInt64) -> MyInt64 { #| self.add_hi_lo(other.hi, other.lo) #|} #|impl Sub for MyInt64 with op_sub(self : MyInt64, other : MyInt64) -> MyInt64 { #| if other.lo == 0 { #| { hi: self.hi - other.hi, lo: self.lo } #| } else { #| self.add_hi_lo(other.hi.lnot(), other.lo.lnot() + 1) #| } #|} #|impl Mul for MyInt64 with op_mul(self : MyInt64, other : MyInt64) -> MyInt64 { #| let { hi: ahi, lo: alo } = self #| let { hi: bhi, lo: blo } = other #| let ahi = ahi.reinterpret_as_uint() #| let alo = alo.reinterpret_as_uint() #| let bhi = bhi.reinterpret_as_uint() #| let blo = blo.reinterpret_as_uint() #| let a48 = ahi >> 16 #| let a32 = ahi & 0xffff #| let a16 = alo >> 16 #| let a00 = alo & 0xffff #| let b48 = bhi >> 16 #| let b32 = bhi & 0xffff #| let b16 = blo >> 16 #| let b00 = blo & 0xffff #| let c00 = a00 * b00 #| let c16 = c00 >> 16 #| let c00 = c00 & 0xffff #| let c16 = c16 + a16 * b00 #| let c32 = c16 >> 16 #| let c16 = c16 & 0xffff #| let c16 = c16 + a00 * b16 #| let c32 = c32 + (c16 >> 16) #| let c16 = c16 & 0xffff #| let c32 = c32 + a32 * b00 #| let c48 = c32 >> 16 #| let c32 = c32 & 0xffff #| let c32 = c32 + a16 * b16 #| let c48 = c48 + (c32 >> 16) #| let c32 = c32 & 0xffff #| let c32 = c32 + a00 * b32 #| let c48 = c48 + (c32 >> 16) #| let c32 = c32 & 0xffff #| let c48 = c48 + a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48 #| let c48 = c48 & 0xffff #| { #| hi: ((c48 << 16) | c32).reinterpret_as_int(), #| lo: ((c16 << 16) | c00).reinterpret_as_int(), #| } #|} #|priv struct Int64WasmHelper { #| div_s : (Int, Int, Int, Int) -> Int #| div_u : (Int, Int, Int, Int) -> Int #| rem_s : (Int, Int, Int, Int) -> Int #| rem_u : (Int, Int, Int, Int) -> Int #| get_high : () -> Int #|} #|extern "js" fn get_int64_wasm_helper() -> Int64WasmHelper = #| #|function f() { #| #| if (f._exports) return f._exports; #| #| return f._exports = new WebAssembly.Instance(new WebAssembly.Module(new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 1, 13, 2, 96, 0, 1, 127, 96, 4, 127, 127, 127, 127, 1, 127, 3, 7, 6, 0, 1, 1, 1, 1, 1, 6, 6, 1, 127, 1, 65, 0, 11, 7, 50, 6, 3, 109, 117, 108, 0, 1, 5, 100, 105, 118, 95, 115, 0, 2, 5, 100, 105, 118, 95, 117, 0, 3, 5, 114, 101, 109, 95, 115, 0, 4, 5, 114, 101, 109, 95, 117, 0, 5, 8, 103, 101, 116, 95, 104, 105, 103, 104, 0, 0, 10, 191, 1, 6, 4, 0, 35, 0, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 126, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 127, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 128, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 129, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11, 36, 1, 1, 126, 32, 0, 173, 32, 1, 173, 66, 32, 134, 132, 32, 2, 173, 32, 3, 173, 66, 32, 134, 132, 130, 34, 4, 66, 32, 135, 167, 36, 0, 32, 4, 167, 11])), {}).exports; #| #|} #|impl Div for MyInt64 with op_div(self : MyInt64, other : MyInt64) -> MyInt64 { #| let exports = get_int64_wasm_helper() #| let { hi: ahi, lo: alo } = self #| let { hi: bhi, lo: blo } = other #| let lo = (exports.div_s)(alo, ahi, blo, bhi) #| let hi = (exports.get_high)() #| { hi, lo } #|} #|fn MyInt64::div_u(self : MyInt64, other : MyInt64) -> MyInt64 { #| let exports = get_int64_wasm_helper() #| let { hi: ahi, lo: alo } = self #| let { hi: bhi, lo: blo } = other #| let lo = (exports.div_u)(alo, ahi, blo, bhi) #| let hi = (exports.get_high)() #| { hi, lo } #|} #|impl Mod for MyInt64 with op_mod(self : MyInt64, other : MyInt64) -> MyInt64 { #| let exports = get_int64_wasm_helper() #| let { hi: ahi, lo: alo } = self #| let { hi: bhi, lo: blo } = other #| let lo = (exports.rem_s)(alo, ahi, blo, bhi) #| let hi = (exports.get_high)() #| { hi, lo } #|} #|fn MyInt64::mod_u(self : MyInt64, other : MyInt64) -> MyInt64 { #| let exports = get_int64_wasm_helper() #| let { hi: ahi, lo: alo } = self #| let { hi: bhi, lo: blo } = other #| let lo = (exports.rem_u)(alo, ahi, blo, bhi) #| let hi = (exports.get_high)() #| { hi, lo } #|} #|fn MyInt64::lnot(self : MyInt64) -> MyInt64 { #| { hi: self.hi.lnot(), lo: self.lo.lnot() } #|} #|fn MyInt64::land(self : MyInt64, other : MyInt64) -> MyInt64 { #| { hi: self.hi & other.hi, lo: self.lo & other.lo } #|} #|fn MyInt64::lor(self : MyInt64, other : MyInt64) -> MyInt64 { #| { hi: self.hi | other.hi, lo: self.lo | other.lo } #|} #|fn MyInt64::lxor(self : MyInt64, other : MyInt64) -> MyInt64 { #| { hi: self.hi ^ other.hi, lo: self.lo ^ other.lo } #|} #|fn MyInt64::lsl(self : MyInt64, shift : Int) -> MyInt64 { #| let shift = shift & 63 #| if shift == 0 { #| self #| } else if shift < 32 { #| let { hi, lo } = self #| let hi = hi.reinterpret_as_uint() #| let lo = lo.reinterpret_as_uint() #| let hi = (hi << shift) | (lo >> (32 - shift)) #| let lo = lo << shift #| { hi: hi.reinterpret_as_int(), lo: lo.reinterpret_as_int() } #| } else { #| { hi: self.lo << (shift - 32), lo: 0 } #| } #|} #|fn MyInt64::lsr(self : MyInt64, shift : Int) -> MyInt64 { #| let shift = shift & 63 #| if shift == 0 { #| self #| } else if shift < 32 { #| { #| hi: (self.hi.reinterpret_as_uint() >> shift).reinterpret_as_int(), #| lo: (self.lo.reinterpret_as_uint() >> shift).reinterpret_as_int() | #| (self.hi << (32 - shift)), #| } #| } else { #| { #| hi: 0, #| lo: (self.hi.reinterpret_as_uint() >> (shift - 32)).reinterpret_as_int(), #| } #| } #|} #|fn MyInt64::asr(self : MyInt64, shift : Int) -> MyInt64 { #| let shift = shift & 63 #| if shift == 0 { #| self #| } else if shift < 32 { #| { #| hi: self.hi >> shift, #| lo: (self.lo.reinterpret_as_uint() >> shift).reinterpret_as_int() | #| (self.hi << (32 - shift)), #| } #| } else { #| { hi: self.hi >> 31, lo: self.hi >> (shift - 32) } #| } #|} #|fn MyInt64::clz(self : MyInt64) -> Int { #| if self.hi != 0 { #| self.hi.clz() #| } else { #| 32 + self.lo.clz() #| } #|} #|fn MyInt64::ctz(self : MyInt64) -> Int { #| if self.lo != 0 { #| self.lo.ctz() #| } else { #| 32 + self.hi.ctz() #| } #|} #|fn MyInt64::popcnt(self : MyInt64) -> Int { #| self.hi.popcnt() + self.lo.popcnt() #|} #|impl Eq for MyInt64 with op_equal(self : MyInt64, other : MyInt64) -> Bool { #| self.hi == other.hi && self.lo == other.lo #|} #|extern "js" fn MyInt64::compare(self : MyInt64, other : MyInt64) -> Int = #| #|(a, b) => { #| #| const ahi = a.hi; #| #| const bhi = b.hi; #| #| if (ahi < bhi) { #| #| return -1; #| #| } #| #| if (ahi > bhi) { #| #| return 1; #| #| } #| #| const alo = a.lo >>> 0; #| #| const blo = b.lo >>> 0; #| #| if (alo < blo) { #| #| return -1; #| #| } #| #| if (alo > blo) { #| #| return 1; #| #| } #| #| return 0; #| #|} #|extern "js" fn MyInt64::compare_u(self : MyInt64, other : MyInt64) -> Int = #| #|(a, b) => { #| #| const ahi = a.hi >>> 0; #| #| const bhi = b.hi >>> 0; #| #| if (ahi < bhi) { #| #| return -1; #| #| } #| #| if (ahi > bhi) { #| #| return 1; #| #| } #| #| const alo = a.lo >>> 0; #| #| const blo = b.lo >>> 0; #| #| if (alo < blo) { #| #| return -1; #| #| } #| #| if (alo > blo) { #| #| return 1; #| #| } #| #| return 0; #| #|} #|fn MyInt64::from_int(value : Int) -> MyInt64 { #| { hi: (value >> 31) & -1, lo: value | 0 } #|} #|fn MyInt64::to_int(self : MyInt64) -> Int { #| self.lo #|} #|fn MyInt64::to_uint(self : MyInt64) -> UInt { #| self.lo.reinterpret_as_uint() #|} #|fn MyInt64::extend_i32_u(value : Int) -> MyInt64 { #| { hi: 0, lo: value } #|} #|extern "js" fn MyInt64::reinterpret_as_double(self : MyInt64) -> Double = #| #|function f(a) { #| #| let view = f._view; #| #| if (view === undefined) { #| #| view = f._view = new DataView(new ArrayBuffer(8)); #| #| } #| #| view.setUint32(0, a.hi); #| #| view.setUint32(4, a.lo); #| #| return view.getFloat64(0); #| #|} #|extern "js" fn MyInt64::reinterpret_double(value : Double) -> MyInt64 = #| #|function f(a) { #| #| let view = f._view; #| #| if (view === undefined) { #| #| view = f._view = new DataView(new ArrayBuffer(8)); #| #| } #| #| view.setFloat64(0, a); #| #| const hi = view.getInt32(0); #| #| const lo = view.getInt32(4); #| #| return { hi, lo }; #| #|} #|extern "js" fn MyInt64::trunc_double_u(value : Double) -> MyInt64 = #| #|(a) => { #| #| let hi = (a * (1 / 0x100000000)) | 0; #| #| let lo = a >>> 0; #| #| return { hi, lo }; #| #|} #|extern "js" fn MyInt64::convert_to_double_u(self : MyInt64) -> Double = #| #|(a) => (a.hi >>> 0) * 4294967296.0 + (a.lo >>> 0) #|extern "js" fn MyInt64::convert_to_double(self : MyInt64) -> Double = #| #|(a) => a.hi * 4294967296.0 + (a.lo >>> 0) #|pub impl Neg for Int64 with op_neg(self : Int64) -> Int64 { #| (-MyInt64::from_int64(self)).to_int64() #|} #|pub impl Add for Int64 with op_add(self : Int64, other : Int64) -> Int64 { #| MyInt64::from_int64(self).op_add(MyInt64::from_int64(other)).to_int64() #|} #|pub impl Sub for Int64 with op_sub(self : Int64, other : Int64) -> Int64 { #| MyInt64::from_int64(self).op_sub(MyInt64::from_int64(other)).to_int64() #|} #|pub impl Mul for Int64 with op_mul(self : Int64, other : Int64) -> Int64 { #| MyInt64::from_int64(self).op_mul(MyInt64::from_int64(other)).to_int64() #|} #|pub impl Div for Int64 with op_div(self : Int64, other : Int64) -> Int64 { #| MyInt64::from_int64(self).op_div(MyInt64::from_int64(other)).to_int64() #|} #|pub impl Mod for Int64 with op_mod(self : Int64, other : Int64) -> Int64 { #| MyInt64::from_int64(self).op_mod(MyInt64::from_int64(other)).to_int64() #|} #|pub fn Int64::lnot(self : Int64) -> Int64 { #| MyInt64::from_int64(self).lnot().to_int64() #|} #|pub impl BitAnd for Int64 with land(self : Int64, other : Int64) -> Int64 { #| MyInt64::from_int64(self).land(MyInt64::from_int64(other)).to_int64() #|} #|pub impl BitOr for Int64 with lor(self : Int64, other : Int64) -> Int64 { #| MyInt64::from_int64(self).lor(MyInt64::from_int64(other)).to_int64() #|} #|pub impl BitXOr for Int64 with lxor(self : Int64, other : Int64) -> Int64 { #| MyInt64::from_int64(self).lxor(MyInt64::from_int64(other)).to_int64() #|} #|#deprecated("Use infix operator `<<` instead") #|#coverage.skip #|pub fn Int64::lsl(self : Int64, other : Int) -> Int64 { #| MyInt64::from_int64(self).lsl(other).to_int64() #|} #|#deprecated("Use infix operator `<<` instead") #|#coverage.skip #|pub fn Int64::shl(self : Int64, other : Int) -> Int64 { #| MyInt64::from_int64(self).lsl(other).to_int64() #|} #|#deprecated("Use UInt64 type and infix operator `>>` instead") #|#coverage.skip #|pub fn Int64::lsr(self : Int64, other : Int) -> Int64 { #| MyInt64::from_int64(self).lsr(other).to_int64() #|} #|#deprecated("Use infix operator `>>` instead") #|#coverage.skip #|pub fn Int64::shr(self : Int64, other : Int) -> Int64 { #| MyInt64::from_int64(self).asr(other).to_int64() #|} #|#deprecated("Use infix operator `>>` instead") #|#coverage.skip #|pub fn Int64::asr(self : Int64, other : Int) -> Int64 { #| MyInt64::from_int64(self).asr(other).to_int64() #|} #|pub impl Shr for Int64 with op_shr(self : Int64, other : Int) -> Int64 { #| MyInt64::from_int64(self).asr(other).to_int64() #|} #|pub impl Shl for Int64 with op_shl(self : Int64, other : Int) -> Int64 { #| MyInt64::from_int64(self).lsl(other).to_int64() #|} #|pub fn Int64::ctz(self : Int64) -> Int { #| MyInt64::from_int64(self).ctz() #|} #|pub fn Int64::clz(self : Int64) -> Int { #| MyInt64::from_int64(self).clz() #|} #|pub fn Int64::popcnt(self : Int64) -> Int { #| MyInt64::from_int64(self).popcnt() #|} #|pub impl Eq for Int64 with op_equal(self : Int64, other : Int64) -> Bool { #| MyInt64::from_int64(self) == MyInt64::from_int64(other) #|} #|pub impl Compare for Int64 with compare(self : Int64, other : Int64) -> Int { #| MyInt64::compare(MyInt64::from_int64(self), MyInt64::from_int64(other)) #|} #|pub impl Default for Int64 with default() { #| 0L #|} #|pub fn Int64::to_int(self : Int64) -> Int { #| MyInt64::from_int64(self).to_int() #|} #|pub fn Int64::to_double(self : Int64) -> Double { #| Double::convert_int64(self) #|} #|pub fn Int64::to_byte(self : Int64) -> Byte { #| MyInt64::from_int64(self).to_int().to_byte() #|} #|pub fn Int64::to_int16(self : Int64) -> Int16 { #| MyInt64::from_int64(self).to_int().to_int16() #|} #|pub fn Int64::to_uint16(self : Int64) -> UInt16 { #| MyInt64::from_int64(self).to_int().to_uint16() #|} #|pub fn UInt64::extend_uint(value : UInt) -> UInt64 { #| MyInt64::extend_i32_u(value.reinterpret_as_int()).to_uint64() #|} #|pub fn Int64::reinterpret_as_double(self : Int64) -> Double { #| MyInt64::reinterpret_as_double(MyInt64::from_int64(self)) #|} #|pub fn UInt64::reinterpret_as_double(self : UInt64) -> Double { #| MyInt64::reinterpret_as_double(MyInt64::from_uint64(self)) #|} #|pub fn Int::to_int64(self : Int) -> Int64 { #| MyInt64::from_int(self).to_int64() #|} #|pub fn Int16::to_int64(self : Int16) -> Int64 { #| MyInt64::from_int(self.to_int()).to_int64() #|} #|pub fn UInt16::to_int64(self : UInt16) -> Int64 { #| MyInt64::from_int(self.to_int()).to_int64() #|} #|#deprecated("Use `reinterpret_as_int64` instead") #|#coverage.skip #|pub fn Double::reinterpret_as_i64(self : Double) -> Int64 { #| MyInt64::reinterpret_double(self).to_int64() #|} #|pub fn Double::reinterpret_as_int64(self : Double) -> Int64 { #| MyInt64::reinterpret_double(self).to_int64() #|} #|#deprecated("Use `reinterpret_as_uint64` instead") #|#coverage.skip #|pub fn Double::reinterpret_as_u64(self : Double) -> UInt64 { #| MyInt64::reinterpret_double(self).to_uint64() #|} #|pub fn Double::reinterpret_as_uint64(self : Double) -> UInt64 { #| MyInt64::reinterpret_double(self).to_uint64() #|} #|pub fn Double::convert_uint64(value : UInt64) -> Double { #| MyInt64::convert_to_double_u(MyInt64::from_uint64(value)) #|} #|fn Double::convert_int64(value : Int64) -> Double { #| MyInt64::convert_to_double(MyInt64::from_int64(value)) #|} #|fn MyInt64::to_uint64(self : MyInt64) -> UInt64 = "%identity" #|fn MyInt64::from_uint64(value : UInt64) -> MyInt64 = "%identity" #|#deprecated("Use `reinterpret_as_uint64` instead") #|#coverage.skip #|pub fn Int64::to_uint64(self : Int64) -> UInt64 = "%identity" #|pub fn Int64::reinterpret_as_uint64(self : Int64) -> UInt64 = "%identity" #|pub impl Add for UInt64 with op_add(self : UInt64, other : UInt64) -> UInt64 { #| MyInt64::from_uint64(self).op_add(MyInt64::from_uint64(other)).to_uint64() #|} #|pub impl Sub for UInt64 with op_sub(self : UInt64, other : UInt64) -> UInt64 { #| MyInt64::from_uint64(self).op_sub(MyInt64::from_uint64(other)).to_uint64() #|} #|pub impl Mul for UInt64 with op_mul(self : UInt64, other : UInt64) -> UInt64 { #| MyInt64::from_uint64(self).op_mul(MyInt64::from_uint64(other)).to_uint64() #|} #|pub impl Div for UInt64 with op_div(self : UInt64, other : UInt64) -> UInt64 { #| MyInt64::from_uint64(self).div_u(MyInt64::from_uint64(other)).to_uint64() #|} #|pub impl Mod for UInt64 with op_mod(self : UInt64, other : UInt64) -> UInt64 { #| MyInt64::from_uint64(self).mod_u(MyInt64::from_uint64(other)).to_uint64() #|} #|#deprecated("Use reinterpret_as_int64 instead") #|#coverage.skip #|pub fn UInt64::to_int64(self : UInt64) -> Int64 = "%identity" #|pub fn UInt64::reinterpret_as_int64(self : UInt64) -> Int64 = "%identity" #|pub fn UInt64::to_uint(self : UInt64) -> UInt { #| MyInt64::from_uint64(self).to_uint() #|} #|pub fn UInt64::to_int(self : UInt64) -> Int { #| MyInt64::from_uint64(self).to_int() #|} #|pub fn UInt64::to_double(self : UInt64) -> Double { #| Double::convert_uint64(self) #|} #|pub impl Compare for UInt64 with compare(self : UInt64, other : UInt64) -> Int { #| MyInt64::from_uint64(self).compare_u(MyInt64::from_uint64(other)) #|} #|pub impl Eq for UInt64 with op_equal(self : UInt64, other : UInt64) -> Bool { #| MyInt64::from_uint64(self).op_equal(MyInt64::from_uint64(other)) #|} #|pub fn UInt64::trunc_double(value : Double) -> UInt64 { #| MyInt64::trunc_double_u(value).to_uint64() #|} #|pub impl BitAnd for UInt64 with land(self : UInt64, other : UInt64) -> UInt64 { #| MyInt64::land(MyInt64::from_uint64(self), MyInt64::from_uint64(other)).to_uint64() #|} #|pub impl BitOr for UInt64 with lor(self : UInt64, other : UInt64) -> UInt64 { #| MyInt64::lor(MyInt64::from_uint64(self), MyInt64::from_uint64(other)).to_uint64() #|} #|pub impl BitXOr for UInt64 with lxor(self : UInt64, other : UInt64) -> UInt64 { #| MyInt64::lxor(MyInt64::from_uint64(self), MyInt64::from_uint64(other)).to_uint64() #|} #|pub fn UInt64::lnot(self : UInt64) -> UInt64 { #| MyInt64::lnot(MyInt64::from_uint64(self)).to_uint64() #|} #|#deprecated("Use infix operator `<<` instead") #|#coverage.skip #|pub fn UInt64::lsl(self : UInt64, shift : Int) -> UInt64 { #| MyInt64::lsl(MyInt64::from_uint64(self), shift).to_uint64() #|} #|#deprecated("Use infix operator `<<` instead") #|#coverage.skip #|pub fn UInt64::lsr(self : UInt64, shift : Int) -> UInt64 { #| MyInt64::lsr(MyInt64::from_uint64(self), shift).to_uint64() #|} #|#deprecated("Use infix operator `>>` instead") #|#coverage.skip #|pub fn UInt64::shl(self : UInt64, shift : Int) -> UInt64 { #| MyInt64::lsl(MyInt64::from_uint64(self), shift).to_uint64() #|} #|#deprecated("Use infix operator `>>` instead") #|#coverage.skip #|pub fn UInt64::shr(self : UInt64, shift : Int) -> UInt64 { #| MyInt64::lsr(MyInt64::from_uint64(self), shift).to_uint64() #|} #|pub impl Shl for UInt64 with op_shl(self : UInt64, shift : Int) -> UInt64 { #| MyInt64::lsl(MyInt64::from_uint64(self), shift).to_uint64() #|} #|pub impl Shr for UInt64 with op_shr(self : UInt64, shift : Int) -> UInt64 { #| MyInt64::lsr(MyInt64::from_uint64(self), shift).to_uint64() #|} #|pub fn UInt64::clz(self : UInt64) -> Int { #| MyInt64::from_uint64(self).clz() #|} #|pub fn UInt64::ctz(self : UInt64) -> Int { #| MyInt64::from_uint64(self).ctz() #|} #|pub fn UInt64::popcnt(self : UInt64) -> Int { #| MyInt64::from_uint64(self).popcnt() #|} #|pub fn Int64::to_float(self : Int64) -> Float { #| self.to_double().to_float() #|} #|pub fn UInt64::to_float(self : UInt64) -> Float { #| Double::convert_uint64(self).to_float() #|} ), "int64_nonjs.mbt": ( #|pub impl Neg for Int64 with op_neg(self : Int64) -> Int64 = "%i64_neg" #|pub impl Add for Int64 with op_add(self, other) = "%i64_add" #|pub impl Sub for Int64 with op_sub(self, other) = "%i64_sub" #|pub impl Mul for Int64 with op_mul(self, other) = "%i64_mul" #|pub impl Div for Int64 with op_div(self, other) = "%i64_div" #|pub impl Mod for Int64 with op_mod(self, other) = "%i64_mod" #|pub fn Int64::lnot(self : Int64) -> Int64 = "%i64_lnot" #|pub impl BitAnd for Int64 with land(self, other) = "%i64_land" #|pub impl BitOr for Int64 with lor(self, other) = "%i64_lor" #|pub impl BitXOr for Int64 with lxor(self, other) = "%i64_lxor" #|#deprecated("Use infix operator `<<` instead") #|#coverage.skip #|pub fn Int64::lsl(self : Int64, other : Int) -> Int64 = "%i64_shl" #|#deprecated("Use infix operator `<<` instead") #|#coverage.skip #|pub fn Int64::shl(self : Int64, other : Int) -> Int64 = "%i64_shl" #|#deprecated("Use UInt64 type and infix operator `>>` instead") #|#coverage.skip #|pub fn Int64::lsr(self : Int64, other : Int) -> Int64 = "%u64.shr" #|#deprecated("Use infix operator `>>` instead") #|#coverage.skip #|pub fn Int64::asr(self : Int64, other : Int) -> Int64 = "%i64_shr" #|#deprecated("Use infix operator `>>` instead") #|#coverage.skip #|pub fn Int64::shr(self : Int64, other : Int) -> Int64 = "%i64_shr" #|pub impl Shl for Int64 with op_shl(self, other) = "%i64_shl" #|pub impl Shr for Int64 with op_shr(self, other) = "%i64_shr" #|pub fn Int64::ctz(self : Int64) -> Int = "%i64_ctz" #|pub fn Int64::clz(self : Int64) -> Int = "%i64_clz" #|pub fn Int64::popcnt(self : Int64) -> Int = "%i64_popcnt" #|pub impl Eq for Int64 with op_equal(self : Int64, other : Int64) -> Bool = "%i64_eq" #|pub impl Compare for Int64 with compare(self, other) = "%i64_compare" #|pub impl Default for Int64 with default() = "%i64_default" #|pub fn Int64::to_int(self : Int64) -> Int = "%i64_to_i32" #|pub fn Int64::to_double(self : Int64) -> Double = "%i64_to_f64" #|pub fn Int64::reinterpret_as_double(self : Int64) -> Double = "%i64_to_f64_reinterpret" #|pub fn UInt64::reinterpret_as_double(self : UInt64) -> Double = "%i64_to_f64_reinterpret" #|pub fn Int64::to_byte(self : Int64) -> Byte = "%i64_to_byte" #|pub fn Int64::to_int16(self : Int64) -> Int16 = "%i64_to_i16" #|pub fn Int64::to_uint16(self : Int64) -> UInt16 = "%i64_to_u16" #|pub fn UInt64::trunc_double(val : Double) -> UInt64 = "%f64.to_u64" #|pub fn Int64::to_float(self : Int64) -> Float = "%i64.to_f32" #|pub fn UInt64::extend_uint(val : UInt) -> UInt64 = "%u32.to_u64" #|pub fn Int::to_int64(self : Int) -> Int64 = "%i32_to_i64" #|pub fn Int16::to_int64(self : Int16) -> Int64 = "%i16_to_i64" #|pub fn UInt16::to_int64(self : UInt16) -> Int64 = "%u16_to_i64" #|#deprecated("Use `reinterpret_as_int64` instead") #|#coverage.skip #|pub fn Double::reinterpret_as_i64(self : Double) -> Int64 = "%f64_to_i64_reinterpret" #|pub fn Double::reinterpret_as_int64(self : Double) -> Int64 = "%f64_to_i64_reinterpret" #|#deprecated("Use `reinterpret_as_uint64` instead") #|#coverage.skip #|pub fn Double::reinterpret_as_u64(self : Double) -> UInt64 = "%f64_to_i64_reinterpret" #|pub fn Double::reinterpret_as_uint64(self : Double) -> UInt64 = "%f64_to_i64_reinterpret" #|pub fn Double::convert_uint64(val : UInt64) -> Double = "%u64.to_f64" #|#deprecated("Use `reinterpret_as_uint64` instead") #|#coverage.skip #|pub fn Int64::to_uint64(self : Int64) -> UInt64 = "%i64.to_u64_reinterpret" #|pub fn Int64::reinterpret_as_uint64(self : Int64) -> UInt64 = "%i64.to_u64_reinterpret" #|#deprecated("Use `reinterpret_as_int64` instead") #|#coverage.skip #|pub fn UInt64::to_int64(self : UInt64) -> Int64 = "%u64.to_i64_reinterpret" #|pub fn UInt64::reinterpret_as_int64(self : UInt64) -> Int64 = "%u64.to_i64_reinterpret" #|pub fn UInt64::to_uint(self : UInt64) -> UInt = "%u64.to_u32" #|pub fn UInt64::to_int(self : UInt64) -> Int = "%u64.to_i32" #|pub fn UInt64::to_double(self : UInt64) -> Double = "%u64.to_f64" #|pub impl Add for UInt64 with op_add(self, other) = "%u64.add" #|pub impl Sub for UInt64 with op_sub(self, other) = "%u64.sub" #|pub impl Mul for UInt64 with op_mul(self, other) = "%u64.mul" #|pub impl Div for UInt64 with op_div(self, other) = "%u64.div" #|pub impl Mod for UInt64 with op_mod(self, other) = "%u64.mod" #|pub impl Compare for UInt64 with compare(self, other) = "%u64.compare" #|pub impl Eq for UInt64 with op_equal(self : UInt64, other : UInt64) -> Bool = "%u64.eq" #|pub impl BitAnd for UInt64 with land(self, other) = "%u64.bitand" #|pub impl BitOr for UInt64 with lor(self, other) = "%u64.bitor" #|pub impl BitXOr for UInt64 with lxor(self, other) = "%u64.bitxor" #|pub fn UInt64::lnot(self : UInt64) -> UInt64 = "%u64.bitnot" #|#deprecated("Use infix operator `<<` instead") #|#coverage.skip #|pub fn UInt64::lsl(self : UInt64, shift : Int) -> UInt64 = "%u64.shl" #|#deprecated("Use infix operator `<<` instead") #|#coverage.skip #|pub fn UInt64::shl(self : UInt64, shift : Int) -> UInt64 = "%u64.shl" #|#deprecated("Use infix operator `>>` instead") #|#coverage.skip #|pub fn UInt64::shr(self : UInt64, shift : Int) -> UInt64 = "%u64.shr" #|#deprecated("Use infix operator `>>` instead") #|#coverage.skip #|pub fn UInt64::lsr(self : UInt64, shift : Int) -> UInt64 = "%u64.shr" #|pub impl Shl for UInt64 with op_shl(self, shift) = "%u64.shl" #|pub impl Shr for UInt64 with op_shr(self, shift) = "%u64.shr" #|pub fn UInt64::clz(self : UInt64) -> Int = "%u64.clz" #|pub fn UInt64::ctz(self : UInt64) -> Int = "%u64.ctz" #|pub fn UInt64::popcnt(self : UInt64) -> Int = "%u64.popcnt" #|pub fn UInt64::to_float(self : UInt64) -> Float = "%u64.to_f32" ), "intrinsics.mbt": ( #|pub fn[T] ignore(t : T) -> Unit = "%ignore" #|pub fn[T] physical_equal(a : T, b : T) -> Bool = "%refeq" #|pub fnalias @abort.abort #|pub fn[T] panic() -> T = "%panic" #|pub fn not(x : Bool) -> Bool = "%bool_not" #|pub impl Eq for Bool with op_equal(self : Bool, other : Bool) -> Bool = "%bool_eq" #|#deprecated("Use `compare` instead") #|#coverage.skip #|pub fn Bool::op_compare(self : Bool, other : Bool) -> Int = "%bool_compare" #|pub impl Compare for Bool with compare(self, other) = "%bool_compare" #|pub impl Default for Bool with default() = "%bool_default" #|pub impl Neg for Int with op_neg(self) = "%i32_neg" #|pub impl Add for Int with op_add(self, other) = "%i32_add" #|pub impl Sub for Int with op_sub(self, other) = "%i32_sub" #|pub impl Mul for Int with op_mul(self, other) = "%i32_mul" #|pub impl Div for Int with op_div(self, other) = "%i32_div" #|pub impl Mod for Int with op_mod(self, other) = "%i32_mod" #|pub fn Int::lnot(self : Int) -> Int = "%i32_lnot" #|pub fn Int::land(self : Int, other : Int) -> Int = "%i32_land" #|pub fn Int::lor(self : Int, other : Int) -> Int = "%i32_lor" #|pub fn Int::lxor(self : Int, other : Int) -> Int = "%i32_lxor" #|pub impl Shl for Int with op_shl(self, other) = "%i32_shl" #|pub impl Shr for Int with op_shr(self, other) = "%i32_shr" #|#deprecated("Use infix operator `<<` instead") #|#coverage.skip #|pub fn Int::lsl(self : Int, other : Int) -> Int = "%i32_shl" #|#deprecated("Use infix operator `<<` instead") #|#coverage.skip #|pub fn Int::shl(self : Int, other : Int) -> Int = "%i32_shl" #|#deprecated("Use UInt type and infix operator `>>` instead") #|#coverage.skip #|pub fn Int::lsr(self : Int, other : Int) -> Int { #| (self.reinterpret_as_uint() >> other).reinterpret_as_int() #|} #|#deprecated("Use infix operator `>>` instead") #|#coverage.skip #|pub fn Int::asr(self : Int, other : Int) -> Int = "%i32_shr" #|#deprecated("Use infix operator `>>` instead") #|#coverage.skip #|pub fn Int::shr(self : Int, other : Int) -> Int = "%i32_shr" #|pub fn Int::ctz(self : Int) -> Int = "%i32_ctz" #|pub fn Int::clz(self : Int) -> Int = "%i32_clz" #|pub fn Int::popcnt(self : Int) -> Int = "%i32_popcnt" #|pub impl Eq for Int with op_equal(self : Int, other : Int) -> Bool = "%i32_eq" #|pub impl Compare for Int with compare(self, other) = "%i32_compare" #|pub fn Int::is_pos(self : Int) -> Bool = "%i32_is_pos" #|pub fn Int::is_neg(self : Int) -> Bool = "%i32_is_neg" #|pub fn Int::is_non_pos(self : Int) -> Bool = "%i32_is_non_pos" #|pub fn Int::is_non_neg(self : Int) -> Bool = "%i32_is_non_neg" #|pub impl Default for Int with default() = "%i32_default" #|pub fn Int::to_double(self : Int) -> Double = "%i32_to_f64" #|pub fn UInt::trunc_double(val : Double) -> UInt = "%f64.to_u32" #|pub fn Int::reinterpret_as_uint(self : Int) -> UInt = "%i32.to_u32_reinterpret" #|#deprecated("Use `reinterpret_as_uint` instead") #|#coverage.skip #|pub fn Int::to_uint(self : Int) -> UInt = "%i32.to_u32_reinterpret" #|pub fn Int::to_uint64(self : Int) -> UInt64 { #| self.to_int64().reinterpret_as_uint64() #|} #|pub impl Neg for Double with op_neg(self) = "%f64_neg" #|pub impl Add for Double with op_add(self, other) = "%f64_add" #|pub impl Sub for Double with op_sub(self, other) = "%f64_sub" #|pub impl Mul for Double with op_mul(self, other) = "%f64_mul" #|pub impl Div for Double with op_div(self, other) = "%f64_div" #|pub fn Double::sqrt(self : Double) -> Double = "%f64_sqrt" #|pub impl Eq for Double with op_equal(self : Double, other : Double) -> Bool = "%f64_eq" #|pub fn Double::op_neq(self : Double, other : Double) -> Bool = "%f64_ne" #|pub impl Compare for Double with compare(self, other) = "%f64_compare" #|pub impl Default for Double with default() = "%f64_default" #|pub fn Double::convert_uint(val : UInt) -> Double = "%u32.to_f64" #|pub fn Char::to_int(self : Char) -> Int = "%char_to_int" #|pub fn Char::to_uint(self : Char) -> UInt { #| self.to_int().reinterpret_as_uint() #|} #|#deprecated("Use `Int::unsafe_to_char` instead, and use `Int::to_char` for safe conversion") #|pub fn Char::from_int(val : Int) -> Char = "%char_from_int" #|pub impl Eq for Char with op_equal(self : Char, other : Char) -> Bool = "%char_eq" #|pub impl Compare for Char with compare(self, other) = "%char_compare" #|pub impl Default for Char with default() = "%char_default" #|pub fn Bytes::op_get(self : Bytes, idx : Int) -> Byte = "%bytes_get" #|#internal(unsafe, "Panic if index is out of bounds") #|pub fn Bytes::unsafe_get(self : Bytes, idx : Int) -> Byte = "%bytes.unsafe_get" #|pub fn Bytes::length(self : Bytes) -> Int = "%bytes_length" #|pub fn Bytes::make(len : Int, init : Byte) -> Bytes { #| if len < 0 { #| return [] #| } #| Bytes::unsafe_make(len, init) #|} #|fn Bytes::unsafe_make(len : Int, init : Byte) -> Bytes = "%bytes_make" #|pub fn Bytes::new(len : Int) -> Bytes { #| Bytes::make(len, b'\x00') #|} #|pub fn Int::to_byte(self : Int) -> Byte = "%i32_to_byte" #|pub fn Int::unsafe_to_char(self : Int) -> Char = "%char_from_int" #|pub fn Int::to_char(self : Int) -> Char? { #| if self is (0..=0xD7FF) || self is (0xE000..=0x10FFFF) { #| Some(self.unsafe_to_char()) #| } else { #| None #| } #|} #|pub fn UInt64::to_byte(self : UInt64) -> Byte { #| self.to_int().to_byte() #|} #|pub fn[T] FixedArray::op_get(self : FixedArray[T], idx : Int) -> T = "%fixedarray.get" #|#internal(unsafe, "Panic if index is out of bounds") #|pub fn[T] FixedArray::unsafe_get(self : FixedArray[T], idx : Int) -> T = "%fixedarray.unsafe_get" #|#internal(unsafe, "Panic if index is out of bounds") #|pub fn[T] FixedArray::unsafe_set( #| self : FixedArray[T], #| idx : Int, #| val : T, #|) -> Unit = "%fixedarray.unsafe_set" #|#intrinsic("%fixedarray.set") #|pub fn[T] FixedArray::op_set(self : FixedArray[T], idx : Int, val : T) -> Unit = "%fixedarray.set" #|pub fn[T] FixedArray::set(self : FixedArray[T], idx : Int, val : T) -> Unit = "%fixedarray.set" #|pub fn[T] FixedArray::length(self : FixedArray[T]) -> Int = "%fixedarray.length" #|pub fn[T] FixedArray::make(len : Int, init : T) -> FixedArray[T] = "%fixedarray.make" #|pub fn String::length(self : String) -> Int = "%string_length" #|#deprecated("use `length` instead") #|pub fn String::charcode_length(self : String) -> Int = "%string_length" #|pub fn String::op_get(self : String, idx : Int) -> Int = "%string_get" #|#internal(unsafe, "Panic if index is out of bounds.") #|pub fn String::unsafe_charcode_at(self : String, idx : Int) -> Int = "%string.unsafe_get" #|pub impl Add for String with op_add(self, other) = "%string_add" #|pub impl Eq for String with op_equal(self : String, other : String) -> Bool = "%string_eq" #|pub fn String::to_string(self : String) -> String = "%string_to_string" #|priv type UnsafeMaybeUninit[_] #|pub fn Byte::to_int(self : Byte) -> Int = "%byte_to_int" #|pub fn Byte::to_char(self : Byte) -> Char { #| self.to_int().unsafe_to_char() #|} #|pub fn Byte::to_int64(self : Byte) -> Int64 { #| self.to_int().to_int64() #|} #|pub fn UInt::reinterpret_as_int(self : UInt) -> Int = "%u32.to_i32_reinterpret" #|#deprecated("Use `reinterpret_as_int` instead") #|#coverage.skip #|pub fn UInt::to_int(self : UInt) -> Int = "%u32.to_i32_reinterpret" #|pub impl Add for UInt with op_add(self, other) = "%u32.add" #|pub impl Sub for UInt with op_sub(self, other) = "%u32.sub" #|pub impl Mul for UInt with op_mul(self, other) = "%u32.mul" #|pub impl Div for UInt with op_div(self, other) = "%u32.div" #|pub impl Mod for UInt with op_mod(self, other) = "%u32.mod" #|pub impl Eq for UInt with op_equal(self : UInt, other : UInt) -> Bool = "%u32.eq" #|pub fn UInt::op_neq(self : UInt, other : UInt) -> Bool = "%u32.ne" #|pub impl Compare for UInt with compare(self, other) = "%u32.compare" #|pub fn UInt::land(self : UInt, other : UInt) -> UInt = "%u32.bitand" #|pub fn UInt::lor(self : UInt, other : UInt) -> UInt = "%u32.bitor" #|pub fn UInt::lxor(self : UInt, other : UInt) -> UInt = "%u32.bitxor" #|pub fn UInt::lnot(self : UInt) -> UInt = "%u32.bitnot" #|#deprecated("Use infix operator `<<` instead") #|#coverage.skip #|pub fn UInt::lsl(self : UInt, shift : Int) -> UInt = "%u32.shl" #|#deprecated("Use infix operator `<<` instead") #|#coverage.skip #|pub fn UInt::shl(self : UInt, shift : Int) -> UInt = "%u32.shl" #|#deprecated("Use infix operator `>>` instead") #|#coverage.skip #|pub fn UInt::lsr(self : UInt, shift : Int) -> UInt = "%u32.shr" #|#deprecated("Use infix operator `>>` instead") #|#coverage.skip #|pub fn UInt::shr(self : UInt, shift : Int) -> UInt = "%u32.shr" #|pub impl Shl for UInt with op_shl(self, shift) = "%u32.shl" #|pub impl Shr for UInt with op_shr(self, shift) = "%u32.shr" #|pub fn UInt::clz(self : UInt) -> Int = "%u32.clz" #|pub fn UInt::ctz(self : UInt) -> Int = "%u32.ctz" #|pub fn UInt::popcnt(self : UInt) -> Int = "%u32.popcnt" #|pub fn UInt::to_uint64(self : UInt) -> UInt64 { #| UInt64::extend_uint(self) #|} #|pub fn UInt::to_byte(self : UInt) -> Byte { #| self.reinterpret_as_int().to_byte() #|} #|pub fn UInt::to_double(self : UInt) -> Double = "%u32.to_f64" #|pub impl Neg for Float with op_neg(self) = "%f32.neg" #|pub impl Add for Float with op_add(self, other) = "%f32.add" #|pub impl Sub for Float with op_sub(self, other) = "%f32.sub" #|pub impl Mul for Float with op_mul(self, other) = "%f32.mul" #|pub impl Div for Float with op_div(self, other) = "%f32.div" #|pub fn Float::sqrt(self : Float) -> Float = "%f32.sqrt" #|pub impl Eq for Float with op_equal(self : Float, other : Float) -> Bool = "%f32.eq" #|pub fn Float::op_neq(self : Float, other : Float) -> Bool = "%f32.ne" #|pub impl Compare for Float with compare(self, other) = "%f32.compare" #|pub fn Float::to_double(self : Float) -> Double = "%f32.to_f64" #|pub fn Float::reinterpret_as_int(self : Float) -> Int = "%f32.to_i32_reinterpret" #|pub fn Float::reinterpret_as_uint(self : Float) -> UInt = "%f32.to_i32_reinterpret" #|pub fn Int::to_float(self : Int) -> Float = "%i32.to_f32" #|pub fn Int::reinterpret_as_float(self : Int) -> Float = "%i32.to_f32_reinterpret" #|pub fn UInt::reinterpret_as_float(self : UInt) -> Float = "%i32.to_f32_reinterpret" #|pub fn Byte::to_float(self : Byte) -> Float = "%byte.to_f32" #|pub fn Byte::to_double(self : Byte) -> Double { #| self.to_int().to_double() #|} #|pub fn Double::to_float(self : Double) -> Float = "%f64.to_f32" #|pub fn UInt::to_float(self : UInt) -> Float = "%u32.to_f32" #|pub fn Int16::to_int(self : Int16) -> Int = "%i16_to_i32" #|pub fn Int16::to_byte(self : Int16) -> Byte = "%i16_to_byte" #|pub fn Int::to_int16(self : Int) -> Int16 = "%i32_to_i16" #|pub fn Byte::to_int16(self : Byte) -> Int16 = "%byte_to_i16" #|pub fn UInt16::to_int(self : UInt16) -> Int = "%u16_to_i32" #|pub fn UInt16::to_byte(self : UInt16) -> Byte = "%u16_to_byte" #|pub fn Int::to_uint16(self : Int) -> UInt16 = "%i32_to_u16" #|pub fn Byte::to_uint16(self : Byte) -> UInt16 = "%byte_to_u16" ), "iter.mbt": ( #|struct Iter[T](((T) -> IterResult) -> IterResult) #|pub fn[T] Iter::run(self : Iter[T], f : (T) -> IterResult) -> IterResult { #| self(f) #|} #|pub fn[T] Iter::just_run(self : Iter[T], f : (T) -> IterResult) -> Unit { #| self(f) |> ignore #|} #|pub(all) enum IterResult { #| IterEnd // false #| IterContinue // true #|} derive(Eq) #|pub impl[T : Show] Show for Iter[T] with output(self, logger) { #| logger.write_iter(self) #|} #|pub fn[T] Iter::each(self : Iter[T], f : (T) -> Unit raise?) -> Unit raise? { #| for a in self { #| f(a) #| } #|} #|pub fn[T] Iter::any(self : Iter[T], f : (T) -> Bool) -> Bool { #| self.run(k => if f(k) { IterEnd } else { IterContinue }) != IterContinue #|} #|pub fn[T] Iter::all(self : Iter[T], f : (T) -> Bool) -> Bool { #| self.run(k => if !f(k) { IterEnd } else { IterContinue }) == IterContinue #|} #|pub fn[T] Iter::eachi( #| self : Iter[T], #| f : (Int, T) -> Unit raise?, #|) -> Unit raise? { #| let mut i = 0 #| for a in self { #| f(i, a) #| i += 1 #| } #|} #|#intrinsic("%iter.reduce") #|#locals(f) #|pub fn[T, B] Iter::fold( #| self : Iter[T], #| init~ : B, #| f : (B, T) -> B raise?, #|) -> B raise? { #| let mut acc = init #| for a in self { #| acc = f(acc, a) #| } #| acc #|} #|pub fn[T] Iter::count(self : Iter[T]) -> Int { #| self.fold((acc, _) => acc + 1, init=0) #|} #|pub fn[T] Iter::new(f : ((T) -> IterResult) -> IterResult) -> Iter[T] { #| Iter(f) #|} #|pub fn[T] Iter::empty() -> Iter[T] { #| _ => IterContinue #|} #|pub fn[T] Iter::singleton(a : T) -> Iter[T] { #| yield_ => yield_(a) #|} #|#intrinsic("%iter.repeat") #|pub fn[T] Iter::repeat(a : T) -> Iter[T] { #| yield_ => loop yield_(a) { #| IterContinue => continue yield_(a) #| IterEnd => IterEnd #| } #|} #|pub fn Int::until( #| self : Int, #| end : Int, #| step? : Int = 1, #| inclusive? : Bool = false, #|) -> Iter[Int] { #| if step == 0 { #| return Iter::empty() #| } #| yield_ => { #| let mut i = self #| while (step > 0 && i < end) || #| (step < 0 && i > end) || #| (inclusive && i == end) { #| if yield_(i) == IterEnd { #| break IterEnd #| } #| let next = i + step #| if (step > 0 && next >= i) || (step < 0 && next <= i) { #| i = next #| } else { #| break IterContinue #| } #| } else { #| IterContinue #| } #| } #|} #|pub fn Int64::until( #| self : Int64, #| end : Int64, #| step? : Int64 = 1L, #| inclusive? : Bool = false, #|) -> Iter[Int64] { #| if step == 0 { #| return Iter::empty() #| } #| yield_ => { #| let mut i = self #| while (step > 0 && i < end) || #| (step < 0 && i > end) || #| (inclusive && i == end) { #| if yield_(i) == IterEnd { #| break IterEnd #| } #| let next = i + step #| if (step > 0 && next >= i) || (step < 0 && next <= i) { #| i = next #| } else { #| break IterContinue #| } #| } else { #| IterContinue #| } #| } #|} #|pub fn Float::until( #| self : Float, #| end : Float, #| step? : Float = 1.0, #| inclusive? : Bool = false, #|) -> Iter[Float] { #| if step == 0.0 { #| return Iter::empty() #| } #| yield_ => { #| let mut i = self #| while (step > 0.0 && i < end) || #| (step < 0.0 && i > end) || #| (inclusive && i == end) { #| if yield_(i) == IterEnd { #| break IterEnd #| } #| let next = i + step #| if (step > 0.0 && next >= i) || (step < 0.0 && next <= i) { #| i = next #| } else { #| break IterContinue #| } #| } else { #| IterContinue #| } #| } #|} #|pub fn Double::until( #| self : Double, #| end : Double, #| step? : Double = 1.0, #| inclusive? : Bool = false, #|) -> Iter[Double] { #| if step == 0.0 { #| return Iter::empty() #| } #| yield_ => { #| let mut i = self #| while (step > 0.0 && i < end) || #| (step < 0.0 && i > end) || #| (inclusive && i == end) { #| if yield_(i) == IterEnd { #| break IterEnd #| } #| let next = i + step #| if (step > 0.0 && next >= i) || (step < 0.0 && next <= i) { #| i = next #| } else { #| break IterContinue #| } #| } else { #| IterContinue #| } #| } #|} #|#intrinsic("%iter.filter") #|pub fn[T] Iter::filter(self : Iter[T], f : (T) -> Bool) -> Iter[T] { #| yield_ => self.run(a => if f(a) { yield_(a) } else { IterContinue }) #|} #|#intrinsic("%iter.map") #|pub fn[T, R] Iter::map(self : Iter[T], f : (T) -> R) -> Iter[R] { #| yield_ => self.run(a => yield_(f(a))) #|} #|pub fn[T, R] Iter::mapi(self : Iter[T], f : (Int, T) -> R) -> Iter[R] { #| yield_ => { #| let mut i = -1 #| self.run(a => { #| i = i + 1 #| yield_(f(i, a)) #| }) #| } #|} #|pub fn[A, B] Iter::filter_map(self : Iter[A], f : (A) -> B?) -> Iter[B] { #| yield_ => self.run(a => match f(a) { #| Some(b) => yield_(b) #| None => IterContinue #| }) #|} #|#deprecated("Use `Iter::filter_map` instead") #|pub fn[A, B] Iter::map_option(self : Iter[A], f : (A) -> B?) -> Iter[B] { #| self.filter_map(f) #|} #|#intrinsic("%iter.flat_map") #|pub fn[T, R] Iter::flat_map(self : Iter[T], f : (T) -> Iter[R]) -> Iter[R] { #| yield_ => self.run(x => f(x).run(yield_)) #|} #|pub fn[T] Iter::flatten(self : Iter[Iter[T]]) -> Iter[T] { #| yield_ => self.run(x => x.run(yield_)) #|} #|pub fn[T] Iter::tap(self : Iter[T], f : (T) -> Unit) -> Iter[T] { #| self.map(a => { #| f(a) #| a #| }) #|} #|#intrinsic("%iter.take") #|pub fn[T] Iter::take(self : Iter[T], n : Int) -> Iter[T] { #| yield_ => { #| let mut i = 0 #| let mut r = IterContinue #| self.just_run(a => if i < n { #| if yield_(a) == IterContinue { #| i = i + 1 #| IterContinue #| } else { #| r = IterEnd #| IterEnd #| } #| } else { #| IterEnd #| }) #| r #| } #|} #|pub fn[T] Iter::take_while(self : Iter[T], f : (T) -> Bool) -> Iter[T] { #| yield_ => { #| let mut r : IterResult = IterContinue #| self.just_run(a => if f(a) { #| if yield_(a) == IterContinue { #| IterContinue #| } else { #| r = IterEnd #| IterEnd #| } #| } else { #| IterEnd #| }) #| r #| } #|} #|pub fn[A, B] Iter::map_while(self : Iter[A], f : (A) -> B?) -> Iter[B] { #| yield_ => { #| let mut r : IterResult = IterContinue #| self.just_run(a => match f(a) { #| Some(b) => #| if yield_(b) == IterContinue { #| IterContinue #| } else { #| r = IterEnd #| IterEnd #| } #| None => IterEnd #| }) #| r #| } #|} #|pub fn[T] Iter::drop(self : Iter[T], n : Int) -> Iter[T] { #| yield_ => { #| let mut i = 0 #| self.run(a => if i < n { #| i = i + 1 #| IterContinue #| } else { #| yield_(a) #| }) #| } #|} #|pub fn[T] Iter::drop_while(self : Iter[T], f : (T) -> Bool) -> Iter[T] { #| yield_ => { #| let mut dropping = true #| self.run(a => if dropping && f(a) { #| IterContinue #| } else { #| dropping = false #| yield_(a) #| }) #| } #|} #|pub fn[T] Iter::find_first(self : Iter[T], f : (T) -> Bool) -> T? { #| for a in self { #| if f(a) { #| break Some(a) #| } #| } else { #| None #| } #|} #|pub fn[T] Iter::peek(self : Iter[T]) -> T? { #| let mut first = None #| self.just_run(a => { #| first = Some(a) #| IterEnd #| }) #| first #|} #|#deprecated("Use `Iter::singleton(a) + self` instead") #|pub fn[T] Iter::prepend(self : Iter[T], a : T) -> Iter[T] { #| yield_ => if yield_(a) == IterContinue { self.run(yield_) } else { IterEnd } #|} #|#deprecated("Use `self + Iter::singleton(a)` instead") #|pub fn[T] Iter::append(self : Iter[T], a : T) -> Iter[T] { #| yield_ => if self.run(yield_) == IterContinue { yield_(a) } else { IterEnd } #|} #|#intrinsic("%iter.concat") #|pub fn[T] Iter::concat(self : Iter[T], other : Iter[T]) -> Iter[T] { #| yield_ => if self.run(yield_) == IterContinue { #| other.run(yield_) #| } else { #| IterEnd #| } #|} #|pub impl[T] Add for Iter[T] with op_add(self, other) { #| Iter::concat(self, other) #|} #|pub fn[T] Iter::to_array(self : Iter[T]) -> Array[T] { #| let result = [] #| for e in self { #| result.push(e) #| } #| result #|} #|pub fn[T] Iter::collect(self : Iter[T]) -> Array[T] { #| let result = [] #| self.each(e => result.push(e)) #| result #|} #|pub fn Iter::join(self : Iter[String], sep : String) -> String { #| let buf = StringBuilder::new() #| let mut first = true #| for str in self { #| if first { #| first = false #| } else { #| buf.write_string(sep) #| } #| buf.write_string(str) #| } #| buf.to_string() #|} #|pub fn[T] Iter::iter(self : Iter[T]) -> Iter[T] { #| self #|} #|pub fn[A] Iter::last(self : Iter[A]) -> A? { #| let mut last = None #| for a in self { #| last = Some(a) #| } #| last #|} #|pub fn[A] Iter::head(self : Iter[A]) -> A? { #| for i in self { #| break Some(i) #| } else { #| None #| } #|} #|pub fn[A] Iter::intersperse(self : Iter[A], sep : A) -> Iter[A] { #| yield_ => { #| let mut first = true #| self.run(x => if first { #| first = false #| yield_(x) #| } else if yield_(sep) == IterEnd { #| IterEnd #| } else { #| yield_(x) #| }) #| } #|} #|pub fn[A] Iter::op_as_view( #| self : Iter[A], #| start? : Int = 0, #| end? : Int, #|) -> Iter[A] { #| match end { #| Some(end) => self.drop(start).take(end - start) #| None => self.drop(start) #| } #|} #|pub fn[A : Eq] Iter::contains(self : Iter[A], value : A) -> Bool { #| for v in self { #| if v == value { #| break true #| } #| } else { #| false #| } #|} #|pub fn[T] Iter::nth(self : Iter[T], n : Int) -> T? { #| self.drop(n).head() #|} #|pub fn[T : Compare] Iter::maximum(self : Iter[T]) -> T? { #| let mut res = None #| for x in self { #| match res { #| None => res = Some(x) #| Some(max) => if x > max { res = Some(x) } #| } #| } #| res #|} #|pub fn[T : Compare] Iter::minimum(self : Iter[T]) -> T? { #| let mut res = None #| for x in self { #| match res { #| None => res = Some(x) #| Some(min) => if x < min { res = Some(x) } #| } #| } #| res #|} #|#deprecated #|pub fn[T, K : Eq + Hash] Iter::group_by( #| self : Iter[T], #| f : (T) -> K, #|) -> Map[K, Array[T]] { #| let result = Map::new() #| for element in self { #| let key = f(element) #| match result.get(key) { #| Some(arr) => result.set(key, arr + [element]) #| None => result.set(key, [element]) #| } #| } #| result #|} #|pub fn[T] Iter::iter2(self : Iter[T]) -> Iter2[Int, T] { #| yield_ => { #| let mut index = -1 #| self.run(i => { #| index += 1 #| yield_(index, i) #| }) #| } #|} ), "iter2.mbt": ( #|struct Iter2[A, B](((A, B) -> IterResult) -> IterResult) #|pub fn[A, B] Iter2::run( #| self : Iter2[A, B], #| f : (A, B) -> IterResult, #|) -> IterResult { #| self(f) #|} #|pub impl[A : Show, B : Show] Show for Iter2[A, B] with output(self, logger) { #| logger.write_string("[") #| let mut first = true #| for k, v in self { #| if !first { #| logger.write_string(", ") #| } else { #| first = false #| } #| logger #| ..write_string("(") #| ..write_object(k) #| ..write_string(", ") #| ..write_object(v) #| ..write_string(")") #| } #| logger.write_string("]") #|} #|pub fn[A, B] Iter2::new( #| f : ((A, B) -> IterResult) -> IterResult, #|) -> Iter2[A, B] { #| Iter2(f) #|} #|pub fn[A, B] Iter2::each(self : Iter2[A, B], f : (A, B) -> Unit) -> Unit { #| self.run((a, b) => { #| f(a, b) #| IterContinue #| }) #| |> ignore #|} #|pub fn[A, B] Iter2::iter(self : Iter2[A, B]) -> Iter[(A, B)] { #| Iter::new(yield_ => self.run((a, b) => yield_((a, b)))) #|} #|pub fn[A, B] Iter2::iter2(self : Iter2[A, B]) -> Iter2[A, B] { #| self #|} #|pub fn[A, B] Iter2::to_array(self : Iter2[A, B]) -> Array[(A, B)] { #| let arr = [] #| for k, v in self { #| arr.push((k, v)) #| } #| arr #|} #|pub fn[A, B] Iter2::concat( #| self : Iter2[A, B], #| other : Iter2[A, B], #|) -> Iter2[A, B] { #| yield_ => { #| guard self.run(yield_) == IterContinue else { IterEnd } #| other.run(yield_) #| } #|} ), "json.mbt": ( #|pub enum Json { #| Null #| True #| False #| Number(Double, repr~ : String?) // 1.0000000000000000000e100 #| String(String) #| Array(Array[Json]) #| Object(Map[String, Json]) #|} #|pub impl Eq for Json with op_equal(a, b) { #| match (a, b) { #| (Null, Null) => true #| (True, True) => true #| (False, False) => true #| (Number(a_num, ..), Number(b_num, ..)) => a_num == b_num #| (String(a_str), String(b_str)) => a_str == b_str #| (Array(a_arr), Array(b_arr)) => a_arr == b_arr #| (Object(a_obj), Object(b_obj)) => a_obj == b_obj #| _ => false #| } #|} #|pub fn Json::null() -> Json { #| return Null #|} #|pub let null : Json = Null #|pub fn Json::number(number : Double, repr? : String) -> Json { #| return Number(number, repr~) #|} #|pub fn Json::string(string : String) -> Json { #| return String(string) #|} #|pub fn Json::boolean(boolean : Bool) -> Json { #| if boolean { #| True #| } else { #| False #| } #|} #|pub fn Json::array(array : Array[Json]) -> Json { #| return Array(array) #|} #|pub fn Json::object(object : Map[String, Json]) -> Json { #| return Object(object) #|} #|pub(open) trait ToJson { #| to_json(Self) -> Json #|} #|pub impl ToJson for Bool with to_json(self : Bool) -> Json { #| if self { #| true #| } else { #| false #| } #|} #|pub impl ToJson for Byte with to_json(self : Byte) -> Json { #| Json::number(self.to_double()) #|} #|pub impl ToJson for Int with to_json(self : Int) -> Json { #| Json::number(self.to_double()) #|} #|pub impl ToJson for Int64 with to_json(self : Int64) -> Json { #| String::to_json(self.to_string()) #|} #|pub impl ToJson for UInt with to_json(self : UInt) -> Json { #| Json::number(self.to_uint64().to_double()) #|} #|pub impl ToJson for UInt64 with to_json(self : UInt64) -> Json { #| String::to_json(self.to_string()) #|} #|pub impl ToJson for Double with to_json(self : Double) -> Json { #| if self != self { #| Json::string("NaN") #| } else if self > 0x7FEFFFFFFFFFFFFFL.reinterpret_as_double() { #| Json::string("Infinity") #| } else if self < 0xFFEFFFFFFFFFFFFFL.reinterpret_as_double() { #| Json::string("-Infinity") #| } else { #| Json::number(self) #| } #|} #|pub impl ToJson for Float with to_json(self : Float) -> Json { #| Json::number(self.to_double()) #|} #|pub impl ToJson for String with to_json(self : String) -> Json { #| String(self) #|} #|pub impl[X : ToJson] ToJson for Array[X] with to_json(self) { #| Array(self.map(ToJson::to_json)) #|} #|pub impl[X : ToJson] ToJson for FixedArray[X] with to_json(self) { #| let len = self.length() #| if len == 0 { #| return [] #| } #| let res = Array::make_uninit(self.length()) #| for i, x in self { #| res.unsafe_set(i, ToJson::to_json(x)) #| } #| Array(res) #|} #|pub impl[X : ToJson] ToJson for ArrayView[X] with to_json(self) { #| let len = self.length() #| if len == 0 { #| return [] #| } #| let res = Array::make_uninit(self.length()) #| for i, x in self { #| res.unsafe_set(i, ToJson::to_json(x)) #| } #| Array(res) #|} #|pub impl[K : Show, V : ToJson] ToJson for Map[K, V] with to_json(self) { #| let object = Map::new(capacity=self.capacity) #| for k, v in self { #| object[k.to_string()] = v.to_json() #| } #| Object(object) #|} #|pub impl[T : ToJson] ToJson for T? with to_json(self) { #| match self { #| None => Null #| Some(value) => [value] #| } #|} #|pub impl[Ok : ToJson, Err : ToJson] ToJson for Result[Ok, Err] with to_json( #| self : Result[Ok, Err], #|) -> Json { #| match self { #| Ok(ok) => { "Ok": ok } #| Err(err) => { "Err": err } #| } #|} #|pub impl ToJson for Unit with to_json(_self) { #| Null #|} #|pub impl Default for Json with default() { #| false #|} ), "linked_hash_map.mbt": ( #|priv struct Entry[K, V] { #| mut prev : Int #| mut next : Entry[K, V]? #| mut psl : Int #| hash : Int #| key : K #| mut value : V #|} derive(Show) #|struct Map[K, V] { #| mut entries : FixedArray[Entry[K, V]?] #| mut size : Int // active key-value pairs count #| mut capacity : Int // current capacity #| mut capacity_mask : Int // capacity_mask = capacity - 1, used to find idx #| mut grow_at : Int // threshold that triggers grow #| mut head : Entry[K, V]? // head of linked list #| mut tail : Int // tail of linked list #|} #|pub fn[K, V] Map::new(capacity? : Int = 8) -> Map[K, V] { #| let capacity = capacity.next_power_of_two() #| { #| size: 0, #| capacity, #| capacity_mask: capacity - 1, #| grow_at: calc_grow_threshold(capacity), #| entries: FixedArray::make(capacity, None), #| head: None, #| tail: -1, #| } #|} #|pub fn[K : Hash + Eq, V] Map::from_array(arr : Array[(K, V)]) -> Map[K, V] { #| let m = Map::new(capacity=arr.length()) #| arr.each(e => m.set(e.0, e.1)) #| m #|} #|pub fn[K : Hash + Eq, V] Map::set(self : Map[K, V], key : K, value : V) -> Unit { #| self.set_with_hash(key, value, key.hash()) #|} #|fn[K : Eq, V] set_with_hash( #| self : Map[K, V], #| key : K, #| value : V, #| hash : Int, #|) -> Unit { #| if self.size >= self.grow_at { #| self.grow() #| } #| let (idx, psl) = for psl = 0, idx = hash & self.capacity_mask { #| match self.entries[idx] { #| None => break (idx, psl) #| Some(curr_entry) => { #| if curr_entry.hash == hash && curr_entry.key == key { #| curr_entry.value = value #| return #| } #| if psl > curr_entry.psl { #| self.push_away(idx, curr_entry) #| break (idx, psl) #| } #| continue psl + 1, (idx + 1) & self.capacity_mask #| } #| } #| } #| let entry = { prev: self.tail, next: None, psl, key, value, hash } #| self.add_entry_to_tail(idx, entry) #|} #|fn[K, V] Map::push_away( #| self : Map[K, V], #| idx : Int, #| entry : Entry[K, V], #|) -> Unit { #| for psl = entry.psl + 1, idx = (idx + 1) & self.capacity_mask, entry = entry { #| match self.entries[idx] { #| None => { #| entry.psl = psl #| self.set_entry(entry, idx) #| break #| } #| Some(curr_entry) => #| if psl > curr_entry.psl { #| entry.psl = psl #| self.set_entry(entry, idx) #| continue curr_entry.psl + 1, #| (idx + 1) & self.capacity_mask, #| curr_entry #| } else { #| continue psl + 1, (idx + 1) & self.capacity_mask, entry #| } #| } #| } #|} #|fn[K, V] Map::set_entry( #| self : Map[K, V], #| entry : Entry[K, V], #| new_idx : Int, #|) -> Unit { #| self.entries[new_idx] = Some(entry) #| match entry.next { #| None => self.tail = new_idx #| Some(next) => next.prev = new_idx #| } #|} #|pub fn[K : Hash + Eq, V] Map::op_set( #| self : Map[K, V], #| key : K, #| value : V, #|) -> Unit { #| self.set(key, value) #|} #|pub fn[K : Hash + Eq, V] Map::get(self : Map[K, V], key : K) -> V? { #| let hash = key.hash() #| for i = 0, idx = hash & self.capacity_mask { #| guard self.entries[idx] is Some(entry) else { break None } #| if entry.hash == hash && entry.key == key { #| break Some(entry.value) #| } #| if i > entry.psl { #| break None #| } #| continue i + 1, (idx + 1) & self.capacity_mask #| } #|} #|pub fn[K : Hash + Eq, V] Map::op_get(self : Map[K, V], key : K) -> V { #| let hash = key.hash() #| for i = 0, idx = hash & self.capacity_mask { #| guard self.entries[idx] is Some(entry) #| if entry.hash == hash && entry.key == key { #| return entry.value #| } #| guard i <= entry.psl #| continue i + 1, (idx + 1) & self.capacity_mask #| } #|} #|pub fn[K : Hash + Eq, V] Map::get_or_default( #| self : Map[K, V], #| key : K, #| default : V, #|) -> V { #| let hash = key.hash() #| for i = 0, idx = hash & self.capacity_mask { #| match self.entries[idx] { #| Some(entry) => { #| if entry.hash == hash && entry.key == key { #| break entry.value #| } #| if i > entry.psl { #| break default #| } #| continue i + 1, (idx + 1) & self.capacity_mask #| } #| None => break default #| } #| } #|} #|pub fn[K : Hash + Eq, V] Map::get_or_init( #| self : Map[K, V], #| key : K, #| default : () -> V, #|) -> V { #| let hash = key.hash() #| let (idx, psl, new_value, push_away) = for psl = 0, idx = hash & #| self.capacity_mask { #| match self.entries[idx] { #| Some(entry) => { #| if entry.hash == hash && entry.key == key { #| return entry.value #| } #| if psl > entry.psl { #| let new_value = default() #| self.push_away(idx, entry) #| break (idx, psl, new_value, Some(entry)) #| } #| continue psl + 1, (idx + 1) & self.capacity_mask #| } #| None => { #| let new_value = default() #| break (idx, psl, new_value, None) #| } #| } #| } #| if self.size >= self.grow_at { #| self.grow() #| self.set_with_hash(key, new_value, hash) #| } else { #| if push_away is Some(entry) { #| self.push_away(idx, entry) #| } #| let entry = { #| prev: self.tail, #| next: None, #| psl, #| hash, #| key, #| value: new_value, #| } #| self.add_entry_to_tail(idx, entry) #| } #| new_value #|} #|pub fn[K : Hash + Eq, V] Map::contains(self : Map[K, V], key : K) -> Bool { #| let hash = key.hash() #| for i = 0, idx = hash & self.capacity_mask { #| guard self.entries[idx] is Some(entry) else { break false } #| if entry.hash == hash && entry.key == key { #| break true #| } #| if i > entry.psl { #| break false #| } #| continue i + 1, (idx + 1) & self.capacity_mask #| } #|} #|pub fn[K : Hash + Eq, V : Eq] Map::contains_kv( #| self : Map[K, V], #| key : K, #| value : V, #|) -> Bool { #| let hash = key.hash() #| for i = 0, idx = hash & self.capacity_mask { #| guard self.entries[idx] is Some(entry) else { break false } #| if entry.hash == hash && entry.key == key && entry.value == value { #| break true #| } #| if i > entry.psl { #| break false #| } #| continue i + 1, (idx + 1) & self.capacity_mask #| } #|} #|pub fn[K : Hash + Eq, V] Map::remove(self : Map[K, V], key : K) -> Unit { #| let hash = key.hash() #| for i = 0, idx = hash & self.capacity_mask { #| guard self.entries[idx] is Some(entry) else { break } #| if entry.hash == hash && entry.key == key { #| self.remove_entry(entry) #| self.shift_back(idx) #| self.size -= 1 #| break #| } #| if i > entry.psl { #| break #| } #| continue i + 1, (idx + 1) & self.capacity_mask #| } #|} #|fn[K, V] Map::add_entry_to_tail( #| self : Map[K, V], #| idx : Int, #| entry : Entry[K, V], #|) -> Unit { #| match self.tail { #| -1 => self.head = Some(entry) #| tail => self.entries[tail].unwrap().next = Some(entry) #| } #| self.tail = idx #| self.entries[idx] = Some(entry) #| self.size += 1 #|} #|fn[K, V] Map::remove_entry(self : Map[K, V], entry : Entry[K, V]) -> Unit { #| match entry.prev { #| -1 => self.head = entry.next #| idx => self.entries[idx].unwrap().next = entry.next #| } #| match entry.next { #| None => self.tail = entry.prev #| Some(next) => next.prev = entry.prev #| } #|} #|fn[K, V] Map::shift_back(self : Map[K, V], idx : Int) -> Unit { #| let next = (idx + 1) & self.capacity_mask #| match self.entries[next] { #| None | Some({ psl: 0, .. }) => self.entries[idx] = None #| Some(entry) => { #| entry.psl -= 1 #| self.set_entry(entry, idx) #| self.shift_back(next) #| } #| } #|} #|fn[K : Eq, V] Map::grow(self : Map[K, V]) -> Unit { #| let old_head = self.head #| let new_capacity = self.capacity << 1 #| self.entries = FixedArray::make(new_capacity, None) #| self.capacity = new_capacity #| self.capacity_mask = new_capacity - 1 #| self.grow_at = calc_grow_threshold(self.capacity) #| self.size = 0 #| self.head = None #| self.tail = -1 #| loop old_head { #| Some({ next, key, value, hash, .. }) => { #| self.set_with_hash(key, value, hash) #| continue next #| } #| None => break #| } #|} #|fn calc_grow_threshold(capacity : Int) -> Int { #| capacity * 13 / 16 #|} #|pub impl[K : Show, V : Show] Show for Map[K, V] with output(self, logger) { #| logger.write_string("{") #| loop (0, self.head) { #| (_, None) => logger.write_string("}") #| (i, Some({ key, value, next, .. })) => { #| if i > 0 { #| logger.write_string(", ") #| } #| logger..write_object(key)..write_string(": ")..write_object(value) #| continue (i + 1, next) #| } #| } #|} #|pub fn[K, V] Map::size(self : Map[K, V]) -> Int { #| self.size #|} #|pub fn[K, V] Map::capacity(self : Map[K, V]) -> Int { #| self.capacity #|} #|pub fn[K, V] Map::is_empty(self : Map[K, V]) -> Bool { #| self.size == 0 #|} #|#locals(f) #|pub fn[K, V] Map::each( #| self : Map[K, V], #| f : (K, V) -> Unit raise?, #|) -> Unit raise? { #| loop self.head { #| Some({ key, value, next, .. }) => { #| f(key, value) #| continue next #| } #| None => break #| } #|} #|#locals(f) #|pub fn[K, V] Map::eachi( #| self : Map[K, V], #| f : (Int, K, V) -> Unit raise?, #|) -> Unit raise? { #| loop (0, self.head) { #| (i, Some({ key, value, next, .. })) => { #| f(i, key, value) #| continue (i + 1, next) #| } #| (_, None) => break #| } #|} #|pub fn[K, V] Map::clear(self : Map[K, V]) -> Unit { #| self.entries.fill(None) #| self.size = 0 #| self.head = None #| self.tail = -1 #|} #|pub fn[K, V] Map::iter(self : Map[K, V]) -> Iter[(K, V)] { #| Iter::new(yield_ => loop self.head { #| Some({ key, value, next, .. }) => { #| guard yield_((key, value)) is IterContinue else { break IterEnd } #| continue next #| } #| None => break IterContinue #| }) #|} #|pub fn[K, V] Map::iter2(self : Map[K, V]) -> Iter2[K, V] { #| Iter2::new(yield_ => loop self.head { #| Some({ key, value, next, .. }) => { #| guard yield_(key, value) is IterContinue else { break IterEnd } #| continue next #| } #| None => IterContinue #| }) #|} #|pub fn[K, V] Map::keys(self : Map[K, V]) -> Iter[K] { #| Iter::new(yield_ => loop self.head { #| Some({ key, next, .. }) => { #| guard yield_(key) is IterContinue else { break IterEnd } #| continue next #| } #| None => IterContinue #| }) #|} #|pub fn[K, V] Map::values(self : Map[K, V]) -> Iter[V] { #| Iter::new(yield_ => loop self.head { #| Some({ value, next, .. }) => { #| guard yield_(value) is IterContinue else { break IterEnd } #| continue next #| } #| None => IterContinue #| }) #|} #|pub fn[K, V] Map::to_array(self : Map[K, V]) -> Array[(K, V)] { #| let arr = Array::make_uninit(self.size) #| let mut i = 0 #| loop self.head { #| Some({ key, value, next, .. }) => { #| arr.unsafe_set(i, (key, value)) #| i += 1 #| continue next #| } #| None => break #| } #| arr #|} #|pub impl[K : Hash + Eq, V : Eq] Eq for Map[K, V] with op_equal( #| self : Map[K, V], #| that : Map[K, V], #|) -> Bool { #| guard self.size == that.size else { return false } #| for k, v in self { #| guard that.contains_kv(k, v) else { return false } #| } else { #| true #| } #|} #|pub fn[K : Hash + Eq, V] Map::of(arr : FixedArray[(K, V)]) -> Map[K, V] { #| let length = arr.length() #| let m = Map::new(capacity=length) #| for i in 0.. Map[K, V] { #| let m = {} #| for e in iter { #| m.set(e.0, e.1) #| } #| m #|} #|pub impl[K, V] Default for Map[K, V] with default() { #| Map::new() #|} #|pub fn[K, V, V2] Map::map(self : Map[K, V], f : (K, V) -> V2) -> Map[K, V2] { #| let other = { #| capacity: self.capacity, #| entries: FixedArray::make(self.capacity, None), #| size: self.size, #| capacity_mask: self.capacity_mask, #| grow_at: self.grow_at, #| head: None, #| tail: self.tail, #| } #| if self.size == 0 { #| return other #| } #| guard self.entries[self.tail] is Some(last) #| loop (last, self.tail, None) { #| ({ prev, psl, hash, key, value, .. }, idx, next) => { #| let new_value = f(key, value) #| let new_entry = { prev, next, psl, hash, key, value: new_value } #| other.entries[idx] = Some(new_entry) #| if prev != -1 { #| continue (self.entries[prev].unwrap(), prev, Some(new_entry)) #| } else { #| other.head = Some(new_entry) #| } #| } #| } #| other #|} #|pub fn[K, V] Map::copy(self : Map[K, V]) -> Map[K, V] { #| let other = { #| capacity: self.capacity, #| entries: FixedArray::make(self.capacity, None), #| size: self.size, #| capacity_mask: self.capacity_mask, #| grow_at: self.grow_at, #| head: None, #| tail: self.tail, #| } #| if self.size == 0 { #| return other #| } #| guard self.entries[self.tail] is Some(last) #| loop (last, self.tail, None) { #| ({ prev, psl, hash, key, value, .. }, idx, next) => { #| let new_entry = { prev, next, psl, hash, key, value } #| other.entries[idx] = Some(new_entry) #| if prev != -1 { #| continue (self.entries[prev].unwrap(), prev, Some(new_entry)) #| } else { #| other.head = Some(new_entry) #| } #| } #| } #| other #|} #|pub fn[K : Hash + Eq, V] Map::update( #| self : Map[K, V], #| key : K, #| f : (V?) -> V?, #|) -> Unit { #| let hash = key.hash() #| let (idx, psl, new_value, push_away) = for psl = 0, idx = hash & #| self.capacity_mask { #| match self.entries[idx] { #| Some(entry) => { #| if entry.hash == hash && entry.key == key { #| if f(Some(entry.value)) is Some(new_value) { #| entry.value = new_value #| } else { #| self.remove_entry(entry) #| self.shift_back(idx) #| self.size -= 1 #| } #| return #| } #| if psl > entry.psl { #| guard f(None) is Some(new_value) else { return } #| break (idx, psl, new_value, Some(entry)) #| } #| continue psl + 1, (idx + 1) & self.capacity_mask #| } #| None => { #| guard f(None) is Some(new_value) else { return } #| break (idx, psl, new_value, None) #| } #| } #| } #| if self.size >= self.grow_at { #| self.grow() #| self.set(key, new_value) #| } else { #| if push_away is Some(entry) { #| self.push_away(idx, entry) #| } #| let entry = { #| prev: self.tail, #| next: None, #| psl, #| hash, #| key, #| value: new_value, #| } #| self.add_entry_to_tail(idx, entry) #| } #|} ), "op.mbt": ( #|#coverage.skip #|pub fn[T : Compare] op_lt(self_ : T, other : T) -> Bool { #| self_.compare(other).is_neg() #|} #|#coverage.skip #|pub fn[T : Compare] op_gt(self_ : T, other : T) -> Bool { #| self_.compare(other).is_pos() #|} #|#coverage.skip #|pub fn[T : Compare] op_le(self_ : T, other : T) -> Bool { #| self_.compare(other).is_non_pos() #|} #|#coverage.skip #|pub fn[T : Compare] op_ge(self_ : T, other : T) -> Bool { #| self_.compare(other).is_non_neg() #|} #|#coverage.skip #|pub fn[T : Eq] op_notequal(x : T, y : T) -> Bool { #| !(x == y) #|} ), "operators.mbt": ( #|pub(open) trait Add { #| op_add(Self, Self) -> Self #|} #|pub(open) trait Sub { #| op_sub(Self, Self) -> Self #|} #|pub(open) trait Mul { #| op_mul(Self, Self) -> Self #|} #|pub(open) trait Div { #| op_div(Self, Self) -> Self #|} #|pub(open) trait Neg { #| op_neg(Self) -> Self #|} #|pub(open) trait Mod { #| op_mod(Self, Self) -> Self #|} #|pub(open) trait BitAnd { #| land(Self, Self) -> Self #|} #|pub(open) trait BitOr { #| lor(Self, Self) -> Self #|} #|pub(open) trait BitXOr { #| lxor(Self, Self) -> Self #|} #|pub(open) trait Shl { #| op_shl(Self, Int) -> Self #|} #|pub(open) trait Shr { #| op_shr(Self, Int) -> Self #|} ), "option.mbt": ( #|pub impl[X : Eq] Eq for X? with op_equal(self, other) { #| match (self, other) { #| (None, None) => true #| (Some(x), Some(y)) => x == y #| _ => false #| } #|} #|pub fn[X : Show] Option::to_string(self : X?) -> String { #| match self { #| None => "None" #| Some(x) => "Some(" + x.to_string() + ")" #| } #|} #|pub fn[X] Option::unwrap(self : X?) -> X { #| match self { #| None => panic() #| Some(x) => x #| } #|} ), "output.mbt": ( #|fn Int64::output(self : Int64, logger : &Logger, radix? : Int = 10) -> Unit { #| fn abs(n : Int64) -> Int64 { #| if n < 0L { #| 0L - n #| } else { #| n #| } #| } #| if self < 0L { #| logger.write_char('-') #| } #| let radix : Int64 = radix.to_int64() #| fn write_digits(num : Int64) { #| let num2 = num / radix #| if num2 != 0L { #| write_digits(num2) #| } #| logger.write_char( #| ALPHABET.charcode_at(abs(num % radix).to_int()).unsafe_to_char(), #| ) #| } #| write_digits(abs(self)) #|} #|fn Int::output(self : Int, logger : &Logger, radix? : Int = 10) -> Unit { #| fn abs(n : Int) -> Int { #| if n < 0 { #| 0 - n #| } else { #| n #| } #| } #| if self < 0 { #| logger.write_char('-') #| } #| fn write_digits(num : Int) { #| let num2 = num / radix #| if num2 != 0 { #| write_digits(num2) #| } #| logger.write_char(ALPHABET.charcode_at(abs(num % radix)).unsafe_to_char()) #| } #| write_digits(abs(self)) #|} #|fn UInt::output(self : UInt, logger : &Logger, radix? : Int = 10) -> Unit { #| let radix : UInt = radix.reinterpret_as_uint() #| fn write_digits(num : UInt) { #| let num2 = num / radix #| if num2 != 0U { #| write_digits(num2) #| } #| logger.write_char( #| ALPHABET.charcode_at((num % radix).reinterpret_as_int()).unsafe_to_char(), #| ) #| } #| write_digits(self) #|} #|fn UInt64::output(self : UInt64, logger : &Logger, radix? : Int = 10) -> Unit { #| let radix : UInt64 = radix.to_uint64() #| fn write_digits(num : UInt64) { #| let num2 = num / radix #| if num2 != 0UL { #| write_digits(num2) #| } #| logger.write_char( #| ALPHABET.charcode_at((num % radix).to_int()).unsafe_to_char(), #| ) #| } #| write_digits(self) #|} #|fn Int64::output_size_hint(radix? : Int = 10) -> Int { #| match radix { #| 2..<7 => 70 // max length is 64, 70 is enough #| 8..<15 => 30 // max length is 23, 30 is enough #| 16..=36 => 20 // max length is 17, 20 is enough #| _ => abort("radix must be between 2 and 36") #| } #|} #|fn Int::output_size_hint(radix? : Int = 10) -> Int { #| match radix { #| 2..<7 => 36 // max length is 32, 36 is enough #| 8..<15 => 18 // max length is 12, 18 is enough #| 16..=36 => 10 // max length is 8, 10 is enough #| _ => abort("radix must be between 2 and 36") #| } #|} #|fn UInt::output_size_hint(radix? : Int = 10) -> Int { #| Int::output_size_hint(radix~) #|} #|fn UInt64::output_size_hint(radix? : Int = 10) -> Int { #| Int64::output_size_hint(radix~) #|} ), "result.mbt": ( #|pub impl[T : Eq, E : Eq] Eq for Result[T, E] with op_equal(self, other) { #| match (self, other) { #| (Ok(x), Ok(y)) => x == y #| (Err(x), Err(y)) => x == y #| _ => false #| } #|} ), "show.mbt": ( #|pub impl Show for Unit with output(_self, logger) { #| logger.write_string("()") #|} #|pub impl Show for Bool with output(self, logger) { #| if self { #| logger.write_string("true") #| } else { #| logger.write_string("false") #| } #|} #|pub impl Show for Int with output(self, logger) { #| self.output(logger) #|} #|pub impl Show for Int64 with output(self, logger) { #| self.output(logger) #|} #|pub impl Show for UInt with output(self, logger) { #| self.output(logger) #|} #|pub impl Show for UInt64 with output(self, logger) { #| self.output(logger) #|} #|pub impl Show for Byte with output(self, logger) { #| logger.write_string(self.to_string()) #|} #|pub impl Show for Int16 with output(self, logger) { #| logger.write_string(self.to_string()) #|} #|pub impl Show for UInt16 with output(self, logger) { #| self.to_int().output(logger) #|} #|fn to_hex_digit(i : Int) -> Char { #| if i < 10 { #| (i + '0').unsafe_to_char() #| } else { #| (i + 'a' - 10).unsafe_to_char() #| } #|} #|test "to_hex_digit" { #| for i in 0..<10 { #| guard to_hex_digit(i) == ('0'.to_int() + i).unsafe_to_char() else { #| fail("to_hex_digit(\{i}) does not match") #| } #| } #| for i in 10..<16 { #| guard to_hex_digit(i) == ('a'.to_int() + (i - 10)).unsafe_to_char() else { #| fail("to_hex_digit(\{i}) does not match") #| } #| } #|} #|pub impl Show for Bytes with output(self, logger) { #| logger.write_string("b\"") #| for b in self { #| let byte = b.to_int() #| logger #| ..write_string("\\x") #| ..write_char(to_hex_digit(byte / 16)) #| ..write_char(to_hex_digit(byte % 16)) #| } #| logger.write_string("\"") #|} #|pub impl Show for String with output(self, logger) { #| logger.write_char('"') #| fn flush_segment(seg : Int, i : Int) { #| if i > seg { #| logger.write_substring(self, seg, i - seg) #| } #| } #| let len = self.length() #| for i = 0, seg = 0 { #| if i >= len { #| flush_segment(seg, i) #| break #| } #| let code = self.unsafe_charcode_at(i) #| match code { #| '"' | '\\' as c => { #| flush_segment(seg, i) #| logger..write_char('\\')..write_char(c.unsafe_to_char()) #| continue i + 1, i + 1 #| } #| '\n' => { #| flush_segment(seg, i) #| logger.write_string("\\n") #| continue i + 1, i + 1 #| } #| '\r' => { #| flush_segment(seg, i) #| logger.write_string("\\r") #| continue i + 1, i + 1 #| } #| '\b' => { #| flush_segment(seg, i) #| logger.write_string("\\b") #| continue i + 1, i + 1 #| } #| '\t' => { #| flush_segment(seg, i) #| logger.write_string("\\t") #| continue i + 1, i + 1 #| } #| code => #| if code < ' ' { #| flush_segment(seg, i) #| logger #| ..write_string("\\u{") #| ..write_char(to_hex_digit(code / 16)) #| ..write_char(to_hex_digit(code % 16)) #| ..write_char('}') #| continue i + 1, i + 1 #| } else { #| continue i + 1, seg #| } #| } #| } #| logger.write_char('"') #|} #|pub impl Show for String with to_string(self) { #| self #|} #|pub fn String::escape(self : String) -> String { #| let buf = StringBuilder::new() #| Show::output(self, buf) #| buf.to_string() #|} #|pub impl[X : Show] Show for X? with output(self, logger) { #| match self { #| None => logger.write_string("None") #| Some(arg) => #| logger..write_string("Some(")..write_object(arg)..write_string(")") #| } #|} #|pub impl[T : Show, E : Show] Show for Result[T, E] with output(self, logger) { #| match self { #| Ok(x) => logger..write_string("Ok(")..write_object(x)..write_string(")") #| Err(e) => logger..write_string("Err(")..write_object(e)..write_string(")") #| } #|} #|pub impl[X : Show] Show for Ref[X] with output(self, logger) { #| logger..write_string("{val: ")..write_object(self.val)..write_string("}") #|} #|pub impl[X : Show] Show for FixedArray[X] with output(self, logger) { #| logger.write_iter(self.iter()) #|} #|pub impl[X : Show] Show for Array[X] with output(self, logger) { #| logger.write_iter(self.iter()) #|} ), "string.mbt": ( #|fn unsafe_make_string(length : Int, value : Char) -> String = "$moonbit.unsafe_make_string" #|pub fn String::make(length : Int, value : Char) -> String { #| guard length >= 0 else { abort("invalid length") } #| if value.to_int() <= 0xFFFF { #| unsafe_make_string(length, value) #| } else { #| let buf = StringBuilder::new(size_hint=2 * length) #| for _ in 0.. Char { #| ((leading - 0xD800) * 0x400 + trailing - 0xDC00 + 0x10000).unsafe_to_char() #|} #|pub fn String::char_length( #| self : String, #| start_offset? : Int = 0, #| end_offset? : Int, #|) -> Int { #| let end_offset = if end_offset is Some(o) { o } else { self.length() } #| guard start_offset >= 0 && #| start_offset <= end_offset && #| end_offset <= self.length() else { #| abort("invalid start or end index for String::codepoint_length") #| } #| for utf16_index = start_offset, char_count = 0 #| utf16_index < end_offset #| utf16_index = utf16_index + 1, char_count = char_count + 1 { #| let c1 = self.unsafe_charcode_at(utf16_index) #| if c1.is_leading_surrogate() && utf16_index + 1 < end_offset { #| let c2 = self.unsafe_charcode_at(utf16_index + 1) #| if c2.is_trailing_surrogate() { #| continue utf16_index + 2, char_count + 1 #| } else { #| abort("invalid surrogate pair") #| } #| } #| } else { #| char_count #| } #|} #|#intrinsic("%string.substring") #|fn unsafe_substring(str : String, start : Int, end : Int) -> String { #| let len = end - start #| let bytes = FixedArray::make(len * 2, Byte::default()) #| bytes.blit_from_string(0, str, start, len) #| bytes.unsafe_reinterpret_as_bytes().to_unchecked_string() #|} #|pub fn String::substring(self : String, start? : Int = 0, end? : Int) -> String { #| let len = self.length() #| let end = match end { #| Some(end) => end #| None => len #| } #| guard start >= 0 && start <= end && end <= len #| unsafe_substring(self, start, end) #|} #|test "substring/empty" { #| let s = "test" #| inspect(s.substring(start=2, end=2), content="") #| inspect(s.substring(start=4, end=4), content="") #| inspect("".substring(), content="") #|} #|test "panic substring/invalid_range" { #| let s = "test" #| ignore(s.substring(start=-1)) #| ignore(s.substring(end=5)) #| ignore(s.substring(start=3, end=2)) #|} #|test "substring/basic" { #| inspect("Hello world".substring(start=0, end=5), content="Hello") #| inspect("Hello world".substring(start=6, end=11), content="world") #| inspect("Hello world".substring(start=0), content="Hello world") #| inspect("Hello world".substring(start=6), content="world") #|} #|test "substring/boundary" { #| inspect("".substring(start=0, end=0), content="") #| inspect("a".substring(start=0, end=1), content="a") #| inspect("abc".substring(start=0), content="abc") #| inspect("abc".substring(start=1), content="bc") #| inspect("abc".substring(start=0, end=3), content="abc") #|} #|test "panic substring/out_of_bounds" { #| ignore("hello".substring(start=-1, end=4)) #| ignore("hello".substring(start=6, end=4)) #| ignore("hello".substring(start=0, end=6)) #|} ), "stringbuilder.mbt": ( #|pub fn[T : Show] StringBuilder::write_object( #| self : StringBuilder, #| obj : T, #|) -> Unit { #| obj.output(self) #|} #|pub fn StringBuilder::write_iter( #| self : StringBuilder, #| iter : Iter[Char], #|) -> Unit { #| for ch in iter { #| self.write_char(ch) #| } #|} ), "stringbuilder_buffer.mbt": ( #|struct StringBuilder { #| mut data : FixedArray[Byte] #| mut len : Int #|} #|pub fn StringBuilder::new(size_hint? : Int = 0) -> StringBuilder { #| let initial = if size_hint < 1 { 1 } else { size_hint } #| let data : FixedArray[Byte] = FixedArray::make(initial, 0) #| { data, len: 0 } #|} #|pub fn StringBuilder::is_empty(self : StringBuilder) -> Bool { #| self.len == 0 #|} #|fn StringBuilder::grow_if_necessary( #| self : StringBuilder, #| required : Int, #|) -> Unit { #| let current_len = self.data.length() #| if required <= current_len { #| return #| } #| let mut enough_space = current_len #| while enough_space < required { #| enough_space = enough_space * 2 #| } #| let new_data = FixedArray::make(enough_space, Byte::default()) #| new_data.unsafe_blit(0, self.data, 0, self.len) #| self.data = new_data #|} #|pub impl Logger for StringBuilder with write_string(self, str) { #| self.grow_if_necessary(self.len + str.length() * 2) #| self.data.blit_from_string(self.len, str, 0, str.length()) #| self.len += str.length() * 2 #|} #|pub impl Logger for StringBuilder with write_char(self, ch) { #| self.grow_if_necessary(self.len + 4) #| let inc = self.data.set_utf16le_char(self.len, ch) #| self.len += inc #|} #|pub impl Logger for StringBuilder with write_substring( #| self : StringBuilder, #| str : String, #| start : Int, #| len : Int, #|) -> Unit { #| guard start >= 0 && len >= 0 && start + len <= str.length() #| self.grow_if_necessary(self.len + len * 2) #| self.data.blit_from_string(self.len, str, start, len) #| self.len += len * 2 #|} #|pub fn StringBuilder::to_string(self : StringBuilder) -> String { #| self.data #| .unsafe_reinterpret_as_bytes() #| .to_unchecked_string(offset=0, length=self.len) #|} #|pub impl Show for StringBuilder with output(self, logger) { #| logger.write_string( #| self.data #| .unsafe_reinterpret_as_bytes() #| .to_unchecked_string(offset=0, length=self.len), #| ) #|} #|pub fn StringBuilder::reset(self : StringBuilder) -> Unit { #| self.len = 0 #|} ), "stringbuilder_concat.mbt": ( #|struct StringBuilder(Ref[String]) #|pub fn StringBuilder::new(size_hint? : Int = 0) -> StringBuilder { #| ignore(size_hint) #| { val: "" } #|} #|pub fn StringBuilder::is_empty(self : StringBuilder) -> Bool { #| self.val == "" #|} #|pub impl Logger for StringBuilder with write_string(self, str) { #| self.val += str #|} #|#intrinsic("%char.to_string") #|fn char_to_string(char : Char) -> String { #| [char] #|} #|pub impl Logger for StringBuilder with write_char(self, ch) { #| self.val += char_to_string(ch) #|} #|pub impl Logger for StringBuilder with write_substring( #| self : StringBuilder, #| str : String, #| start : Int, #| len : Int, #|) -> Unit { #| self.val += str.substring(start~, end=start + len) #|} #|pub impl Show for StringBuilder with output(self, logger) { #| logger.write_string(self.val) #|} #|pub fn StringBuilder::to_string(self : StringBuilder) -> String { #| self.val #|} #|pub fn StringBuilder::reset(self : StringBuilder) -> Unit { #| self.val = "" #|} ), "to_string.mbt": ( #|const ALPHABET : String = "0123456789abcdefghijklmnopqrstuvwxyz" #|pub fn Int64::to_string(self : Int64, radix? : Int = 10) -> String { #| let buf = StringBuilder::new(size_hint=Int64::output_size_hint(radix~)) #| self.output(buf, radix~) #| buf.to_string() #|} #|pub impl Show for Int64 with to_string(self) { #| self.to_string(radix=10) #|} #|pub fn Int::to_string(self : Int, radix? : Int = 10) -> String { #| let buf = StringBuilder::new(size_hint=Int::output_size_hint(radix~)) #| self.output(buf, radix~) #| buf.to_string() #|} #|pub impl Show for Int with to_string(self) { #| self.to_string(radix=10) #|} #|pub fn UInt::to_string(self : UInt, radix? : Int = 10) -> String { #| let buf = StringBuilder::new(size_hint=UInt::output_size_hint(radix~)) #| self.output(buf, radix~) #| buf.to_string() #|} #|pub impl Show for UInt with to_string(self) { #| self.to_string(radix=10) #|} #|test "UInt::to_string" { #| inspect(0U, content="0") #| inspect(17U, content="17") #| inspect(4294967295U, content="4294967295") #|} #|pub fn UInt64::to_string(self : UInt64, radix? : Int = 10) -> String { #| let buf = StringBuilder::new(size_hint=UInt64::output_size_hint(radix~)) #| self.output(buf, radix~) #| buf.to_string() #|} #|pub impl Show for UInt64 with to_string(self) { #| self.to_string(radix=10) #|} #|pub fn Int16::to_string(self : Int16, radix? : Int = 10) -> String { #| self.to_int().to_string(radix~) #|} #|pub impl Show for Int16 with to_string(self) { #| self.to_string(radix=10) #|} #|pub fn UInt16::to_string(self : UInt16, radix? : Int = 10) -> String { #| self.to_int().to_string(radix~) #|} #|pub impl Show for UInt16 with to_string(self) { #| self.to_string(radix=10) #|} #|test "to_string" { #| assert_eq((0x100).to_string(), "256") #| assert_eq("\{0x100}", "256") #| assert_eq(0x200U.to_string(), "512") #| assert_eq("\{0x200U}", "512") #| assert_eq(0x300L.to_string(), "768") #| assert_eq("\{0x300L}", "768") #| assert_eq(0x400UL.to_string(), "1024") #| assert_eq("\{0x400UL}", "1024") #|} #|test "to_string with radix" { #| inspect((0).to_string(radix=2), content="0") #| inspect((1).to_string(radix=2), content="1") #| inspect((2).to_string(radix=2), content="10") #| inspect((255).to_string(radix=2), content="11111111") #| inspect((-255).to_string(radix=2), content="-11111111") #| inspect((0).to_string(radix=8), content="0") #| inspect((8).to_string(radix=8), content="10") #| inspect((64).to_string(radix=8), content="100") #| inspect((-64).to_string(radix=8), content="-100") #| inspect((0).to_string(radix=10), content="0") #| inspect((123).to_string(radix=10), content="123") #| inspect((-123).to_string(radix=10), content="-123") #| inspect( #| 0x7fff_ffff_ffff_ffffL.to_string(radix=10), #| content="9223372036854775807", #| ) #| inspect( #| 0x8000_0000_0000_0000L.to_string(radix=10), #| content="-9223372036854775808", #| ) #| inspect((0).to_string(radix=16), content="0") #| inspect((0x11).to_string(radix=16), content="11") #| inspect((0x15ef).to_string(radix=16), content="15ef") #| inspect((-0xabcd).to_string(radix=16), content="-abcd") #| inspect( #| (1.0 : Float).reinterpret_as_int().to_string(radix=16), #| content="3f800000", #| ) #| inspect(0U.to_string(radix=16), content="0") #| inspect(0x1AU.to_string(radix=16), content="1a") #| inspect(0xabcdU.to_string(radix=16), content="abcd") #| inspect( #| (-2.0 : Float).reinterpret_as_uint().to_string(radix=16), #| content="c0000000", #| ) #| inspect((-1).reinterpret_as_uint().to_string(radix=16), content="ffffffff") #| inspect(0L.to_string(radix=16), content="0") #| inspect(0x2fL.to_string(radix=16), content="2f") #| inspect(0xf0aeL.to_string(radix=16), content="f0ae") #| inspect((-0x1234eacbL).to_string(radix=16), content="-1234eacb") #| inspect( #| 1.0.reinterpret_as_uint64().to_string(radix=16), #| content="3ff0000000000000", #| ) #| inspect(0b101L.to_string(radix=2), content="101") #| inspect(0o17L.to_string(radix=8), content="17") #| inspect(0UL.to_string(radix=16), content="0") #| inspect(0x11UL.to_string(radix=16), content="11") #| inspect(0x12bdUL.to_string(radix=16), content="12bd") #| inspect( #| (-1L).reinterpret_as_uint64().to_string(radix=16), #| content="ffffffffffffffff", #| ) #| inspect( #| 2.0.reinterpret_as_uint64().to_string(radix=16), #| content="4000000000000000", #| ) #|} #|test "panic to_string_by_radix/illegal_radix" { #| ignore((1).to_string(radix=1)) #| ignore((1).to_string(radix=37)) #| ignore(1L.to_string(radix=0)) #| ignore(1L.to_string(radix=42)) #| ignore(1U.to_string(radix=-1)) #| ignore(1U.to_string(radix=73)) #| ignore(1UL.to_string(radix=-100)) #| ignore(1UL.to_string(radix=100)) #|} ), "traits.mbt": ( #|pub(open) trait Eq { #| op_equal(Self, Self) -> Bool #|} #|pub(open) trait Compare: Eq { #| compare(Self, Self) -> Int #|} #|pub(open) trait Hash { #| hash_combine(Self, Hasher) -> Unit #| hash(Self) -> Int = _ #|} #|impl Hash with hash(self) { #| Hasher::new()..combine(self).finalize() #|} #|pub(open) trait Default { #| default() -> Self #|} #|pub(open) trait Logger { #| write_string(Self, String) -> Unit #| write_substring(Self, String, Int, Int) -> Unit #| write_char(Self, Char) -> Unit = _ #|} #|impl Logger with write_char(self, value) { #| self.write_string([value]) #|} #|pub(open) trait Show { #| output(Self, &Logger) -> Unit #| to_string(Self) -> String = _ #|} #|impl Show with to_string(self) { #| let logger = StringBuilder::new() #| self.output(logger) #| logger.to_string() #|} #|pub fn[Obj : Show] &Logger::write_object(self : &Logger, obj : Obj) -> Unit { #| obj.output(self) #|} #|pub fn[T : Show] &Logger::write_iter( #| self : &Logger, #| iter : Iter[T], #| prefix? : String = "[", #| suffix? : String = "]", #| sep? : String = ", ", #| trailing? : Bool = false, #|) -> Unit { #| self.write_string(prefix) #| if trailing { #| for x in iter { #| self.write_object(x) #| self.write_string(sep) #| } #| } else { #| let mut first = true #| for x in iter { #| if first { #| first = false #| } else { #| self.write_string(sep) #| } #| self.write_object(x) #| } #| } #| self.write_string(suffix) #|} #|pub fn[T : Show] repr(t : T) -> String { #| let logger = StringBuilder::new() #| t.output(logger) #| logger.to_string() #|} ), "tuple_compare.mbt": ( #|pub impl[T0 : Compare, T1 : Compare] Compare for (T0, T1) with compare( #| self : (T0, T1), #| other : (T0, T1), #|) -> Int { #| let t0 = self.0.compare(other.0) #| guard t0 == 0 else { return t0 } #| self.1.compare(other.1) #|} #|pub impl[T0 : Compare, T1 : Compare, T2 : Compare] Compare for (T0, T1, T2) with compare( #| self : (T0, T1, T2), #| other : (T0, T1, T2), #|) -> Int { #| let t0 = self.0.compare(other.0) #| guard t0 == 0 else { return t0 } #| let t1 = self.1.compare(other.1) #| guard t1 == 0 else { return t1 } #| self.2.compare(other.2) #|} #|pub impl[T0 : Compare, T1 : Compare, T2 : Compare, T3 : Compare] Compare for ( #| T0, #| T1, #| T2, #| T3, #|) with compare(self : (T0, T1, T2, T3), other : (T0, T1, T2, T3)) -> Int { #| let t0 = self.0.compare(other.0) #| guard t0 == 0 else { return t0 } #| let t1 = self.1.compare(other.1) #| guard t1 == 0 else { return t1 } #| let t2 = self.2.compare(other.2) #| guard t2 == 0 else { return t2 } #| self.3.compare(other.3) #|} #|pub impl[T0 : Compare, T1 : Compare, T2 : Compare, T3 : Compare, T4 : Compare] Compare for ( #| T0, #| T1, #| T2, #| T3, #| T4, #|) with compare(self : (T0, T1, T2, T3, T4), other : (T0, T1, T2, T3, T4)) -> Int { #| let t0 = self.0.compare(other.0) #| guard t0 == 0 else { return t0 } #| let t1 = self.1.compare(other.1) #| guard t1 == 0 else { return t1 } #| let t2 = self.2.compare(other.2) #| guard t2 == 0 else { return t2 } #| let t3 = self.3.compare(other.3) #| guard t3 == 0 else { return t3 } #| self.4.compare(other.4) #|} #|pub impl[ #| T0 : Compare, #| T1 : Compare, #| T2 : Compare, #| T3 : Compare, #| T4 : Compare, #| T5 : Compare, #|] Compare for (T0, T1, T2, T3, T4, T5) with compare( #| self : (T0, T1, T2, T3, T4, T5), #| other : (T0, T1, T2, T3, T4, T5), #|) -> Int { #| let t0 = self.0.compare(other.0) #| guard t0 == 0 else { return t0 } #| let t1 = self.1.compare(other.1) #| guard t1 == 0 else { return t1 } #| let t2 = self.2.compare(other.2) #| guard t2 == 0 else { return t2 } #| let t3 = self.3.compare(other.3) #| guard t3 == 0 else { return t3 } #| let t4 = self.4.compare(other.4) #| guard t4 == 0 else { return t4 } #| self.5.compare(other.5) #|} #|pub impl[ #| T0 : Compare, #| T1 : Compare, #| T2 : Compare, #| T3 : Compare, #| T4 : Compare, #| T5 : Compare, #| T6 : Compare, #|] Compare for (T0, T1, T2, T3, T4, T5, T6) with compare( #| self : (T0, T1, T2, T3, T4, T5, T6), #| other : (T0, T1, T2, T3, T4, T5, T6), #|) -> Int { #| let t0 = self.0.compare(other.0) #| guard t0 == 0 else { return t0 } #| let t1 = self.1.compare(other.1) #| guard t1 == 0 else { return t1 } #| let t2 = self.2.compare(other.2) #| guard t2 == 0 else { return t2 } #| let t3 = self.3.compare(other.3) #| guard t3 == 0 else { return t3 } #| let t4 = self.4.compare(other.4) #| guard t4 == 0 else { return t4 } #| let t5 = self.5.compare(other.5) #| guard t5 == 0 else { return t5 } #| self.6.compare(other.6) #|} #|pub impl[ #| T0 : Compare, #| T1 : Compare, #| T2 : Compare, #| T3 : Compare, #| T4 : Compare, #| T5 : Compare, #| T6 : Compare, #| T7 : Compare, #|] Compare for (T0, T1, T2, T3, T4, T5, T6, T7) with compare( #| self : (T0, T1, T2, T3, T4, T5, T6, T7), #| other : (T0, T1, T2, T3, T4, T5, T6, T7), #|) -> Int { #| let t0 = self.0.compare(other.0) #| guard t0 == 0 else { return t0 } #| let t1 = self.1.compare(other.1) #| guard t1 == 0 else { return t1 } #| let t2 = self.2.compare(other.2) #| guard t2 == 0 else { return t2 } #| let t3 = self.3.compare(other.3) #| guard t3 == 0 else { return t3 } #| let t4 = self.4.compare(other.4) #| guard t4 == 0 else { return t4 } #| let t5 = self.5.compare(other.5) #| guard t5 == 0 else { return t5 } #| let t6 = self.6.compare(other.6) #| guard t6 == 0 else { return t6 } #| self.7.compare(other.7) #|} #|pub impl[ #| T0 : Compare, #| T1 : Compare, #| T2 : Compare, #| T3 : Compare, #| T4 : Compare, #| T5 : Compare, #| T6 : Compare, #| T7 : Compare, #| T8 : Compare, #|] Compare for (T0, T1, T2, T3, T4, T5, T6, T7, T8) with compare( #| self : (T0, T1, T2, T3, T4, T5, T6, T7, T8), #| other : (T0, T1, T2, T3, T4, T5, T6, T7, T8), #|) -> Int { #| let t0 = self.0.compare(other.0) #| guard t0 == 0 else { return t0 } #| let t1 = self.1.compare(other.1) #| guard t1 == 0 else { return t1 } #| let t2 = self.2.compare(other.2) #| guard t2 == 0 else { return t2 } #| let t3 = self.3.compare(other.3) #| guard t3 == 0 else { return t3 } #| let t4 = self.4.compare(other.4) #| guard t4 == 0 else { return t4 } #| let t5 = self.5.compare(other.5) #| guard t5 == 0 else { return t5 } #| let t6 = self.6.compare(other.6) #| guard t6 == 0 else { return t6 } #| let t7 = self.7.compare(other.7) #| guard t7 == 0 else { return t7 } #| self.8.compare(other.8) #|} #|pub impl[ #| T0 : Compare, #| T1 : Compare, #| T2 : Compare, #| T3 : Compare, #| T4 : Compare, #| T5 : Compare, #| T6 : Compare, #| T7 : Compare, #| T8 : Compare, #| T9 : Compare, #|] Compare for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) with compare( #| self : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9), #| other : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9), #|) -> Int { #| let t0 = self.0.compare(other.0) #| guard t0 == 0 else { return t0 } #| let t1 = self.1.compare(other.1) #| guard t1 == 0 else { return t1 } #| let t2 = self.2.compare(other.2) #| guard t2 == 0 else { return t2 } #| let t3 = self.3.compare(other.3) #| guard t3 == 0 else { return t3 } #| let t4 = self.4.compare(other.4) #| guard t4 == 0 else { return t4 } #| let t5 = self.5.compare(other.5) #| guard t5 == 0 else { return t5 } #| let t6 = self.6.compare(other.6) #| guard t6 == 0 else { return t6 } #| let t7 = self.7.compare(other.7) #| guard t7 == 0 else { return t7 } #| let t8 = self.8.compare(other.8) #| guard t8 == 0 else { return t8 } #| self.9.compare(other.9) #|} #|pub impl[ #| T0 : Compare, #| T1 : Compare, #| T2 : Compare, #| T3 : Compare, #| T4 : Compare, #| T5 : Compare, #| T6 : Compare, #| T7 : Compare, #| T8 : Compare, #| T9 : Compare, #| T10 : Compare, #|] Compare for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) with compare( #| self : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10), #| other : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10), #|) -> Int { #| let t0 = self.0.compare(other.0) #| guard t0 == 0 else { return t0 } #| let t1 = self.1.compare(other.1) #| guard t1 == 0 else { return t1 } #| let t2 = self.2.compare(other.2) #| guard t2 == 0 else { return t2 } #| let t3 = self.3.compare(other.3) #| guard t3 == 0 else { return t3 } #| let t4 = self.4.compare(other.4) #| guard t4 == 0 else { return t4 } #| let t5 = self.5.compare(other.5) #| guard t5 == 0 else { return t5 } #| let t6 = self.6.compare(other.6) #| guard t6 == 0 else { return t6 } #| let t7 = self.7.compare(other.7) #| guard t7 == 0 else { return t7 } #| let t8 = self.8.compare(other.8) #| guard t8 == 0 else { return t8 } #| let t9 = self.9.compare(other.9) #| guard t9 == 0 else { return t9 } #| self.10.compare(other.10) #|} #|pub impl[ #| T0 : Compare, #| T1 : Compare, #| T2 : Compare, #| T3 : Compare, #| T4 : Compare, #| T5 : Compare, #| T6 : Compare, #| T7 : Compare, #| T8 : Compare, #| T9 : Compare, #| T10 : Compare, #| T11 : Compare, #|] Compare for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) with compare( #| self : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11), #| other : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11), #|) -> Int { #| let t0 = self.0.compare(other.0) #| guard t0 == 0 else { return t0 } #| let t1 = self.1.compare(other.1) #| guard t1 == 0 else { return t1 } #| let t2 = self.2.compare(other.2) #| guard t2 == 0 else { return t2 } #| let t3 = self.3.compare(other.3) #| guard t3 == 0 else { return t3 } #| let t4 = self.4.compare(other.4) #| guard t4 == 0 else { return t4 } #| let t5 = self.5.compare(other.5) #| guard t5 == 0 else { return t5 } #| let t6 = self.6.compare(other.6) #| guard t6 == 0 else { return t6 } #| let t7 = self.7.compare(other.7) #| guard t7 == 0 else { return t7 } #| let t8 = self.8.compare(other.8) #| guard t8 == 0 else { return t8 } #| let t9 = self.9.compare(other.9) #| guard t9 == 0 else { return t9 } #| let t10 = self.10.compare(other.10) #| guard t10 == 0 else { return t10 } #| self.11.compare(other.11) #|} #|pub impl[ #| T0 : Compare, #| T1 : Compare, #| T2 : Compare, #| T3 : Compare, #| T4 : Compare, #| T5 : Compare, #| T6 : Compare, #| T7 : Compare, #| T8 : Compare, #| T9 : Compare, #| T10 : Compare, #| T11 : Compare, #| T12 : Compare, #|] Compare for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) with compare( #| self : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12), #| other : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12), #|) -> Int { #| let t0 = self.0.compare(other.0) #| guard t0 == 0 else { return t0 } #| let t1 = self.1.compare(other.1) #| guard t1 == 0 else { return t1 } #| let t2 = self.2.compare(other.2) #| guard t2 == 0 else { return t2 } #| let t3 = self.3.compare(other.3) #| guard t3 == 0 else { return t3 } #| let t4 = self.4.compare(other.4) #| guard t4 == 0 else { return t4 } #| let t5 = self.5.compare(other.5) #| guard t5 == 0 else { return t5 } #| let t6 = self.6.compare(other.6) #| guard t6 == 0 else { return t6 } #| let t7 = self.7.compare(other.7) #| guard t7 == 0 else { return t7 } #| let t8 = self.8.compare(other.8) #| guard t8 == 0 else { return t8 } #| let t9 = self.9.compare(other.9) #| guard t9 == 0 else { return t9 } #| let t10 = self.10.compare(other.10) #| guard t10 == 0 else { return t10 } #| let t11 = self.11.compare(other.11) #| guard t11 == 0 else { return t11 } #| self.12.compare(other.12) #|} #|pub impl[ #| T0 : Compare, #| T1 : Compare, #| T2 : Compare, #| T3 : Compare, #| T4 : Compare, #| T5 : Compare, #| T6 : Compare, #| T7 : Compare, #| T8 : Compare, #| T9 : Compare, #| T10 : Compare, #| T11 : Compare, #| T12 : Compare, #| T13 : Compare, #|] Compare for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) with compare( #| self : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13), #| other : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13), #|) -> Int { #| let t0 = self.0.compare(other.0) #| guard t0 == 0 else { return t0 } #| let t1 = self.1.compare(other.1) #| guard t1 == 0 else { return t1 } #| let t2 = self.2.compare(other.2) #| guard t2 == 0 else { return t2 } #| let t3 = self.3.compare(other.3) #| guard t3 == 0 else { return t3 } #| let t4 = self.4.compare(other.4) #| guard t4 == 0 else { return t4 } #| let t5 = self.5.compare(other.5) #| guard t5 == 0 else { return t5 } #| let t6 = self.6.compare(other.6) #| guard t6 == 0 else { return t6 } #| let t7 = self.7.compare(other.7) #| guard t7 == 0 else { return t7 } #| let t8 = self.8.compare(other.8) #| guard t8 == 0 else { return t8 } #| let t9 = self.9.compare(other.9) #| guard t9 == 0 else { return t9 } #| let t10 = self.10.compare(other.10) #| guard t10 == 0 else { return t10 } #| let t11 = self.11.compare(other.11) #| guard t11 == 0 else { return t11 } #| let t12 = self.12.compare(other.12) #| guard t12 == 0 else { return t12 } #| self.13.compare(other.13) #|} #|pub impl[ #| T0 : Compare, #| T1 : Compare, #| T2 : Compare, #| T3 : Compare, #| T4 : Compare, #| T5 : Compare, #| T6 : Compare, #| T7 : Compare, #| T8 : Compare, #| T9 : Compare, #| T10 : Compare, #| T11 : Compare, #| T12 : Compare, #| T13 : Compare, #| T14 : Compare, #|] Compare for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) with compare( #| self : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14), #| other : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14), #|) -> Int { #| let t0 = self.0.compare(other.0) #| guard t0 == 0 else { return t0 } #| let t1 = self.1.compare(other.1) #| guard t1 == 0 else { return t1 } #| let t2 = self.2.compare(other.2) #| guard t2 == 0 else { return t2 } #| let t3 = self.3.compare(other.3) #| guard t3 == 0 else { return t3 } #| let t4 = self.4.compare(other.4) #| guard t4 == 0 else { return t4 } #| let t5 = self.5.compare(other.5) #| guard t5 == 0 else { return t5 } #| let t6 = self.6.compare(other.6) #| guard t6 == 0 else { return t6 } #| let t7 = self.7.compare(other.7) #| guard t7 == 0 else { return t7 } #| let t8 = self.8.compare(other.8) #| guard t8 == 0 else { return t8 } #| let t9 = self.9.compare(other.9) #| guard t9 == 0 else { return t9 } #| let t10 = self.10.compare(other.10) #| guard t10 == 0 else { return t10 } #| let t11 = self.11.compare(other.11) #| guard t11 == 0 else { return t11 } #| let t12 = self.12.compare(other.12) #| guard t12 == 0 else { return t12 } #| let t13 = self.13.compare(other.13) #| guard t13 == 0 else { return t13 } #| self.14.compare(other.14) #|} #|pub impl[ #| T0 : Compare, #| T1 : Compare, #| T2 : Compare, #| T3 : Compare, #| T4 : Compare, #| T5 : Compare, #| T6 : Compare, #| T7 : Compare, #| T8 : Compare, #| T9 : Compare, #| T10 : Compare, #| T11 : Compare, #| T12 : Compare, #| T13 : Compare, #| T14 : Compare, #| T15 : Compare, #|] Compare for ( #| T0, #| T1, #| T2, #| T3, #| T4, #| T5, #| T6, #| T7, #| T8, #| T9, #| T10, #| T11, #| T12, #| T13, #| T14, #| T15, #|) with compare( #| self : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15), #| other : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15), #|) -> Int { #| let t0 = self.0.compare(other.0) #| guard t0 == 0 else { return t0 } #| let t1 = self.1.compare(other.1) #| guard t1 == 0 else { return t1 } #| let t2 = self.2.compare(other.2) #| guard t2 == 0 else { return t2 } #| let t3 = self.3.compare(other.3) #| guard t3 == 0 else { return t3 } #| let t4 = self.4.compare(other.4) #| guard t4 == 0 else { return t4 } #| let t5 = self.5.compare(other.5) #| guard t5 == 0 else { return t5 } #| let t6 = self.6.compare(other.6) #| guard t6 == 0 else { return t6 } #| let t7 = self.7.compare(other.7) #| guard t7 == 0 else { return t7 } #| let t8 = self.8.compare(other.8) #| guard t8 == 0 else { return t8 } #| let t9 = self.9.compare(other.9) #| guard t9 == 0 else { return t9 } #| let t10 = self.10.compare(other.10) #| guard t10 == 0 else { return t10 } #| let t11 = self.11.compare(other.11) #| guard t11 == 0 else { return t11 } #| let t12 = self.12.compare(other.12) #| guard t12 == 0 else { return t12 } #| let t13 = self.13.compare(other.13) #| guard t13 == 0 else { return t13 } #| let t14 = self.14.compare(other.14) #| guard t14 == 0 else { return t14 } #| self.15.compare(other.15) #|} ), "tuple_eq.mbt": ( #|pub impl[T0 : Eq, T1 : Eq] Eq for (T0, T1) with op_equal( #| self : (T0, T1), #| other : (T0, T1), #|) -> Bool { #| self.0 == other.0 && self.1 == other.1 #|} #|pub impl[T0 : Eq, T1 : Eq, T2 : Eq] Eq for (T0, T1, T2) with op_equal( #| self : (T0, T1, T2), #| other : (T0, T1, T2), #|) -> Bool { #| self.0 == other.0 && self.1 == other.1 && self.2 == other.2 #|} #|pub impl[T0 : Eq, T1 : Eq, T2 : Eq, T3 : Eq] Eq for (T0, T1, T2, T3) with op_equal( #| self : (T0, T1, T2, T3), #| other : (T0, T1, T2, T3), #|) -> Bool { #| self.0 == other.0 && #| self.1 == other.1 && #| self.2 == other.2 && #| self.3 == other.3 #|} #|pub impl[T0 : Eq, T1 : Eq, T2 : Eq, T3 : Eq, T4 : Eq] Eq for ( #| T0, #| T1, #| T2, #| T3, #| T4, #|) with op_equal(self : (T0, T1, T2, T3, T4), other : (T0, T1, T2, T3, T4)) -> Bool { #| self.0 == other.0 && #| self.1 == other.1 && #| self.2 == other.2 && #| self.3 == other.3 && #| self.4 == other.4 #|} #|pub impl[T0 : Eq, T1 : Eq, T2 : Eq, T3 : Eq, T4 : Eq, T5 : Eq] Eq for ( #| T0, #| T1, #| T2, #| T3, #| T4, #| T5, #|) with op_equal( #| self : (T0, T1, T2, T3, T4, T5), #| other : (T0, T1, T2, T3, T4, T5), #|) -> Bool { #| self.0 == other.0 && #| self.1 == other.1 && #| self.2 == other.2 && #| self.3 == other.3 && #| self.4 == other.4 && #| self.5 == other.5 #|} #|pub impl[T0 : Eq, T1 : Eq, T2 : Eq, T3 : Eq, T4 : Eq, T5 : Eq, T6 : Eq] Eq for ( #| T0, #| T1, #| T2, #| T3, #| T4, #| T5, #| T6, #|) with op_equal( #| self : (T0, T1, T2, T3, T4, T5, T6), #| other : (T0, T1, T2, T3, T4, T5, T6), #|) -> Bool { #| self.0 == other.0 && #| self.1 == other.1 && #| self.2 == other.2 && #| self.3 == other.3 && #| self.4 == other.4 && #| self.5 == other.5 && #| self.6 == other.6 #|} #|pub impl[T0 : Eq, T1 : Eq, T2 : Eq, T3 : Eq, T4 : Eq, T5 : Eq, T6 : Eq, T7 : Eq] Eq for ( #| T0, #| T1, #| T2, #| T3, #| T4, #| T5, #| T6, #| T7, #|) with op_equal( #| self : (T0, T1, T2, T3, T4, T5, T6, T7), #| other : (T0, T1, T2, T3, T4, T5, T6, T7), #|) -> Bool { #| self.0 == other.0 && #| self.1 == other.1 && #| self.2 == other.2 && #| self.3 == other.3 && #| self.4 == other.4 && #| self.5 == other.5 && #| self.6 == other.6 && #| self.7 == other.7 #|} #|pub impl[ #| T0 : Eq, #| T1 : Eq, #| T2 : Eq, #| T3 : Eq, #| T4 : Eq, #| T5 : Eq, #| T6 : Eq, #| T7 : Eq, #| T8 : Eq, #|] Eq for (T0, T1, T2, T3, T4, T5, T6, T7, T8) with op_equal( #| self : (T0, T1, T2, T3, T4, T5, T6, T7, T8), #| other : (T0, T1, T2, T3, T4, T5, T6, T7, T8), #|) -> Bool { #| self.0 == other.0 && #| self.1 == other.1 && #| self.2 == other.2 && #| self.3 == other.3 && #| self.4 == other.4 && #| self.5 == other.5 && #| self.6 == other.6 && #| self.7 == other.7 && #| self.8 == other.8 #|} #|pub impl[ #| T0 : Eq, #| T1 : Eq, #| T2 : Eq, #| T3 : Eq, #| T4 : Eq, #| T5 : Eq, #| T6 : Eq, #| T7 : Eq, #| T8 : Eq, #| T9 : Eq, #|] Eq for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) with op_equal( #| self : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9), #| other : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9), #|) -> Bool { #| self.0 == other.0 && #| self.1 == other.1 && #| self.2 == other.2 && #| self.3 == other.3 && #| self.4 == other.4 && #| self.5 == other.5 && #| self.6 == other.6 && #| self.7 == other.7 && #| self.8 == other.8 && #| self.9 == other.9 #|} #|pub impl[ #| T0 : Eq, #| T1 : Eq, #| T2 : Eq, #| T3 : Eq, #| T4 : Eq, #| T5 : Eq, #| T6 : Eq, #| T7 : Eq, #| T8 : Eq, #| T9 : Eq, #| T10 : Eq, #|] Eq for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) with op_equal( #| self : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10), #| other : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10), #|) -> Bool { #| self.0 == other.0 && #| self.1 == other.1 && #| self.2 == other.2 && #| self.3 == other.3 && #| self.4 == other.4 && #| self.5 == other.5 && #| self.6 == other.6 && #| self.7 == other.7 && #| self.8 == other.8 && #| self.9 == other.9 && #| self.10 == other.10 #|} #|pub impl[ #| T0 : Eq, #| T1 : Eq, #| T2 : Eq, #| T3 : Eq, #| T4 : Eq, #| T5 : Eq, #| T6 : Eq, #| T7 : Eq, #| T8 : Eq, #| T9 : Eq, #| T10 : Eq, #| T11 : Eq, #|] Eq for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) with op_equal( #| self : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11), #| other : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11), #|) -> Bool { #| self.0 == other.0 && #| self.1 == other.1 && #| self.2 == other.2 && #| self.3 == other.3 && #| self.4 == other.4 && #| self.5 == other.5 && #| self.6 == other.6 && #| self.7 == other.7 && #| self.8 == other.8 && #| self.9 == other.9 && #| self.10 == other.10 && #| self.11 == other.11 #|} #|pub impl[ #| T0 : Eq, #| T1 : Eq, #| T2 : Eq, #| T3 : Eq, #| T4 : Eq, #| T5 : Eq, #| T6 : Eq, #| T7 : Eq, #| T8 : Eq, #| T9 : Eq, #| T10 : Eq, #| T11 : Eq, #| T12 : Eq, #|] Eq for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) with op_equal( #| self : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12), #| other : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12), #|) -> Bool { #| self.0 == other.0 && #| self.1 == other.1 && #| self.2 == other.2 && #| self.3 == other.3 && #| self.4 == other.4 && #| self.5 == other.5 && #| self.6 == other.6 && #| self.7 == other.7 && #| self.8 == other.8 && #| self.9 == other.9 && #| self.10 == other.10 && #| self.11 == other.11 && #| self.12 == other.12 #|} #|pub impl[ #| T0 : Eq, #| T1 : Eq, #| T2 : Eq, #| T3 : Eq, #| T4 : Eq, #| T5 : Eq, #| T6 : Eq, #| T7 : Eq, #| T8 : Eq, #| T9 : Eq, #| T10 : Eq, #| T11 : Eq, #| T12 : Eq, #| T13 : Eq, #|] Eq for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) with op_equal( #| self : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13), #| other : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13), #|) -> Bool { #| self.0 == other.0 && #| self.1 == other.1 && #| self.2 == other.2 && #| self.3 == other.3 && #| self.4 == other.4 && #| self.5 == other.5 && #| self.6 == other.6 && #| self.7 == other.7 && #| self.8 == other.8 && #| self.9 == other.9 && #| self.10 == other.10 && #| self.11 == other.11 && #| self.12 == other.12 && #| self.13 == other.13 #|} #|pub impl[ #| T0 : Eq, #| T1 : Eq, #| T2 : Eq, #| T3 : Eq, #| T4 : Eq, #| T5 : Eq, #| T6 : Eq, #| T7 : Eq, #| T8 : Eq, #| T9 : Eq, #| T10 : Eq, #| T11 : Eq, #| T12 : Eq, #| T13 : Eq, #| T14 : Eq, #|] Eq for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) with op_equal( #| self : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14), #| other : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14), #|) -> Bool { #| self.0 == other.0 && #| self.1 == other.1 && #| self.2 == other.2 && #| self.3 == other.3 && #| self.4 == other.4 && #| self.5 == other.5 && #| self.6 == other.6 && #| self.7 == other.7 && #| self.8 == other.8 && #| self.9 == other.9 && #| self.10 == other.10 && #| self.11 == other.11 && #| self.12 == other.12 && #| self.13 == other.13 && #| self.14 == other.14 #|} #|pub impl[ #| T0 : Eq, #| T1 : Eq, #| T2 : Eq, #| T3 : Eq, #| T4 : Eq, #| T5 : Eq, #| T6 : Eq, #| T7 : Eq, #| T8 : Eq, #| T9 : Eq, #| T10 : Eq, #| T11 : Eq, #| T12 : Eq, #| T13 : Eq, #| T14 : Eq, #| T15 : Eq, #|] Eq for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) with op_equal( #| self : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15), #| other : (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15), #|) -> Bool { #| self.0 == other.0 && #| self.1 == other.1 && #| self.2 == other.2 && #| self.3 == other.3 && #| self.4 == other.4 && #| self.5 == other.5 && #| self.6 == other.6 && #| self.7 == other.7 && #| self.8 == other.8 && #| self.9 == other.9 && #| self.10 == other.10 && #| self.11 == other.11 && #| self.12 == other.12 && #| self.13 == other.13 && #| self.14 == other.14 && #| self.15 == other.15 #|} ), "tuple_hash.mbt": ( #|pub impl[A : Hash, B : Hash] Hash for (A, B) with hash_combine(self, hasher) { #| let (a, b) = self #| hasher..combine(a)..combine(b) #|} #|pub impl[A : Hash, B : Hash, C : Hash] Hash for (A, B, C) with hash_combine( #| self, #| hasher, #|) { #| let (a, b, c) = self #| hasher..combine(a)..combine(b)..combine(c) #|} #|pub impl[A : Hash, B : Hash, C : Hash, D : Hash] Hash for (A, B, C, D) with hash_combine( #| self, #| hasher, #|) { #| let (a, b, c, d) = self #| hasher..combine(a)..combine(b)..combine(c)..combine(d) #|} #|pub impl[A : Hash, B : Hash, C : Hash, D : Hash, E : Hash] Hash for ( #| A, #| B, #| C, #| D, #| E, #|) with hash_combine(self, hasher) { #| let (a, b, c, d, e) = self #| hasher..combine(a)..combine(b)..combine(c)..combine(d)..combine(e) #|} #|pub impl[A : Hash, B : Hash, C : Hash, D : Hash, E : Hash, F : Hash] Hash for ( #| A, #| B, #| C, #| D, #| E, #| F, #|) with hash_combine(self, hasher) { #| let (a, b, c, d, e, f) = self #| hasher..combine(a)..combine(b)..combine(c)..combine(d)..combine(e)..combine(f) #|} #|pub impl[A : Hash, B : Hash, C : Hash, D : Hash, E : Hash, F : Hash, G : Hash] Hash for ( #| A, #| B, #| C, #| D, #| E, #| F, #| G, #|) with hash_combine(self, hasher) { #| let (a, b, c, d, e, f, g) = self #| hasher #| ..combine(a) #| ..combine(b) #| ..combine(c) #| ..combine(d) #| ..combine(e) #| ..combine(f) #| ..combine(g) #|} ), "tuple_show.mbt": ( #|pub impl[A : Show, B : Show] Show for (A, B) with output(self, logger) { #| let (a, b) = self #| logger #| ..write_string("(") #| ..write_object(a) #| ..write_string(", ") #| ..write_object(b) #| ..write_string(")") #|} #|pub impl[A : Show, B : Show, C : Show] Show for (A, B, C) with output( #| self, #| logger, #|) { #| let (a, b, c) = self #| logger #| ..write_string("(") #| ..write_object(a) #| ..write_string(", ") #| ..write_object(b) #| ..write_string(", ") #| ..write_object(c) #| ..write_string(")") #|} #|pub impl[A : Show, B : Show, C : Show, D : Show] Show for (A, B, C, D) with output( #| self, #| logger, #|) { #| let (a, b, c, d) = self #| logger #| ..write_string("(") #| ..write_object(a) #| ..write_string(", ") #| ..write_object(b) #| ..write_string(", ") #| ..write_object(c) #| ..write_string(", ") #| ..write_object(d) #| ..write_string(")") #|} #|pub impl[A : Show, B : Show, C : Show, D : Show, E : Show] Show for ( #| A, #| B, #| C, #| D, #| E, #|) with output(self, logger) { #| let (a, b, c, d, e) = self #| logger #| ..write_string("(") #| ..write_object(a) #| ..write_string(", ") #| ..write_object(b) #| ..write_string(", ") #| ..write_object(c) #| ..write_string(", ") #| ..write_object(d) #| ..write_string(", ") #| ..write_object(e) #| ..write_string(")") #|} #|pub impl[A : Show, B : Show, C : Show, D : Show, E : Show, F : Show] Show for ( #| A, #| B, #| C, #| D, #| E, #| F, #|) with output(self, logger) { #| let (a, b, c, d, e, f) = self #| logger #| ..write_string("(") #| ..write_object(a) #| ..write_string(", ") #| ..write_object(b) #| ..write_string(", ") #| ..write_object(c) #| ..write_string(", ") #| ..write_object(d) #| ..write_string(", ") #| ..write_object(e) #| ..write_string(", ") #| ..write_object(f) #| ..write_string(")") #|} #|pub impl[A : Show, B : Show, C : Show, D : Show, E : Show, F : Show, G : Show] Show for ( #| A, #| B, #| C, #| D, #| E, #| F, #| G, #|) with output(self, logger) { #| let (a, b, c, d, e, f, g) = self #| logger #| ..write_string("(") #| ..write_object(a) #| ..write_string(", ") #| ..write_object(b) #| ..write_string(", ") #| ..write_object(c) #| ..write_string(", ") #| ..write_object(d) #| ..write_string(", ") #| ..write_object(e) #| ..write_string(", ") #| ..write_object(f) #| ..write_string(", ") #| ..write_object(g) #| ..write_string(")") #|} #|pub impl[ #| T0 : Show, #| T1 : Show, #| T2 : Show, #| T3 : Show, #| T4 : Show, #| T5 : Show, #| T6 : Show, #| T7 : Show, #|] Show for (T0, T1, T2, T3, T4, T5, T6, T7) with output(self, logger) { #| let (x0, x1, x2, x3, x4, x5, x6, x7) = self #| logger #| ..write_string("(") #| ..write_object(x0) #| ..write_string(", ") #| ..write_object(x1) #| ..write_string(", ") #| ..write_object(x2) #| ..write_string(", ") #| ..write_object(x3) #| ..write_string(", ") #| ..write_object(x4) #| ..write_string(", ") #| ..write_object(x5) #| ..write_string(", ") #| ..write_object(x6) #| ..write_string(", ") #| ..write_object(x7) #| ..write_string(")") #|} #|pub impl[ #| T0 : Show, #| T1 : Show, #| T2 : Show, #| T3 : Show, #| T4 : Show, #| T5 : Show, #| T6 : Show, #| T7 : Show, #| T8 : Show, #|] Show for (T0, T1, T2, T3, T4, T5, T6, T7, T8) with output(self, logger) { #| let (x0, x1, x2, x3, x4, x5, x6, x7, x8) = self #| logger #| ..write_string("(") #| ..write_object(x0) #| ..write_string(", ") #| ..write_object(x1) #| ..write_string(", ") #| ..write_object(x2) #| ..write_string(", ") #| ..write_object(x3) #| ..write_string(", ") #| ..write_object(x4) #| ..write_string(", ") #| ..write_object(x5) #| ..write_string(", ") #| ..write_object(x6) #| ..write_string(", ") #| ..write_object(x7) #| ..write_string(", ") #| ..write_object(x8) #| ..write_string(")") #|} #|pub impl[ #| T0 : Show, #| T1 : Show, #| T2 : Show, #| T3 : Show, #| T4 : Show, #| T5 : Show, #| T6 : Show, #| T7 : Show, #| T8 : Show, #| T9 : Show, #|] Show for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) with output(self, logger) { #| let (x0, x1, x2, x3, x4, x5, x6, x7, x8, x9) = self #| logger #| ..write_string("(") #| ..write_object(x0) #| ..write_string(", ") #| ..write_object(x1) #| ..write_string(", ") #| ..write_object(x2) #| ..write_string(", ") #| ..write_object(x3) #| ..write_string(", ") #| ..write_object(x4) #| ..write_string(", ") #| ..write_object(x5) #| ..write_string(", ") #| ..write_object(x6) #| ..write_string(", ") #| ..write_object(x7) #| ..write_string(", ") #| ..write_object(x8) #| ..write_string(", ") #| ..write_object(x9) #| ..write_string(")") #|} #|pub impl[ #| T0 : Show, #| T1 : Show, #| T2 : Show, #| T3 : Show, #| T4 : Show, #| T5 : Show, #| T6 : Show, #| T7 : Show, #| T8 : Show, #| T9 : Show, #| T10 : Show, #|] Show for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) with output( #| self, #| logger, #|) { #| let (x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10) = self #| logger #| ..write_string("(") #| ..write_object(x0) #| ..write_string(", ") #| ..write_object(x1) #| ..write_string(", ") #| ..write_object(x2) #| ..write_string(", ") #| ..write_object(x3) #| ..write_string(", ") #| ..write_object(x4) #| ..write_string(", ") #| ..write_object(x5) #| ..write_string(", ") #| ..write_object(x6) #| ..write_string(", ") #| ..write_object(x7) #| ..write_string(", ") #| ..write_object(x8) #| ..write_string(", ") #| ..write_object(x9) #| ..write_string(", ") #| ..write_object(x10) #| ..write_string(")") #|} #|pub impl[ #| T0 : Show, #| T1 : Show, #| T2 : Show, #| T3 : Show, #| T4 : Show, #| T5 : Show, #| T6 : Show, #| T7 : Show, #| T8 : Show, #| T9 : Show, #| T10 : Show, #| T11 : Show, #|] Show for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) with output( #| self, #| logger, #|) { #| let (x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11) = self #| logger #| ..write_string("(") #| ..write_object(x0) #| ..write_string(", ") #| ..write_object(x1) #| ..write_string(", ") #| ..write_object(x2) #| ..write_string(", ") #| ..write_object(x3) #| ..write_string(", ") #| ..write_object(x4) #| ..write_string(", ") #| ..write_object(x5) #| ..write_string(", ") #| ..write_object(x6) #| ..write_string(", ") #| ..write_object(x7) #| ..write_string(", ") #| ..write_object(x8) #| ..write_string(", ") #| ..write_object(x9) #| ..write_string(", ") #| ..write_object(x10) #| ..write_string(", ") #| ..write_object(x11) #| ..write_string(")") #|} #|pub impl[ #| T0 : Show, #| T1 : Show, #| T2 : Show, #| T3 : Show, #| T4 : Show, #| T5 : Show, #| T6 : Show, #| T7 : Show, #| T8 : Show, #| T9 : Show, #| T10 : Show, #| T11 : Show, #| T12 : Show, #|] Show for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) with output( #| self, #| logger, #|) { #| let (x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12) = self #| logger #| ..write_string("(") #| ..write_object(x0) #| ..write_string(", ") #| ..write_object(x1) #| ..write_string(", ") #| ..write_object(x2) #| ..write_string(", ") #| ..write_object(x3) #| ..write_string(", ") #| ..write_object(x4) #| ..write_string(", ") #| ..write_object(x5) #| ..write_string(", ") #| ..write_object(x6) #| ..write_string(", ") #| ..write_object(x7) #| ..write_string(", ") #| ..write_object(x8) #| ..write_string(", ") #| ..write_object(x9) #| ..write_string(", ") #| ..write_object(x10) #| ..write_string(", ") #| ..write_object(x11) #| ..write_string(", ") #| ..write_object(x12) #| ..write_string(")") #|} #|pub impl[ #| T0 : Show, #| T1 : Show, #| T2 : Show, #| T3 : Show, #| T4 : Show, #| T5 : Show, #| T6 : Show, #| T7 : Show, #| T8 : Show, #| T9 : Show, #| T10 : Show, #| T11 : Show, #| T12 : Show, #| T13 : Show, #|] Show for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) with output( #| self, #| logger, #|) { #| let (x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13) = self #| logger #| ..write_string("(") #| ..write_object(x0) #| ..write_string(", ") #| ..write_object(x1) #| ..write_string(", ") #| ..write_object(x2) #| ..write_string(", ") #| ..write_object(x3) #| ..write_string(", ") #| ..write_object(x4) #| ..write_string(", ") #| ..write_object(x5) #| ..write_string(", ") #| ..write_object(x6) #| ..write_string(", ") #| ..write_object(x7) #| ..write_string(", ") #| ..write_object(x8) #| ..write_string(", ") #| ..write_object(x9) #| ..write_string(", ") #| ..write_object(x10) #| ..write_string(", ") #| ..write_object(x11) #| ..write_string(", ") #| ..write_object(x12) #| ..write_string(", ") #| ..write_object(x13) #| ..write_string(")") #|} #|pub impl[ #| T0 : Show, #| T1 : Show, #| T2 : Show, #| T3 : Show, #| T4 : Show, #| T5 : Show, #| T6 : Show, #| T7 : Show, #| T8 : Show, #| T9 : Show, #| T10 : Show, #| T11 : Show, #| T12 : Show, #| T13 : Show, #| T14 : Show, #|] Show for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) with output( #| self, #| logger, #|) { #| let (x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14) = self #| logger #| ..write_string("(") #| ..write_object(x0) #| ..write_string(", ") #| ..write_object(x1) #| ..write_string(", ") #| ..write_object(x2) #| ..write_string(", ") #| ..write_object(x3) #| ..write_string(", ") #| ..write_object(x4) #| ..write_string(", ") #| ..write_object(x5) #| ..write_string(", ") #| ..write_object(x6) #| ..write_string(", ") #| ..write_object(x7) #| ..write_string(", ") #| ..write_object(x8) #| ..write_string(", ") #| ..write_object(x9) #| ..write_string(", ") #| ..write_object(x10) #| ..write_string(", ") #| ..write_object(x11) #| ..write_string(", ") #| ..write_object(x12) #| ..write_string(", ") #| ..write_object(x13) #| ..write_string(", ") #| ..write_object(x14) #| ..write_string(")") #|} #|pub impl[ #| T0 : Show, #| T1 : Show, #| T2 : Show, #| T3 : Show, #| T4 : Show, #| T5 : Show, #| T6 : Show, #| T7 : Show, #| T8 : Show, #| T9 : Show, #| T10 : Show, #| T11 : Show, #| T12 : Show, #| T13 : Show, #| T14 : Show, #| T15 : Show, #|] Show for ( #| T0, #| T1, #| T2, #| T3, #| T4, #| T5, #| T6, #| T7, #| T8, #| T9, #| T10, #| T11, #| T12, #| T13, #| T14, #| T15, #|) with output(self, logger) { #| let (x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15) = self #| logger #| ..write_string("(") #| ..write_object(x0) #| ..write_string(", ") #| ..write_object(x1) #| ..write_string(", ") #| ..write_object(x2) #| ..write_string(", ") #| ..write_object(x3) #| ..write_string(", ") #| ..write_object(x4) #| ..write_string(", ") #| ..write_object(x5) #| ..write_string(", ") #| ..write_object(x6) #| ..write_string(", ") #| ..write_object(x7) #| ..write_string(", ") #| ..write_object(x8) #| ..write_string(", ") #| ..write_object(x9) #| ..write_string(", ") #| ..write_object(x10) #| ..write_string(", ") #| ..write_object(x11) #| ..write_string(", ") #| ..write_object(x12) #| ..write_string(", ") #| ..write_object(x13) #| ..write_string(", ") #| ..write_object(x14) #| ..write_string(", ") #| ..write_object(x15) #| ..write_string(")") #|} ), "tuple_to_json.mbt": ( #|pub impl[A : ToJson, B : ToJson] ToJson for (A, B) with to_json(self) { #| [self.0.to_json(), self.1.to_json()] #|} #|pub impl[A : ToJson, B : ToJson, C : ToJson] ToJson for (A, B, C) with to_json( #| self, #|) { #| [self.0.to_json(), self.1.to_json(), self.2.to_json()] #|} #|pub impl[A : ToJson, B : ToJson, C : ToJson, D : ToJson] ToJson for (A, B, C, D) with to_json( #| self, #|) { #| [self.0.to_json(), self.1.to_json(), self.2.to_json(), self.3.to_json()] #|} #|pub impl[A : ToJson, B : ToJson, C : ToJson, D : ToJson, E : ToJson] ToJson for ( #| A, #| B, #| C, #| D, #| E, #|) with to_json(self) { #| [ #| self.0.to_json(), #| self.1.to_json(), #| self.2.to_json(), #| self.3.to_json(), #| self.4.to_json(), #| ] #|} #|pub impl[A : ToJson, B : ToJson, C : ToJson, D : ToJson, E : ToJson, F : ToJson] ToJson for ( #| A, #| B, #| C, #| D, #| E, #| F, #|) with to_json(self) { #| [ #| self.0.to_json(), #| self.1.to_json(), #| self.2.to_json(), #| self.3.to_json(), #| self.4.to_json(), #| self.5.to_json(), #| ] #|} #|pub impl[ #| A : ToJson, #| B : ToJson, #| C : ToJson, #| D : ToJson, #| E : ToJson, #| F : ToJson, #| G : ToJson, #|] ToJson for (A, B, C, D, E, F, G) with to_json(self) { #| [ #| self.0.to_json(), #| self.1.to_json(), #| self.2.to_json(), #| self.3.to_json(), #| self.4.to_json(), #| self.5.to_json(), #| self.6.to_json(), #| ] #|} #|pub impl[ #| A : ToJson, #| B : ToJson, #| C : ToJson, #| D : ToJson, #| E : ToJson, #| F : ToJson, #| G : ToJson, #| H : ToJson, #|] ToJson for (A, B, C, D, E, F, G, H) with to_json(self) { #| [ #| self.0.to_json(), #| self.1.to_json(), #| self.2.to_json(), #| self.3.to_json(), #| self.4.to_json(), #| self.5.to_json(), #| self.6.to_json(), #| self.7.to_json(), #| ] #|} #|pub impl[ #| A : ToJson, #| B : ToJson, #| C : ToJson, #| D : ToJson, #| E : ToJson, #| F : ToJson, #| G : ToJson, #| H : ToJson, #| I : ToJson, #|] ToJson for (A, B, C, D, E, F, G, H, I) with to_json(self) { #| [ #| self.0.to_json(), #| self.1.to_json(), #| self.2.to_json(), #| self.3.to_json(), #| self.4.to_json(), #| self.5.to_json(), #| self.6.to_json(), #| self.7.to_json(), #| self.8.to_json(), #| ] #|} #|pub impl[ #| A : ToJson, #| B : ToJson, #| C : ToJson, #| D : ToJson, #| E : ToJson, #| F : ToJson, #| G : ToJson, #| H : ToJson, #| I : ToJson, #| J : ToJson, #|] ToJson for (A, B, C, D, E, F, G, H, I, J) with to_json(self) { #| [ #| self.0.to_json(), #| self.1.to_json(), #| self.2.to_json(), #| self.3.to_json(), #| self.4.to_json(), #| self.5.to_json(), #| self.6.to_json(), #| self.7.to_json(), #| self.8.to_json(), #| self.9.to_json(), #| ] #|} #|pub impl[ #| A : ToJson, #| B : ToJson, #| C : ToJson, #| D : ToJson, #| E : ToJson, #| F : ToJson, #| G : ToJson, #| H : ToJson, #| I : ToJson, #| J : ToJson, #| K : ToJson, #|] ToJson for (A, B, C, D, E, F, G, H, I, J, K) with to_json(self) { #| [ #| self.0.to_json(), #| self.1.to_json(), #| self.2.to_json(), #| self.3.to_json(), #| self.4.to_json(), #| self.5.to_json(), #| self.6.to_json(), #| self.7.to_json(), #| self.8.to_json(), #| self.9.to_json(), #| self.10.to_json(), #| ] #|} #|pub impl[ #| A : ToJson, #| B : ToJson, #| C : ToJson, #| D : ToJson, #| E : ToJson, #| F : ToJson, #| G : ToJson, #| H : ToJson, #| I : ToJson, #| J : ToJson, #| K : ToJson, #| L : ToJson, #|] ToJson for (A, B, C, D, E, F, G, H, I, J, K, L) with to_json(self) { #| [ #| self.0.to_json(), #| self.1.to_json(), #| self.2.to_json(), #| self.3.to_json(), #| self.4.to_json(), #| self.5.to_json(), #| self.6.to_json(), #| self.7.to_json(), #| self.8.to_json(), #| self.9.to_json(), #| self.10.to_json(), #| self.11.to_json(), #| ] #|} #|pub impl[ #| A : ToJson, #| B : ToJson, #| C : ToJson, #| D : ToJson, #| E : ToJson, #| F : ToJson, #| G : ToJson, #| H : ToJson, #| I : ToJson, #| J : ToJson, #| K : ToJson, #| L : ToJson, #| M : ToJson, #|] ToJson for (A, B, C, D, E, F, G, H, I, J, K, L, M) with to_json(self) { #| [ #| self.0.to_json(), #| self.1.to_json(), #| self.2.to_json(), #| self.3.to_json(), #| self.4.to_json(), #| self.5.to_json(), #| self.6.to_json(), #| self.7.to_json(), #| self.8.to_json(), #| self.9.to_json(), #| self.10.to_json(), #| self.11.to_json(), #| self.12.to_json(), #| ] #|} #|pub impl[ #| A : ToJson, #| B : ToJson, #| C : ToJson, #| D : ToJson, #| E : ToJson, #| F : ToJson, #| G : ToJson, #| H : ToJson, #| I : ToJson, #| J : ToJson, #| K : ToJson, #| L : ToJson, #| M : ToJson, #| N : ToJson, #|] ToJson for (A, B, C, D, E, F, G, H, I, J, K, L, M, N) with to_json(self) { #| [ #| self.0.to_json(), #| self.1.to_json(), #| self.2.to_json(), #| self.3.to_json(), #| self.4.to_json(), #| self.5.to_json(), #| self.6.to_json(), #| self.7.to_json(), #| self.8.to_json(), #| self.9.to_json(), #| self.10.to_json(), #| self.11.to_json(), #| self.12.to_json(), #| self.13.to_json(), #| ] #|} #|pub impl[ #| A : ToJson, #| B : ToJson, #| C : ToJson, #| D : ToJson, #| E : ToJson, #| F : ToJson, #| G : ToJson, #| H : ToJson, #| I : ToJson, #| J : ToJson, #| K : ToJson, #| L : ToJson, #| M : ToJson, #| N : ToJson, #| O : ToJson, #|] ToJson for (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) with to_json(self) { #| [ #| self.0.to_json(), #| self.1.to_json(), #| self.2.to_json(), #| self.3.to_json(), #| self.4.to_json(), #| self.5.to_json(), #| self.6.to_json(), #| self.7.to_json(), #| self.8.to_json(), #| self.9.to_json(), #| self.10.to_json(), #| self.11.to_json(), #| self.12.to_json(), #| self.13.to_json(), #| self.14.to_json(), #| ] #|} #|pub impl[ #| A : ToJson, #| B : ToJson, #| C : ToJson, #| D : ToJson, #| E : ToJson, #| F : ToJson, #| G : ToJson, #| H : ToJson, #| I : ToJson, #| J : ToJson, #| K : ToJson, #| L : ToJson, #| M : ToJson, #| N : ToJson, #| O : ToJson, #| P : ToJson, #|] ToJson for (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) with to_json(self) { #| [ #| self.0.to_json(), #| self.1.to_json(), #| self.2.to_json(), #| self.3.to_json(), #| self.4.to_json(), #| self.5.to_json(), #| self.6.to_json(), #| self.7.to_json(), #| self.8.to_json(), #| self.9.to_json(), #| self.10.to_json(), #| self.11.to_json(), #| self.12.to_json(), #| self.13.to_json(), #| self.14.to_json(), #| self.15.to_json(), #| ] #|} ), "uint64.mbt": ( #|pub impl Default for UInt64 with default() { #| 0 #|} #|test { #| inspect(0x7000_0001_1F00_100FUL.popcnt(), content="14") #|} ), "uninitialized_array.mbt": ( #|struct UninitializedArray[T](FixedArray[UnsafeMaybeUninit[T]]) #|pub fn[T] UninitializedArray::make(size : Int) -> UninitializedArray[T] = "%fixedarray.make_uninit" #|pub fn[T] UninitializedArray::op_get( #| self : UninitializedArray[T], #| index : Int, #|) -> T = "%fixedarray.get" #|pub fn[T] UninitializedArray::op_set( #| self : UninitializedArray[T], #| index : Int, #| value : T, #|) = "%fixedarray.set" #|pub fn[T] UninitializedArray::op_as_view( #| self : UninitializedArray[T], #| start? : Int = 0, #| end? : Int, #|) -> ArrayView[T] { #| let len = self.length() #| let end = match end { #| None => len #| Some(end) => end #| } #| guard start >= 0 && start <= end && end <= len else { #| abort("View start index out of bounds") #| } #| ArrayView::make(self, start, end - start) #|} #|pub fn[A] UninitializedArray::length(self : UninitializedArray[A]) -> Int { #| let UninitializedArray(self) = self #| self.length() #|} #|#internal(unsafe, "For internal use only.") #|pub fn[T] UninitializedArray::unsafe_blit( #| dst : UninitializedArray[T], #| dst_offset : Int, #| src : UninitializedArray[T], #| src_offset : Int, #| len : Int, #|) -> Unit { #| FixedArray::unsafe_blit(dst.0, dst_offset, src.0, src_offset, len) #|} #|test "op_as_view with valid_range" { #| let arr : UninitializedArray[Int] = UninitializedArray::make(5) #| let view = arr[1:4] #| inspect(view.start(), content="1") #| inspect(view.len(), content="3") #|} #|test "panic op_as_view with invalid_start" { #| let arr : UninitializedArray[Int] = UninitializedArray::make(5) #| ignore(arr[-1:]) #|} #|test "panic op_as_view with invalid_end" { #| let arr : UninitializedArray[Int] = UninitializedArray::make(5) #| ignore(arr[2:10]) #|} #|#intrinsic("%fixedarray.fill") #|#cfg(not(target="js")) #|fn[T] UninitializedArray::unchecked_fill( #| self : UninitializedArray[T], #| start : Int, #| value : T, #| len : Int, #|) -> Unit { #| for i in start..<(start + len) { #| self[i] = value #| } #|} ), "unit.mbt": ( #|pub impl Eq for Unit with op_equal(self : Unit, _other : Unit) -> Bool { #| let _ = self #| true #|} ), }, ) ///| let moonbitlang_core_byte_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/byte", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module }, files={ "moon.pkg.json": ( #|{ #| "import": ["moonbitlang/core/builtin"] #|} ), "byte.mbt": ( #|pub let max_value : Byte = b'\xFF' #|pub let min_value : Byte = b'\x00' #|pub fn to_uint64(self : Byte) -> UInt64 { #| self.to_uint().to_uint64() #|} #|pub fn popcnt(self : Byte) -> Int { #| let mut n = self #| n = (n & 0x55) + ((n >> 1) & 0x55) #| n = (n & 0x33) + ((n >> 2) & 0x33) #| n = (n & 0x0F) + ((n >> 4) & 0x0F) #| n.to_int() #|} ), }, ) ///| let moonbitlang_core_bytes_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/bytes", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module }, files={ "moon.pkg.json": ( #|{ #| "import": ["moonbitlang/core/builtin"], #| "test-import": [ #| "moonbitlang/core/array", #| "moonbitlang/core/double", #| "moonbitlang/core/uint", #| "moonbitlang/core/uint64", #| "moonbitlang/core/test", #| "moonbitlang/core/quickcheck" #| ] #|} ), "bitstring.mbt": ( #|#internal(experimental, "subject to breaking change without notice") #|pub fn View::unsafe_extract_bit(bs : View, offset : Int, _len : Int) -> UInt { #| let byte_index = offset >> 3 #| let bit_mask = (1 << (7 - (offset & 7))).to_byte() #| if (bs.unsafe_get(byte_index) & bit_mask) != 0 { #| 1 #| } else { #| 0 #| } #|} #|#internal(experimental, "subject to breaking change without notice") #|pub fn View::unsafe_extract_byte(bs : View, offset : Int, len : Int) -> UInt { #| let byte_index = offset >> 3 #| if (offset & 7) == 0 { #| let byte = bs.unsafe_get(byte_index) #| (byte >> (8 - len)).to_uint() #| } else if (offset & 7) + len <= 8 { #| let byte = bs.unsafe_get(byte_index).to_uint() #| let shift = 8 - ((offset & 7) + len) #| let mask = (1U << len) - 1 #| (byte >> shift) & mask #| } else { #| let b0 = bs.unsafe_get(byte_index).to_uint() #| let b1 = bs.unsafe_get(byte_index + 1).to_uint() #| let data = (b0 << 8) | b1 #| let bit_mask = (1U << (16 - (offset & 7))) - 1 #| let data = data & bit_mask #| let shift = 16 - ((offset & 7) + len) #| data >> shift #| } #|} #|#internal(experimental, "subject to breaking change without notice") #|pub fn View::unsafe_extract_uint_le(bs : View, offset : Int, len : Int) -> UInt { #| let bytes_needed = (len + 7) / 8 #| let b0 = bs.unsafe_extract_byte(offset, 8) #| match bytes_needed { #| 2 => { #| let b1 = bs.unsafe_extract_byte(offset + 8, len - 8) #| (b1 << 8) | b0 #| } #| 3 => { #| let b1 = bs.unsafe_extract_byte(offset + 8, 8) #| let b2 = bs.unsafe_extract_byte(offset + 16, len - 16) #| (b2 << 16) | (b1 << 8) | b0 #| } #| 4 => { #| let b1 = bs.unsafe_extract_byte(offset + 8, 8) #| let b2 = bs.unsafe_extract_byte(offset + 16, 8) #| let b3 = bs.unsafe_extract_byte(offset + 24, len - 24) #| (b3 << 24) | (b2 << 16) | (b1 << 8) | b0 #| } #| _ => abort("Invalid byte count for int32 extraction") #| } #|} #|#internal(experimental, "subject to breaking change without notice") #|pub fn View::unsafe_extract_uint_be(bs : View, offset : Int, len : Int) -> UInt { #| let bytes_needed = (len + 7) / 8 #| let b0 = bs.unsafe_extract_byte(offset, 8) #| match bytes_needed { #| 2 => { #| let b1 = bs.unsafe_extract_byte(offset + 8, len - 8) #| let shift = 16 - len #| let data = (b0 << 8) | (b1 << shift) #| data >> shift #| } #| 3 => { #| let b1 = bs.unsafe_extract_byte(offset + 8, 8) #| let b2 = bs.unsafe_extract_byte(offset + 16, len - 16) #| let shift = 24 - len #| let data = (b0 << 16) | (b1 << 8) | (b2 << shift) #| data >> shift #| } #| 4 => { #| let b1 = bs.unsafe_extract_byte(offset + 8, 8) #| let b2 = bs.unsafe_extract_byte(offset + 16, 8) #| let b3 = bs.unsafe_extract_byte(offset + 24, len - 24) #| let shift = 32 - len #| let data = (b0 << 24) | (b1 << 16) | (b2 << 8) | (b3 << shift) #| data >> shift #| } #| _ => abort("Invalid byte count for int32 extraction") #| } #|} #|#internal(experimental, "subject to breaking change without notice") #|pub fn View::unsafe_extract_uint64_le( #| bs : View, #| offset : Int, #| len : Int, #|) -> UInt64 { #| let bytes_needed = (len + 7) / 8 #| let b0 = bs.unsafe_extract_byte(offset, 8).to_uint64() #| let b1 = bs.unsafe_extract_byte(offset + 8, 8).to_uint64() #| let b2 = bs.unsafe_extract_byte(offset + 16, 8).to_uint64() #| let b3 = bs.unsafe_extract_byte(offset + 24, 8).to_uint64() #| match bytes_needed { #| 5 => { #| let b4 = bs.unsafe_extract_byte(offset + 32, len - 32).to_uint64() #| (b4 << 32) | (b3 << 24) | (b2 << 16) | (b1 << 8) | b0 #| } #| 6 => { #| let b4 = bs.unsafe_extract_byte(offset + 32, 8).to_uint64() #| let b5 = bs.unsafe_extract_byte(offset + 40, len - 40).to_uint64() #| (b5 << 40) | (b4 << 32) | (b3 << 24) | (b2 << 16) | (b1 << 8) | b0 #| } #| 7 => { #| let b4 = bs.unsafe_extract_byte(offset + 32, 8).to_uint64() #| let b5 = bs.unsafe_extract_byte(offset + 40, 8).to_uint64() #| let b6 = bs.unsafe_extract_byte(offset + 48, len - 48).to_uint64() #| (b6 << 48) | #| (b5 << 40) | #| (b4 << 32) | #| (b3 << 24) | #| (b2 << 16) | #| (b1 << 8) | #| b0 #| } #| 8 => { #| let b4 = bs.unsafe_extract_byte(offset + 32, 8).to_uint64() #| let b5 = bs.unsafe_extract_byte(offset + 40, 8).to_uint64() #| let b6 = bs.unsafe_extract_byte(offset + 48, 8).to_uint64() #| let b7 = bs.unsafe_extract_byte(offset + 56, len - 56).to_uint64() #| (b7 << 56) | #| (b6 << 48) | #| (b5 << 40) | #| (b4 << 32) | #| (b3 << 24) | #| (b2 << 16) | #| (b1 << 8) | #| b0 #| } #| _ => abort("Invalid byte count for int64 extraction") #| } #|} #|#internal(experimental, "subject to breaking change without notice") #|pub fn View::unsafe_extract_uint64_be( #| bs : View, #| offset : Int, #| len : Int, #|) -> UInt64 { #| let bytes_needed = (len + 7) / 8 #| let b0 = bs.unsafe_extract_byte(offset, 8).to_uint64() #| let b1 = bs.unsafe_extract_byte(offset + 8, 8).to_uint64() #| let b2 = bs.unsafe_extract_byte(offset + 16, 8).to_uint64() #| let b3 = bs.unsafe_extract_byte(offset + 24, 8).to_uint64() #| match bytes_needed { #| 5 => { #| let b4 = bs.unsafe_extract_byte(offset + 32, len - 32).to_uint64() #| let shift = 40 - len #| let data = (b0 << 32) | #| (b1 << 24) | #| (b2 << 16) | #| (b3 << 8) | #| (b4 << shift) #| data >> shift #| } #| 6 => { #| let b4 = bs.unsafe_extract_byte(offset + 32, 8).to_uint64() #| let b5 = bs.unsafe_extract_byte(offset + 40, len - 40).to_uint64() #| let shift = 48 - len #| let data = (b0 << 40) | #| (b1 << 32) | #| (b2 << 24) | #| (b3 << 16) | #| (b4 << 8) | #| (b5 << shift) #| data >> shift #| } #| 7 => { #| let b4 = bs.unsafe_extract_byte(offset + 32, 8).to_uint64() #| let b5 = bs.unsafe_extract_byte(offset + 40, 8).to_uint64() #| let b6 = bs.unsafe_extract_byte(offset + 48, len - 48).to_uint64() #| let shift = 56 - len #| let data = (b0 << 48) | #| (b1 << 40) | #| (b2 << 32) | #| (b3 << 24) | #| (b4 << 16) | #| (b5 << 8) | #| (b6 << shift) #| data >> shift #| } #| 8 => { #| let b4 = bs.unsafe_extract_byte(offset + 32, 8).to_uint64() #| let b5 = bs.unsafe_extract_byte(offset + 40, 8).to_uint64() #| let b6 = bs.unsafe_extract_byte(offset + 48, 8).to_uint64() #| let b7 = bs.unsafe_extract_byte(offset + 56, len - 56).to_uint64() #| let shift = 64 - len #| let data = (b0 << 56) | #| (b1 << 48) | #| (b2 << 40) | #| (b3 << 32) | #| (b4 << 24) | #| (b5 << 16) | #| (b6 << 8) | #| (b7 << shift) #| data >> shift #| } #| _ => abort("Invalid byte count for int64 extraction") #| } #|} #|#internal(experimental, "subject to breaking change without notice") #|pub fn View::unsafe_extract_bytesview( #| bs : View, #| offset : Int, #| len : Int, #|) -> View { #| View::make(bs.bytes(), bs.start() + (offset >> 3), len >> 3) #|} #|#internal(experimental, "subject to breaking change without notice") #|pub fn Bytes::unsafe_extract_bit(bs : Bytes, offset : Int, len : Int) -> UInt { #| bs[:].unsafe_extract_bit(offset, len) #|} #|#internal(experimental, "subject to breaking change without notice") #|pub fn Bytes::unsafe_extract_byte(bs : Bytes, offset : Int, len : Int) -> UInt { #| bs[:].unsafe_extract_byte(offset, len) #|} #|#internal(experimental, "subject to breaking change without notice") #|pub fn Bytes::unsafe_extract_uint_le( #| bs : Bytes, #| offset : Int, #| len : Int, #|) -> UInt { #| bs[:].unsafe_extract_uint_le(offset, len) #|} #|#internal(experimental, "subject to breaking change without notice") #|pub fn Bytes::unsafe_extract_uint_be( #| bs : Bytes, #| offset : Int, #| len : Int, #|) -> UInt { #| bs[:].unsafe_extract_uint_be(offset, len) #|} #|#internal(experimental, "subject to breaking change without notice") #|pub fn Bytes::unsafe_extract_uint64_le( #| bs : Bytes, #| offset : Int, #| len : Int, #|) -> UInt64 { #| bs[:].unsafe_extract_uint64_le(offset, len) #|} #|#internal(experimental, "subject to breaking change without notice") #|pub fn Bytes::unsafe_extract_uint64_be( #| bs : Bytes, #| offset : Int, #| len : Int, #|) -> UInt64 { #| bs[:].unsafe_extract_uint64_be(offset, len) #|} #|#internal(experimental, "subject to breaking change without notice") #|pub fn Bytes::unsafe_extract_bytesview( #| bs : Bytes, #| offset : Int, #| len : Int, #|) -> View { #| bs[:].unsafe_extract_bytesview(offset, len) #|} ), "bytes.mbt": ( #|pub fn Bytes::from_array(arr : Array[Byte]) -> Bytes { #| Bytes::makei(arr.length(), i => arr[i]) #|} #|pub fn from_array(arr : Array[Byte]) -> Bytes { #| Bytes::makei(arr.length(), i => arr[i]) #|} #|pub fn Bytes::from_fixedarray(arr : FixedArray[Byte], len? : Int) -> Bytes { #| let len = match len { #| None => arr.length() #| Some(x) => x #| } #| Bytes::makei(len, i => arr[i]) #|} #|pub fn from_fixedarray(arr : FixedArray[Byte], len? : Int) -> Bytes { #| Bytes::from_fixedarray(arr, len?) #|} #|pub fn to_fixedarray(self : Bytes, len? : Int) -> FixedArray[Byte] { #| let len = match len { #| None => self.length() #| Some(x) => x #| } #| let arr = FixedArray::make(len, Byte::default()) #| for i in 0.. Bytes { #| from_array(iter.collect()) #|} #|pub fn from_iter(iter : Iter[Byte]) -> Bytes { #| from_array(iter.collect()) #|} #|pub fn Bytes::of(arr : FixedArray[Byte]) -> Bytes { #| Bytes::makei(arr.length(), i => arr[i]) #|} #|pub fn of(arr : FixedArray[Byte]) -> Bytes { #| Bytes::makei(arr.length(), i => arr[i]) #|} #|pub fn to_array(self : Bytes) -> Array[Byte] { #| let len = self.length() #| let rv = Array::make(len, b'0') #| for i in 0.. Iter[Byte] { #| Iter::new(yield_ => for i in 0.. Iter2[Int, Byte] { #| Iter2::new(yield_ => for i in 0.. Byte? { #| guard index >= 0 && index < self.length() else { None } #| Some(self[index]) #|} #|pub fn default() -> Bytes { #| b"" #|} #|fn unsafe_to_bytes(array : FixedArray[Byte]) -> Bytes = "%identity" #|pub impl Add for Bytes with op_add(self : Bytes, other : Bytes) -> Bytes { #| let len_self = self.length() #| let len_other = other.length() #| let rv : FixedArray[Byte] = FixedArray::make(len_self + len_other, 0) #| for i in 0.. Int? { #| let target_len = target.length() #| let pattern_len = pattern.length() #| for i in 0..=(target_len - pattern_len) { #| for j in 0.. Int? { #| target[:].find(pattern) #|} #|pub fn View::rev_find(target : View, pattern : View) -> Int? { #| let target_len = target.length() #| let pattern_len = pattern.length() #| for i = target_len - pattern_len; i >= 0; i = i - 1 { #| for j in 0.. Int? { #| target[:].rev_find(pattern) #|} ), "view.mbt": ( #|#builtin.valtype #|type View #|fn View::bytes(self : View) -> Bytes = "%bytesview.bytes" #|fn View::start(self : View) -> Int = "%bytesview.start" #|fn View::make(b : Bytes, start : Int, len : Int) -> View = "%bytesview.make" #|pub fn View::length(self : View) -> Int { #| self.len() #|} #|fn View::len(self : View) -> Int = "%bytesview.len" #|pub fn View::op_get(self : View, index : Int) -> Byte { #| guard index >= 0 && index < self.length() else { #| abort( #| "index out of bounds: the len is from 0 to \{self.length()} but the index is \{index}", #| ) #| } #| self.bytes()[self.start() + index] #|} #|pub fn View::get(self : View, index : Int) -> Byte? { #| guard index >= 0 && index < self.length() else { None } #| Some(self.bytes().unsafe_get(self.start() + index)) #|} #|#internal(unsafe, "Panic if index is out of bounds") #|pub fn View::unsafe_get(self : View, index : Int) -> Byte { #| self.bytes()[self.start() + index] #|} #|pub fn Bytes::op_as_view(self : Bytes, start? : Int = 0, end? : Int) -> View { #| let len = self.length() #| let end = match end { #| None => len #| Some(end) => if end < 0 { len + end } else { end } #| } #| let start = if start < 0 { len + start } else { start } #| guard start >= 0 && start <= end && end <= len else { #| abort("Invalid index for View") #| } #| View::make(self, start, end - start) #|} #|pub fn View::op_as_view(self : View, start? : Int = 0, end? : Int) -> View { #| let len = self.length() #| let end = match end { #| None => len #| Some(end) => if end < 0 { len + end } else { end } #| } #| let start = if start < 0 { len + start } else { start } #| guard start >= 0 && start <= end && end <= len else { #| abort("Invalid index for View") #| } #| View::make(self.bytes(), self.start() + start, end - start) #|} #|pub fn View::iter(self : View) -> Iter[Byte] { #| Iter::new(yield_ => for i in 0.. UInt { #| (self[0].to_uint() << 24) + #| (self[1].to_uint() << 16) + #| (self[2].to_uint() << 8) + #| self[3].to_uint() #|} #|pub fn View::to_uint_le(self : View) -> UInt { #| self[0].to_uint() + #| (self[1].to_uint() << 8) + #| (self[2].to_uint() << 16) + #| (self[3].to_uint() << 24) #|} #|pub fn View::to_uint64_be(self : View) -> UInt64 { #| (self[0].to_uint().to_uint64() << 56) + #| (self[1].to_uint().to_uint64() << 48) + #| (self[2].to_uint().to_uint64() << 40) + #| (self[3].to_uint().to_uint64() << 32) + #| (self[4].to_uint().to_uint64() << 24) + #| (self[5].to_uint().to_uint64() << 16) + #| (self[6].to_uint().to_uint64() << 8) + #| self[7].to_uint().to_uint64() #|} #|pub fn View::to_uint64_le(self : View) -> UInt64 { #| self[0].to_uint().to_uint64() + #| (self[1].to_uint().to_uint64() << 8) + #| (self[2].to_uint().to_uint64() << 16) + #| (self[3].to_uint().to_uint64() << 24) + #| (self[4].to_uint().to_uint64() << 32) + #| (self[5].to_uint().to_uint64() << 40) + #| (self[6].to_uint().to_uint64() << 48) + #| (self[7].to_uint().to_uint64() << 56) #|} #|pub fn View::to_int_be(self : View) -> Int { #| self.to_uint_be().reinterpret_as_int() #|} #|pub fn View::to_int_le(self : View) -> Int { #| self.to_uint_le().reinterpret_as_int() #|} #|pub fn View::to_int64_be(self : View) -> Int64 { #| self.to_uint64_be().reinterpret_as_int64() #|} #|pub fn View::to_int64_le(self : View) -> Int64 { #| self.to_uint64_le().reinterpret_as_int64() #|} #|pub fn View::to_float_be(self : View) -> Float { #| self.to_uint_be().reinterpret_as_float() #|} #|pub fn View::to_float_le(self : View) -> Float { #| self.to_uint_le().reinterpret_as_float() #|} #|pub fn View::to_double_be(self : View) -> Double { #| self.to_uint64_be().reinterpret_as_double() #|} #|pub fn View::to_double_le(self : View) -> Double { #| self.to_uint64_le().reinterpret_as_double() #|} #|pub impl Show for View with output(self, logger) { #| fn to_hex_digit(i : Int) -> Char { #| if i < 10 { #| ('0'.to_int() + i).unsafe_to_char() #| } else { #| ('a'.to_int() + (i - 10)).unsafe_to_char() #| } #| } #| logger.write_string("b\"") #| for i in 0.. Bool { #| guard self.length() == other.length() else { return false } #| for i in 0.. Int { #| let self_len = self.length() #| let other_len = other.length() #| let cmp = self_len.compare(other_len) #| guard cmp == 0 else { return cmp } #| for i in 0.. Bytes { #| self.bytes() #|} #|pub fn View::start_offset(self : View) -> Int { #| self.start() #|} #|pub fn View::to_bytes(self : View) -> Bytes { #| if self.length() == 0 && self.length() == self.bytes().length() { #| return self.bytes() #| } #| let bytes = FixedArray::make(self.length(), (0 : Byte)) #| bytes.blit_from_bytes(0, self.bytes(), self.start_offset(), self.length()) #| unsafe_to_bytes(bytes) #|} #|pub impl Hash for View with hash_combine(self : View, hasher : Hasher) { #| for i in 0.. Int { #| xxhash32(self.data(), 0, offset=self.start_offset(), len=self.length()) #|} ), "xxhash.mbt": ( #|let gPRIME1 = 0x9E3779B1 #|let gPRIME2 = 0x85EBCA77 #|let gPRIME3 = 0xC2B2AE3D #|let gPRIME4 = 0x27D4EB2F #|let gPRIME5 = 0x165667B1 #|fn xxhash32( #| input : Bytes, #| offset? : Int = 0, #| len? : Int = input.length(), #| seed : Int, #|) -> Int { #| let h = (if len >= 16 { #| h16bytes(input, offset, len, seed) #| } else { #| seed + gPRIME5 #| }) + #| len #| finalize(h, input, offset + (len & -16), len & 0xF) #|} #|pub impl Hash for Bytes with hash(self) { #| xxhash32(self, 0) #|} #|pub impl Hash for Bytes with hash_combine(self, hasher) { #| hasher.combine_bytes(self) #|} #|fn rotl(x : Int, r : Int) -> Int { #| (x << r) | (x.reinterpret_as_uint() >> (32 - r)).reinterpret_as_int() #|} #|fn round(acc : Int, input : Int) -> Int { #| rotl(acc + input * gPRIME2, 13) * gPRIME1 #|} #|fn avalanche_step(h : Int, rshift : Int, prime : Int) -> Int { #| (h ^ (h.reinterpret_as_uint() >> rshift).reinterpret_as_int()) * prime #|} #|fn avalanche(h : Int) -> Int { #| avalanche_step( #| avalanche_step(avalanche_step(h, 15, gPRIME2), 13, gPRIME3), #| 16, #| 1, #| ) #|} #|fn endian32(input : Bytes, cur : Int) -> Int { #| input[cur + 0].to_int() | #| ( #| (input[cur + 1].to_int() << 8) | #| ((input[cur + 2].to_int() << 16) | (input[cur + 3].to_int() << 24)) #| ) #|} #|fn fetch32(input : Bytes, cur : Int, v : Int) -> Int { #| round(v, endian32(input, cur)) #|} #|fn finalize(h : Int, input : Bytes, cur : Int, remain : Int) -> Int { #| if remain >= 4 { #| finalize( #| rotl(h + endian32(input, cur) * gPRIME3, 17) * gPRIME4, #| input, #| cur + 4, #| remain - 4, #| ) #| } else if remain > 0 { #| finalize( #| rotl(h + input[cur].to_int() * gPRIME5, 11) * gPRIME1, #| input, #| cur + 1, #| remain - 1, #| ) #| } else { #| avalanche(h) #| } #|} #|fn _h16bytes( #| input : Bytes, #| cur : Int, #| remain : Int, #| v1 : Int, #| v2 : Int, #| v3 : Int, #| v4 : Int, #|) -> Int { #| if remain >= 16 { #| _h16bytes( #| input, #| cur + 16, #| remain - 16, #| fetch32(input, cur, v1), #| fetch32(input, cur + 4, v2), #| fetch32(input, cur + 8, v3), #| fetch32(input, cur + 12, v4), #| ) #| } else { #| rotl(v1, 1) + rotl(v2, 7) + rotl(v3, 12) + rotl(v4, 18) #| } #|} #|fn h16bytes(input : Bytes, cur : Int, len : Int, seed : Int) -> Int { #| _h16bytes( #| input, #| cur, #| len, #| seed + gPRIME1 + gPRIME2, #| seed + gPRIME2, #| seed, #| seed - gPRIME1, #| ) #|} #|test "Bytes hash_combine" { #| let data : Bytes = [1, 2, 3, 4] #| let hasher = Hasher::new() #| data.hash_combine(hasher) #| assert_true(hasher.finalize() != 0) #|} ), }, ) ///| let moonbitlang_core_char_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/char", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module }, files={ "moon.pkg.json": ( #|{ #| "import": ["moonbitlang/core/builtin"] #|} ), "char.mbt": ( #|pub impl Hash for Char with hash(self) { #| self.to_int() #|} #|pub impl Hash for Char with hash_combine(self, hasher) -> Unit { #| hasher.combine_char(self) #|} #|pub fn Char::is_ascii(self : Self) -> Bool { #| self is ('\u{00}'..='\u{7F}') #|} #|pub fn Char::is_ascii_alphabetic(self : Self) -> Bool { #| self is ('A'..='Z' | 'a'..='z') #|} #|pub fn Char::is_ascii_control(self : Self) -> Bool { #| self is ('\u{00}'..='\u{1F}' | '\u{7F}') #|} #|pub fn Char::is_ascii_digit(self : Self) -> Bool { #| self is ('0'..='9') #|} #|pub fn Char::is_ascii_graphic(self : Self) -> Bool { #| self is ('\u{21}'..='\u{7E}') #|} #|pub fn Char::is_ascii_hexdigit(self : Self) -> Bool { #| self is ('0'..='9' | 'A'..='F' | 'a'..='f') #|} #|pub fn Char::is_ascii_lowercase(self : Self) -> Bool { #| self is ('a'..='z') #|} #|pub fn Char::is_ascii_octdigit(self : Self) -> Bool { #| self is ('0'..='7') #|} #|pub fn Char::is_ascii_punctuation(self : Self) -> Bool { #| self #| is ('\u{21}'..='\u{2F}' #| | '\u{3A}'..='\u{40}' #| | '\u{5B}'..='\u{60}' #| | '\u{7B}'..='\u{7E}') #|} #|pub fn Char::is_ascii_uppercase(self : Self) -> Bool { #| self is ('A'..='Z') #|} #|pub fn Char::is_ascii_whitespace(self : Self) -> Bool { #| self is ('\u{20}' | '\u{09}' | '\u{0A}' | '\u{0B}' | '\u{0C}' | '\u{0D}') #|} #|pub fn Char::is_control(self : Self) -> Bool { #| self is ('\u0000'..='\u001F' | '\u007F'..='\u009F') #|} #|pub fn Char::is_digit(self : Self, radix : UInt) -> Bool { #| let v = self.to_uint() #| match radix { #| 2..=10 => v >= 48 && v <= radix + 47 #| 11..=36 => #| (v >= 48 && v <= 57) || #| (v >= 65 && v <= radix + 54) || #| (v >= 97 && v <= radix + 86) #| _ => panic() #| } #|} #|pub fn Char::is_whitespace(self : Self) -> Bool { #| self #| is ('\u0009'..='\u000D' #| | '\u0020' #| | '\u0085' #| | '\u00A0' #| | '\u1680' #| | '\u2000'..='\u200A' #| | '\u2028' #| | '\u2029' #| | '\u202F' #| | '\u205F' #| | '\u3000') #|} #|pub fn Char::is_numeric(self : Self) -> Bool { #| self #| is ('\u0030'..='\u0039' #| | '\u00B2' #| | '\u00B3' #| | '\u00B9' #| | '\u00BC' #| | '\u00BD' #| | '\u00BE' #| | '\u0660'..='\u0669' #| | '\u06F0'..='\u06F9' #| | '\u07C0'..='\u07F9' #| | '\u0966'..='\u096F' #| | '\u09E6'..='\u09EF' #| | '\u09F4'..='\u09F9' #| | '\u0A66'..='\u0A6F' #| | '\u0AE6'..='\u0AEF' #| | '\u0B66'..='\u0B6F' #| | '\u0B72'..='\u0B77' #| | '\u0BE6'..='\u0BEF' #| | '\u0BF0'..='\u0BF2' #| | '\u0C66'..='\u0C6F' #| | '\u0C78'..='\u0C7E' #| | '\u0CE6'..='\u0CEF' #| | '\u0D58'..='\u0D5E' #| | '\u0D66'..='\u0D6F' #| | '\u0D70'..='\u0D78' #| | '\u0DE6'..='\u0DEF' #| | '\u0E50'..='\u0E59' #| | '\u0ED0'..='\u0ED9' #| | '\u0F20'..='\u0F33' #| | '\u1040'..='\u1049' #| | '\u1090'..='\u1099' #| | '\u1369'..='\u137C' #| | '\u16EE'..='\u16F0' #| | '\u17E0'..='\u17E9' #| | '\u17F0'..='\u17F9' #| | '\u1810'..='\u1819' #| | '\u1946'..='\u194F' #| | '\u19D0'..='\u19DA' #| | '\u1A80'..='\u1A89' #| | '\u1A90'..='\u1A99' #| | '\u1B50'..='\u1B59' #| | '\u1BB0'..='\u1BB9' #| | '\u1C40'..='\u1C49' #| | '\u1C50'..='\u1C59' #| | '\u2070' #| | '\u2074'..='\u2079' #| | '\u2080'..='\u2089' #| | '\u2150'..='\u2189' #| | '\u2460'..='\u249B' #| | '\u24EA'..='\u24FF' #| | '\u2776'..='\u2793' #| | '\u2CFD' #| | '\u3007' #| | '\u3021'..='\u3029' #| | '\u3038'..='\u303A' #| | '\u3192'..='\u3195' #| | '\u3220'..='\u3229' #| | '\u3248'..='\u324F' #| | '\u3251'..='\u325F' #| | '\u3280'..='\u3289' #| | '\u32B1'..='\u32BF' #| | '\uA620'..='\uA629' #| | '\uA6E6'..='\uA6EF' #| | '\uA830'..='\uA835' #| | '\uA8D0'..='\uA8D9' #| | '\uA900'..='\uA909' #| | '\uA9D0'..='\uA9D9' #| | '\uA9F0'..='\uA9F9' #| | '\uAA50'..='\uAA59' #| | '\uABF0'..='\uABF9' #| | '\uFF10'..='\uFF19' #| | '\u{10107}'..='\u{10133}' #| | '\u{10140}'..='\u{10178}' #| | '\u{1018A}'..='\u{1018B}' #| | '\u{102E1}'..='\u{102FB}' #| | '\u{10320}'..='\u{10323}' #| | '\u{10341}' #| | '\u{1034A}' #| | '\u{103D1}'..='\u{103D5}' #| | '\u{104A0}'..='\u{104A9}' #| | '\u{10858}'..='\u{1085F}' #| | '\u{10879}'..='\u{1087F}' #| | '\u{108A7}'..='\u{108AF}' #| | '\u{108FB}'..='\u{108FF}' #| | '\u{10916}'..='\u{1091B}' #| | '\u{109BC}'..='\u{109BD}' #| | '\u{109C0}'..='\u{109CF}' #| | '\u{10A40}'..='\u{10A48}' #| | '\u{10A7D}'..='\u{10A7E}' #| | '\u{10A9D}'..='\u{10A9F}' #| | '\u{10AEB}'..='\u{10AEF}' #| | '\u{10B58}'..='\u{10B5F}' #| | '\u{10B78}'..='\u{10B7F}' #| | '\u{10BA9}'..='\u{10BAF}' #| | '\u{10CFA}'..='\u{10CFF}' #| | '\u{10D30}'..='\u{10D39}' #| | '\u{10D40}'..='\u{10D49}' #| | '\u{10E60}'..='\u{10E7E}' #| | '\u{10F1D}'..='\u{10F26}' #| | '\u{10F51}'..='\u{10F54}' #| | '\u{10FC5}'..='\u{10FCB}' #| | '\u{11052}'..='\u{1106F}' #| | '\u{110F0}'..='\u{110F9}' #| | '\u{11136}'..='\u{1113F}' #| | '\u{111D0}'..='\u{111D9}' #| | '\u{111E1}'..='\u{111F4}' #| | '\u{112F0}'..='\u{112F9}' #| | '\u{11450}'..='\u{11459}' #| | '\u{114D0}'..='\u{114D9}' #| | '\u{11650}'..='\u{11659}' #| | '\u{116C0}'..='\u{116C9}' #| | '\u{116D0}'..='\u{116E3}' #| | '\u{11730}'..='\u{1173B}' #| | '\u{118E0}'..='\u{118F2}' #| | '\u{11950}'..='\u{11959}' #| | '\u{11BF0}'..='\u{11BF9}' #| | '\u{11C50}'..='\u{11C6C}' #| | '\u{11D50}'..='\u{11D59}' #| | '\u{11DA0}'..='\u{11DA9}' #| | '\u{11F50}'..='\u{11F59}' #| | '\u{11FC0}'..='\u{11FD4}' #| | '\u{12400}'..='\u{1246E}' #| | '\u{16130}'..='\u{16139}' #| | '\u{16A60}'..='\u{16A69}' #| | '\u{16AC0}'..='\u{16AC9}' #| | '\u{16B50}'..='\u{16B59}' #| | '\u{16B5B}'..='\u{16B61}' #| | '\u{16D70}'..='\u{16D79}' #| | '\u{16D80}'..='\u{16E96}' #| | '\u{1CCF0}'..='\u{1CCF9}' #| | '\u{1D2C0}'..='\u{1D2F3}' #| | '\u{1D360}'..='\u{1D378}' #| | '\u{1D7CE}'..='\u{1D7FF}' #| | '\u{1E140}'..='\u{1E149}' #| | '\u{1E2F0}'..='\u{1E2F9}' #| | '\u{1E4F0}'..='\u{1E4F9}' #| | '\u{1E5F1}'..='\u{1E5FA}' #| | '\u{1E8C7}'..='\u{1E8CF}' #| | '\u{1E950}'..='\u{1E959}' #| | '\u{1EC71}'..='\u{1ECB4}' #| | '\u{1ED01}'..='\u{1ED3D}' #| | '\u{1F100}'..='\u{1F10C}' #| | '\u{1FBF0}'..='\u{1FBF9}') #|} #|pub fn Char::is_printable(self : Self) -> Bool { #| if self.is_control() { #| return false #| } #| let self = self.to_int() #| if self is (0xE000..=0xF8FF | 0xF0000..=0xFFFFD | 0x100000..=0x10FFFD) { #| return false #| } #| if self #| is ('\u{00AD}' #| | '\u{0600}'..='\u{0605}' #| | '\u{061C}' #| | '\u{06DD}' #| | '\u{070F}' #| | '\u{0890}'..='\u{0891}' #| | '\u{08E2}' #| | '\u{180E}' #| | '\u{200B}'..='\u{200F}' #| | '\u{202A}'..='\u{202E}' #| | '\u{2060}'..='\u{2064}' #| | '\u{2066}'..='\u{206F}' #| | '\u{feff}' #| | '\u{FFF9}'..='\u{FFFB}' #| | '\u{110BD}' #| | '\u{110CD}' #| | '\u{13430}'..='\u{1343F}' #| | '\u{1BCA0}'..='\u{1BCA3}' #| | '\u{1D173}'..='\u{1D17A}' #| | '\u{E0001}' #| | '\u{E0020}'..='\u{E007F}') { #| return false #| } #| if self.is_surrogate() { #| return false #| } #| if self == '\u{2028}' || self == '\u{2029}' { #| return false #| } #| if self #| is (0xFDD0..=0xFDEF #| | 0xFFFE..=0xFFFF #| | 0x1FFFE..=0x1FFFF #| | 0x2FFFE..=0x2FFFF #| | 0x3FFFE..=0x3FFFF #| | 0x4FFFE..=0x4FFFF #| | 0x5FFFE..=0x5FFFF #| | 0x6FFFE..=0x6FFFF #| | 0x7FFFE..=0x7FFFF #| | 0x8FFFE..=0x8FFFF #| | 0x9FFFE..=0x9FFFF #| | 0xAFFFE..=0xAFFFF #| | 0xBFFFE..=0xBFFFF #| | 0xCFFFE..=0xCFFFF #| | 0xDFFFE..=0xDFFFF #| | 0xEFFFE..=0xEFFFF #| | 0xFFFFE..=0xFFFFF #| | 0x10FFFE..=0x10FFFF) { #| return false #| } #| true #|} #|pub fn Char::to_ascii_lowercase(self : Self) -> Char { #| if self.is_ascii_uppercase() { #| return (self.to_int() + 32).unsafe_to_char() #| } #| self #|} #|pub fn Char::to_ascii_uppercase(self : Self) -> Char { #| if self.is_ascii_lowercase() { #| return (self.to_int() - 32).unsafe_to_char() #| } #| self #|} #|pub impl Show for Char with to_string(self : Char) -> String { #| char_to_string(self) #|} #|#intrinsic("%char.to_string") #|fn char_to_string(char : Char) -> String { #| [char] #|} #|pub impl Show for Char with output(self, logger) { #| fn to_hex_digit(i : Int) -> Char { #| if i < 10 { #| (i + '0').unsafe_to_char() #| } else { #| (i + 'a' - 10).unsafe_to_char() #| } #| } #| logger.write_char('\'') #| match self { #| '\'' | '\\' => logger..write_char('\\')..write_char(self) #| '\n' => logger.write_string("\\n") #| '\r' => logger.write_string("\\r") #| '\b' => logger.write_string("\\b") #| '\t' => logger.write_string("\\t") #| ' '..='~' => logger.write_char(self) #| _ => #| if !self.is_printable() { #| let code = self.to_int() #| let hex_len = if code <= 0xFF { #| 2 #| } else if code <= 0xFFF { #| 3 #| } else if code <= 0xFFFF { #| 4 #| } else if code <= 0xFFFFF { #| 5 #| } else { #| 6 #| } #| logger.write_string("\\u{") #| if hex_len >= 6 { #| logger.write_char(to_hex_digit((code >> 20) & 0xF)) #| } #| if hex_len >= 5 { #| logger.write_char(to_hex_digit((code >> 16) & 0xF)) #| } #| if hex_len >= 4 { #| logger.write_char(to_hex_digit((code >> 12) & 0xF)) #| } #| if hex_len >= 3 { #| logger.write_char(to_hex_digit((code >> 8) & 0xF)) #| } #| if hex_len >= 2 { #| logger.write_char(to_hex_digit((code >> 4) & 0xF)) #| } #| logger.write_char(to_hex_digit(code & 0xF)) #| logger.write_char('}') #| } else { #| logger.write_char(self) #| } #| } #| logger.write_char('\'') #|} #|pub impl ToJson for Char with to_json(self : Char) -> Json { #| Json::string(self.to_string()) #|} #|pub fn Char::utf16_len(self : Self) -> Int { #| let code = self.to_int() #| if code <= 0xFFFF { #| 1 #| } else { #| 2 #| } #|} #|pub fn Char::is_bmp(self : Self) -> Bool { #| self.to_int() <= 0xFFFF #|} ), }, ) ///| let moonbitlang_core_cmp_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/cmp", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/builtin" #| ], #| "test-import": [ #| "moonbitlang/core/int", #| "moonbitlang/core/double", #| "moonbitlang/core/test" #| ] #|} ), "cmp.mbt": ( #|pub fn[T, K : Compare] maximum_by_key(x : T, y : T, f : (T) -> K) -> T { #| if f(x) > f(y) { #| x #| } else { #| y #| } #|} #|pub fn[T, K : Compare] minimum_by_key(x : T, y : T, f : (T) -> K) -> T { #| if f(x) > f(y) { #| y #| } else { #| x #| } #|} #|pub fn[T : Compare] maximum(x : T, y : T) -> T { #| if x > y { #| x #| } else { #| y #| } #|} #|pub fn[T : Compare] minimum(x : T, y : T) -> T { #| if x > y { #| y #| } else { #| x #| } #|} ), }, ) ///| let moonbitlang_core_deque_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/deque", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/json": moonbitlang_core_json_module, "moonbitlang/core/array": moonbitlang_core_array_module, "moonbitlang/core/string": moonbitlang_core_string_module, }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/builtin", #| "moonbitlang/core/json", #| "moonbitlang/core/array", #| "moonbitlang/core/string" #| ], #| "targets": { #| "panic_test.mbt": ["not", "native", "llvm"] #| } #|} ), "deprecated.mbt": ( #|#deprecated("Use `unsafe_pop_front` instead") #|#coverage.skip #|pub fn[A] pop_front_exn(self : T[A]) -> Unit { #| self.unsafe_pop_front() #|} #|#deprecated("Use `unsafe_pop_back` instead") #|#coverage.skip #|pub fn[A] pop_back_exn(self : T[A]) -> Unit { #| self.unsafe_pop_back() #|} #|#deprecated("Use `@deque.retain_map` instead") #|pub fn[A] filter_map_inplace(self : T[A], f : (A) -> A?) -> Unit { #| self.retain_map(f) #|} ), "deque.mbt": ( #|fn[T] set_null(buffer : UninitializedArray[T], index : Int) = "%fixedarray.set_null" #|pub fn[A] new(capacity? : Int = 0) -> T[A] { #| T::{ buf: UninitializedArray::make(capacity), len: 0, head: 0, tail: 0 } #|} #|pub impl[A : Show] Show for T[A] with output(self, logger) { #| logger.write_iter(self.iter(), prefix="@deque.of([", suffix="])") #|} #|pub fn[A] from_array(arr : Array[A]) -> T[A] { #| let deq = T::{ #| buf: UninitializedArray::make(arr.length()), #| len: arr.length(), #| head: 0, #| tail: arr.length() - 1, #| } #| for i in 0.. T[A] { #| let len = self.len #| let deq = T::{ #| buf: UninitializedArray::make(len), #| len, #| head: 0, #| tail: len - 1, #| } #| for i, x in self { #| deq.buf[i] = x #| } #| deq #|} #|pub fn[A] of(arr : FixedArray[A]) -> T[A] { #| let deq = T::{ #| buf: UninitializedArray::make(arr.length()), #| len: arr.length(), #| head: 0, #| tail: arr.length() - 1, #| } #| for i in 0.. Int { #| self.len #|} #|pub fn[A] capacity(self : T[A]) -> Int { #| self.buf.length() #|} #|fn[A] realloc(self : T[A]) -> Unit { #| let old_cap = self.len #| let new_cap = if old_cap == 0 { 8 } else { old_cap * 2 } #| let new_buf = UninitializedArray::make(new_cap) #| if old_cap > 0 { #| if self.tail >= self.head { #| for i = self.head, j = 0; i <= self.tail; i = i + 1, j = j + 1 { #| new_buf[j] = self.buf[i] #| } #| } else { #| let mut j = 0 #| for i in self.head.. A? { #| if self.len == 0 { #| None #| } else { #| Some(self.buf[self.head]) #| } #|} #|pub fn[A] back(self : T[A]) -> A? { #| if self.len == 0 { #| None #| } else { #| Some(self.buf[self.tail]) #| } #|} #|pub fn[A] push_front(self : T[A], value : A) -> Unit { #| if self.len == self.buf.length() { #| self.realloc() #| } #| if self.len != 0 { #| self.head = (self.head + self.buf.length() - 1) % self.buf.length() #| } #| self.buf[self.head] = value #| self.len += 1 #|} #|pub fn[A] push_back(self : T[A], value : A) -> Unit { #| if self.len == self.buf.length() { #| self.realloc() #| } #| if self.len != 0 { #| self.tail = (self.tail + self.buf.length() + 1) % self.buf.length() #| } #| self.buf[self.tail] = value #| self.len += 1 #|} #|#internal(unsafe, "Panic if the deque is empty.") #|pub fn[A] unsafe_pop_front(self : T[A]) -> Unit { #| match self.len { #| 0 => abort("The deque is empty!") #| 1 => { #| set_null(self.buf, self.head) #| self.len -= 1 #| } #| _ => { #| set_null(self.buf, self.head) #| self.head = if self.head < self.buf.length() - 1 { #| self.head + 1 #| } else { #| 0 #| } #| self.len -= 1 #| } #| } #|} #|#internal(unsafe, "Panic if the deque is empty.") #|pub fn[A] unsafe_pop_back(self : T[A]) -> Unit { #| match self.len { #| 0 => abort("The deque is empty!") #| 1 => { #| set_null(self.buf, self.tail) #| self.len -= 1 #| } #| _ => { #| set_null(self.buf, self.tail) #| self.tail = if self.tail > 0 { #| self.tail - 1 #| } else { #| self.buf.length() - 1 #| } #| self.len -= 1 #| } #| } #|} #|pub fn[A] pop_front(self : T[A]) -> A? { #| match self.len { #| 0 => None #| 1 => { #| let origin_head = self.buf[self.head] #| set_null(self.buf, self.head) #| self.len -= 1 #| Some(origin_head) #| } #| _ => { #| let origin_head = self.buf[self.head] #| set_null(self.buf, self.head) #| self.head = if self.head < self.buf.length() - 1 { #| self.head + 1 #| } else { #| 0 #| } #| self.len -= 1 #| Some(origin_head) #| } #| } #|} #|pub fn[A] pop_back(self : T[A]) -> A? { #| match self.len { #| 0 => None #| 1 => { #| let origin_back = self.buf[self.tail] #| set_null(self.buf, self.tail) #| self.len -= 1 #| Some(origin_back) #| } #| _ => { #| let origin_back = self.buf[self.tail] #| set_null(self.buf, self.tail) #| self.tail = if self.tail > 0 { #| self.tail - 1 #| } else { #| self.buf.length() - 1 #| } #| self.len -= 1 #| Some(origin_back) #| } #| } #|} #|pub fn[A] op_get(self : T[A], index : Int) -> A { #| if index < 0 || index >= self.len { #| let len = self.len #| abort( #| "index out of bounds: the len is from 0 to \{len} but the index is \{index}", #| ) #| } #| if self.head + index < self.buf.length() { #| self.buf[self.head + index] #| } else { #| self.buf[self.head + index - self.buf.length()] #| } #|} #|pub fn[A] op_set(self : T[A], index : Int, value : A) -> Unit { #| if index < 0 || index >= self.len { #| let len = self.len #| abort( #| "index out of bounds: the len is from 0 to \{len} but the index is \{index}", #| ) #| } #| if self.head + index < self.buf.length() { #| self.buf[self.head + index] = value #| } else { #| self.buf[self.head + index - self.buf.length()] = value #| } #|} #|pub fn[A] T::as_views(self : T[A]) -> (@array.View[A], @array.View[A]) { #| guard self.len != 0 else { ([][:], [][:]) } #| let { buf, head, len, .. } = self #| let cap = buf.length() #| let head_len = cap - head #| if head_len >= len { #| (buf[head:head + len], [][:]) #| } else { #| (buf[head:cap], buf[:len - head_len]) #| } #|} #|pub impl[A : Eq] Eq for T[A] with op_equal(self, other) { #| if self.len != other.len { #| return false #| } #| for i in 0.. Unit) -> Unit { #| for v in self { #| f(v) #| } #|} #|pub fn[A] eachi(self : T[A], f : (Int, A) -> Unit) -> Unit { #| for i, v in self { #| f(i, v) #| } #|} #|pub fn[A] rev_each(self : T[A], f : (A) -> Unit) -> Unit { #| for v in self.rev_iter() { #| f(v) #| } #|} #|pub fn[A] rev_eachi(self : T[A], f : (Int, A) -> Unit) -> Unit { #| for i, v in self.rev_iter2() { #| f(i, v) #| } #|} #|pub fn[A] clear(self : T[A]) -> Unit { #| let { head, buf, len, .. } = self #| let cap = buf.length() #| let head_len = cap - head #| if head_len >= len { #| for i in head..<(head + len) { #| set_null(buf, i) #| } #| } else { #| for i in head.. U) -> T[U] { #| if self.len == 0 { #| new() #| } else { #| let buf : UninitializedArray[U] = UninitializedArray::make(self.len) #| for i in 0.. U) -> T[U] { #| if self.len == 0 { #| new() #| } else { #| let buf : UninitializedArray[U] = UninitializedArray::make(self.len) #| for i in 0.. Bool { #| self.len == 0 #|} #|pub fn[A : Eq] search(self : T[A], value : A) -> Int? { #| for i in 0.. Bool { #| self.iter().contains(value) #|} #|pub fn[A] reserve_capacity(self : T[A], capacity : Int) -> Unit { #| if self.capacity() >= capacity { #| return #| } #| let new_buf : UninitializedArray[A] = UninitializedArray::make(capacity) #| let { buf, len, head, .. } = self #| self.buf = new_buf #| self.head = 0 #| self.tail = 0 #| for i in 0.. Unit { #| if self.capacity() <= self.length() { #| return #| } #| let { buf, len, head, .. } = self #| self.buf = UninitializedArray::make(len) #| self.head = 0 #| self.tail = 0 #| for i in 0.. Unit { #| guard len >= 0 && len < self.len else { return } #| if len == 0 { #| self.clear() #| return #| } #| let { head, buf, .. } = self #| let (front, back) = self.as_views() #| if front.length() < len { #| self.len = len #| let start = len - front.length() #| self.tail = start - 1 #| for i in start.. A?) -> Unit { #| guard !self.is_empty() else { return } #| let { head, buf, .. } = self #| let cap = buf.length() #| let head_len = cap - head #| let mut idx = head #| let (front, back) = self.as_views() #| for cur in front { #| if f(cur) is Some(v) { #| buf[idx] = v #| idx += 1 #| } #| } #| if back.length() == 0 { #| self.truncate(idx - head) #| return #| } #| for cur in back { #| if idx == cap { #| idx = 0 #| } #| if f(cur) is Some(v) { #| buf[idx] = v #| idx += 1 #| } #| } #| if idx <= self.len - head_len { #| self.truncate(idx + head_len) #| } else { #| self.truncate(idx - head) #| } #|} #|pub fn[A] retain(self : T[A], f : (A) -> Bool) -> Unit { #| guard !self.is_empty() else { return } #| let { head, buf, .. } = self #| let cap = buf.length() #| let head_len = cap - head #| let mut idx = head #| let (front, back) = self.as_views() #| for cur in front { #| if f(cur) { #| buf[idx] = cur #| idx += 1 #| } #| } #| if back.length() == 0 { #| self.truncate(idx - head) #| return #| } #| for cur in back { #| if idx == cap { #| idx = 0 #| } #| if f(cur) { #| buf[idx] = cur #| idx += 1 #| } #| } #| if idx <= self.len - head_len { #| self.truncate(idx + head_len) #| } else { #| self.truncate(idx - head) #| } #|} #|pub fn[A] iter(self : T[A]) -> Iter[A] { #| Iter::new(yield_ => { #| guard !self.is_empty() else { IterContinue } #| let { head, buf, len, .. } = self #| let cap = buf.length() #| let head_len = cap - head #| if head_len >= len { #| for i in head..<(head + len) { #| guard yield_(buf[i]) is IterContinue else { return IterEnd } #| } #| } else { #| for i in head.. Iter2[Int, A] { #| Iter2::new(yield_ => { #| guard !self.is_empty() else { IterContinue } #| let { head, buf, len, .. } = self #| let cap = buf.length() #| let head_len = cap - head #| let mut j = 0 #| if head_len >= len { #| for i in head..<(head + len) { #| guard yield_(j, buf[i]) is IterContinue else { return IterEnd } #| j += 1 #| } #| } else { #| for i in head.. Iter[A] { #| Iter::new(yield_ => { #| guard !self.is_empty() else { IterContinue } #| let { head, buf, len, .. } = self #| let cap = buf.length() #| let head_len = cap - head #| if head_len >= len { #| for i = head + len - 1; i >= head; i = i - 1 { #| guard yield_(buf[i]) is IterContinue else { return IterEnd } #| } #| } else { #| for i = len - head_len - 1; i >= 0; i = i - 1 { #| guard yield_(buf[i]) is IterContinue else { return IterEnd } #| } #| for i = cap - 1; i >= head; i = i - 1 { #| guard yield_(buf[i]) is IterContinue else { return IterEnd } #| } #| } #| IterContinue #| }) #|} #|pub fn[A] rev_iter2(self : T[A]) -> Iter2[Int, A] { #| Iter2::new(yield_ => { #| guard !self.is_empty() else { IterContinue } #| let { head, buf, len, .. } = self #| let cap = buf.length() #| let head_len = cap - head #| let mut j = 0 #| if head_len >= len { #| for i = head + len - 1; i >= head; i = i - 1 { #| guard yield_(j, buf[i]) is IterContinue else { return IterEnd } #| j += 1 #| } #| } else { #| for i = len - head_len - 1; i >= 0; i = i - 1 { #| guard yield_(j, buf[i]) is IterContinue else { return IterEnd } #| j += 1 #| } #| for i = cap - 1; i >= head; i = i - 1 { #| guard yield_(j, buf[i]) is IterContinue else { return IterEnd } #| j += 1 #| } #| } #| IterContinue #| }) #|} #|pub fn[A] from_iter(iter : Iter[A]) -> T[A] { #| let dq = new() #| iter.each(e => dq.push_back(e)) #| dq #|} #|pub fn[A] to_array(self : T[A]) -> Array[A] { #| let len = self.length() #| if len == 0 { #| [] #| } else { #| let xs = Array::make(len, self[0]) #| for i in 0.. String { #| let str = separator.to_string() #| self.iter().join(str) #|} #|pub impl[A : ToJson] ToJson for T[A] with to_json(self : T[A]) -> Json { #| let res = Array::make(self.length(), null) #| for i, x in self { #| res[i] = x.to_json() #| } #| Json::array(res) #|} #|pub impl[A : @json.FromJson] @json.FromJson for T[A] with from_json(json, path) { #| guard json is Array(arr) else { #| raise @json.JsonDecodeError((path, "Deque::from_json: expected array")) #| } #| let len = arr.length() #| let buf = UninitializedArray::make(len) #| let head = 0 #| let tail = len #| for i, x in arr { #| buf[i] = @json.FromJson::from_json(x, path.add_index(i)) #| } #| { len, buf, head, tail } #|} #|pub fn[A] T::flatten(self : T[T[A]]) -> T[A] { #| let mut len = 0 #| for deque in self { #| len += deque.length() #| } #| let target = T::{ #| buf: UninitializedArray::make(len), #| len, #| head: 0, #| tail: len - 1, #| } #| let mut i = 0 #| for deque in self { #| let cap = deque.buf.length() #| let head_len = cap - deque.head #| target.buf.unsafe_blit(i, deque.buf, deque.head, head_len) #| if head_len < deque.len { #| target.buf.unsafe_blit(i + head_len, deque.buf, 0, deque.len - head_len) #| } #| i += deque.len #| } #| target #|} #|pub fn[A] T::drain(self : T[A], start~ : Int, len? : Int) -> T[A] { #| let len = match len { #| Some(l) => if l > self.len { self.len } else { l } #| None => self.len - start #| } #| if len == 0 { #| return new() #| } #| let deque = T::{ #| buf: UninitializedArray::make(len), #| len, #| head: 0, #| tail: len - 1, #| } #| let cap = self.buf.length() #| let start_idx = (self.head + start) % cap #| let start_len = cap - start_idx #| if start_len < len { #| deque.buf.unsafe_blit(0, self.buf, start_idx, start_len) #| deque.buf.unsafe_blit(start_len, self.buf, 0, len - start_len) #| for i in 0..= 0; i = i - 1 { #| self.buf[(new_head + i) % cap] = self.buf[(self.head + i) % cap] #| set_null(self.buf, (self.head + i) % cap) #| } #| self.head = new_head % cap #| self.len -= len #| deque #|} #|#locals(cmp) #|pub fn[A] binary_search_by(self : T[A], cmp : (A) -> Int) -> Result[Int, Int] { #| let len = self.len #| for i = 0, j = len; i < j; { #| let h = i + (j - i) / 2 #| let ord = cmp(self[h]) #| if ord < 0 { #| continue h + 1, j #| } else { #| continue i, h #| } #| } else { #| if i < len && cmp(self[i]) == 0 { #| Ok(i) #| } else { #| Err(i) #| } #| } #|} #|pub fn[A] get(self : T[A], index : Int) -> A? { #| if index >= 0 && index < self.len { #| let physical_index = (self.head + index) % self.buf.length() #| Some(self.buf[physical_index]) #| } else { #| None #| } #|} #|pub fn[A : Compare] binary_search(self : T[A], value : A) -> Result[Int, Int] { #| self.binary_search_by(x => x.compare(value)) #|} #|pub impl[A : Compare] Compare for T[A] with compare(self, other) { #| let len_self = self.length() #| let len_other = other.length() #| let cmp = len_self.compare(len_other) #| guard cmp is 0 else { return cmp } #| for i in 0.. Unit { #| guard self.len > 0 else { return } #| let cap = self.buf.length() #| let mut left = self.head #| let mut right = self.tail #| for _ in 0..<(self.len / 2) { #| let temp = self.buf[left] #| self.buf[left] = self.buf[right] #| self.buf[right] = temp #| left = (left + 1) % cap #| right = (right - 1 + cap) % cap #| } #|} #|pub fn[A] T::rev(self : T[A]) -> T[A] { #| let len = self.len #| let new_buf = UninitializedArray::make(len) #| for i in 0.. Int) -> Unit { #| let n = self.len #| let buf_length = self.buf.length() #| for i = n - 1; i > 0; i = i - 1 { #| let j = rand(i + 1) #| let i_pos = (self.head + i) % buf_length #| let j_pos = (self.head + j) % buf_length #| let tmp = self.buf[i_pos] #| self.buf[i_pos] = self.buf[j_pos] #| self.buf[j_pos] = tmp #| } #|} #|pub fn[A] shuffle(self : T[A], rand~ : (Int) -> Int) -> T[A] { #| let new_deque = self.copy() #| new_deque.shuffle_in_place(rand~) #| new_deque #|} ), "types.mbt": ( #|struct T[A] { #| mut buf : UninitializedArray[A] #| mut len : Int #| mut head : Int #| mut tail : Int #|} ), }, ) ///| let moonbitlang_core_double_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/double", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/int64": moonbitlang_core_int64_module, "moonbitlang/core/uint64": moonbitlang_core_uint64_module, "moonbitlang/core/double/internal/ryu": moonbitlang_core_double_internal_ryu_module, }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/builtin", #| "moonbitlang/core/int64", #| "moonbitlang/core/uint64", #| "moonbitlang/core/double/internal/ryu" #| ], #| "targets": { #| "exp_js.mbt": ["js"], #| "exp_nonjs.mbt": ["not", "js"], #| "log_js.mbt": ["js"], #| "log_nonjs.mbt": ["not", "js"], #| "mod_js.mbt": ["js"], #| "mod_nonjs.mbt": ["not", "js"], #| "pow_js.mbt": ["js"], #| "pow_nonjs.mbt": ["not", "js"], #| "trig_js.mbt" : ["js"], #| "trig_nonjs.mbt" : ["not", "js"], #| "round_js.mbt": ["js"], #| "round_wasm.mbt": ["wasm", "wasm-gc"], #| "round.mbt": ["not", "js", "wasm", "wasm-gc"], #| "to_uint_wasm.mbt": ["wasm", "wasm-gc"], #| "to_uint.mbt": ["not", "wasm", "wasm-gc"], #| "hyperbolic_js.mbt": ["js"], #| "hyperbolic_nonjs.mbt": ["not", "js"], #| "cbrt_js.mbt" : ["js"], #| "cbrt_nonjs.mbt" : ["not", "js"], #| "hypot_js.mbt" : ["js"], #| "hypot_nonjs.mbt" : ["not", "js"], #| "scalbn.mbt" : ["not", "js"] #| } #|} ), "cbrt_js.mbt": ( #|#deprecated("use `@math.cbrt` instead") #|#coverage.skip #|pub fn Double::cbrt(self : Double) -> Double = "Math" "cbrt" ), "cbrt_nonjs.mbt": ( #|#deprecated("use `@math.cbrt` instead") #|#coverage.skip #|pub fn Double::cbrt(self : Double) -> Double { #| if self.is_inf() || self.is_nan() || self == 0.0 { #| return self #| } #| let b1 : UInt = 715094163 // B1 = (682-0.03306235651)*2**20 #| let b2 : UInt = 696219795 // B2 = (664-0.03306235651)*2**20 #| let c = 5.42857142857142815906e-01 // 19/35 = 0x3FE15F15, 0xF15F15F1 #| let d = -7.05306122448979611050e-01 // -864/1225 = 0xBFE691DE, 0x2532C834 #| let e = 1.41428571428571436819e+00 // 99/70 = 0x3FF6A0EA, 0x0EA0EA0F #| let f = 1.60714285714285720630e+00 // 45/28 = 0x3FF9B6DB, 0x6DB6DB6E #| let g = 3.57142857142857150787e-01 // 5/14 = 0x3FD6DB6D, 0xB6DB6DB7 #| let hx = get_high_word(self).reinterpret_as_int() #| let sign = if self < 0.0 { true } else { false } #| let self = abs(self) #| let t = if hx < 0x00100000 { #| let t : UInt64 = 0x43500000_00000000 #| let t : Double = t.reinterpret_as_double() #| let t = t * self #| set_high_word(0, get_high_word(t) / 3 + b2) #| } else { #| set_high_word(0, hx.reinterpret_as_uint() / 3 + b1) #| } #| let r = t * t / self #| let s = c + r * t #| let t = t * (g + f / (s + e + d / s)) #| let t = set_high_word(0, get_high_word(t) + 0x00000001) #| let s = t * t #| let r = self / s #| let w = t + t #| let r = (r - t) / (w + r) #| let t = t + t * r #| if sign { #| -t #| } else { #| t #| } #|} ), "deprecated.mbt": ( #|#deprecated("Use `@double.not_a_number` instead") #|#coverage.skip #|pub fn Double::nan() -> Double { #| not_a_number #|} #|#deprecated("Use `@double.infinity` and `@double.neg_infinity` instead") #|#coverage.skip #|pub fn Double::inf(sign : Int) -> Double { #| if sign >= 0 { #| infinity #| } else { #| neg_infinity #| } #|} #|#deprecated("Use `@double.min_positive` instead") #|#coverage.skip #|pub fn Double::min_normal() -> Double { #| min_positive #|} ), "double.mbt": ( #|pub let not_a_number : Double = 0x7FF8000000000001L.reinterpret_as_double() #|pub let infinity : Double = 0x7FF0000000000000L.reinterpret_as_double() #|pub let neg_infinity : Double = 0xFFF0000000000000L.reinterpret_as_double() #|pub let max_value : Double = 0x7FEFFFFFFFFFFFFFL.reinterpret_as_double() #|pub let min_value : Double = 0xFFEFFFFFFFFFFFFFL.reinterpret_as_double() #|pub let min_positive : Double = 0x0010000000000000L.reinterpret_as_double() #|pub fn Double::from_int(i : Int) -> Double { #| i.to_double() #|} #|pub fn from_int(i : Int) -> Double { #| i.to_double() #|} #|pub fn Double::abs(self : Double) -> Double = "%f64.abs" #|pub fn signum(self : Double) -> Double { #| if self < 0.0 { #| -1.0 #| } else if self > 0.0 { #| 1.0 #| } else { #| self // handles 0.0, -0.0, NaN #| } #|} #|pub fn is_nan(self : Double) -> Bool { #| self != self #|} #|pub fn is_inf(self : Double) -> Bool { #| self > max_value || self < min_value #|} #|pub fn is_pos_inf(self : Double) -> Bool { #| self > max_value #|} #|pub fn is_neg_inf(self : Double) -> Bool { #| self < min_value #|} #|test "from_int" { #| assert_eq(from_int(1), 1.0) #| assert_eq(from_int(0), 0.0) #| assert_eq(from_int(100000), 1.0e5) #|} #|test "abs" { #| let d = -1.0 #| assert_eq(d.abs(), 1.0) #| assert_eq(1.0.abs(), 1.0) #|} #|test "signum" { #| let d = -2.0 #| assert_eq(d.signum(), -1.0) #| assert_eq(1.0.signum(), 1.0) #| assert_eq(0.0.signum(), 0.0) #| assert_true(not_a_number.signum().is_nan()) #|} #|test "is_nan" { #| assert_true(not_a_number.is_nan()) #| assert_false(0.0.is_nan()) #| assert_false(12345.678.is_nan()) #| assert_false(infinity.is_nan()) #| assert_false(neg_infinity.is_nan()) #|} #|test "is_inf" { #| assert_true(infinity.is_inf()) #| assert_true(neg_infinity.is_inf()) #| assert_false(0.0.is_inf()) #| assert_false(12345.678.is_inf()) #|} #|test "is_pos_inf" { #| assert_true(infinity.is_pos_inf()) #| assert_false(neg_infinity.is_pos_inf()) #| assert_false(0.0.is_pos_inf()) #| assert_false(12345.678.is_pos_inf()) #|} #|test "is_neg_inf" { #| assert_false(infinity.is_neg_inf()) #| assert_true(neg_infinity.is_neg_inf()) #| assert_false(0.0.is_neg_inf()) #| assert_false(12345.678.is_neg_inf()) #|} #|test "min equal to neg max" { #| assert_true(min_value == -max_value) #|} #|pub impl Hash for Double with hash(self) { #| self.reinterpret_as_int64() |> Hash::hash() #|} #|pub impl Hash for Double with hash_combine(self, hasher) { #| hasher.combine_double(self) #|} #|#intrinsic("%f64.to_string") #|pub fn to_string(self : Double) -> String { #| @ryu.ryu_to_string(self) #|} #|pub impl Show for Double with output(self, logger) { #| logger.write_string(self.to_string()) #|} #|pub fn Double::is_close( #| self : Self, #| other : Self, #| relative_tolerance? : Self = 1.0e-09, #| absolute_tolerance? : Self = 0.0, #|) -> Bool { #| if relative_tolerance < 0.0 || absolute_tolerance < 0.0 { #| abort("Tolerances must be non-negative") #| } #| if self == other { #| return true #| } #| if self.is_inf() || other.is_inf() { #| return false #| } #| let diff = (other - self).abs() #| return ( #| diff <= (relative_tolerance * other).abs() || #| diff <= (relative_tolerance * self).abs() #| ) || #| diff <= absolute_tolerance #|} #|pub fn to_be_bytes(self : Double) -> Bytes { #| self.reinterpret_as_uint64().to_be_bytes() #|} #|pub fn to_le_bytes(self : Double) -> Bytes { #| self.reinterpret_as_uint64().to_le_bytes() #|} ), "exp_js.mbt": ( #|#deprecated("use `Double::exp` instead") #|#coverage.skip #|pub fn Double::exp(self : Double) -> Double = "Math" "exp" #|#deprecated("use `Double::expm1` instead") #|#coverage.skip #|pub fn Double::expm1(self : Double) -> Double = "Math" "expm1" ), "exp_nonjs.mbt": ( #|#deprecated("use `@math.exp` instead") #|#coverage.skip #|pub fn Double::exp(self : Double) -> Double { #| fn get_high_word(x : Double) -> UInt { #| (x.reinterpret_as_uint64() >> 32).to_uint() #| } #| fn get_low_word(x : Double) -> UInt { #| x.reinterpret_as_uint64().to_uint() #| } #| fn insert_words(ix0 : UInt64, ix1 : UInt64) -> Double { #| let mut bits : UInt64 = 0 #| bits = bits | (ix0 << 32) #| bits = bits | ix1 #| bits.reinterpret_as_double() #| } #| let mut x = self #| let one = 1.0 #| let halF = [0.5, -0.5] #| let o_threshold = 7.09782712893383973096e+02 #| let u_threshold = -7.45133219101941108420e+02 #| let ln2HI = [6.93147180369123816490e-01, -6.93147180369123816490e-01] #| let ln2LO = [1.90821492927058770002e-10, -1.90821492927058770002e-10] #| let invln2 = 1.44269504088896338700e+00 #| let p1 = 1.66666666666666019037e-01 #| let p2 = -2.77777777770155933842e-03 #| let p3 = 6.61375632143793436117e-05 #| let p4 = -1.65339022054652515390e-06 #| let p5 = 4.13813679705723846039e-08 #| let e = 2.718281828459045 #| let mut hi = 0.0 #| let mut lo = 0.0 #| let huge = 1.0e+300 #| let twom1000 = 9.33263618503218878990e-302 #| let two1023 = 8.988465674311579539e307 #| let mut k : Int = 0 #| let mut hx : UInt = get_high_word(self) #| let xsb : Int = ((hx >> 31) & 1).reinterpret_as_int() #| hx = hx & 0x7FFFFFFF #| if hx >= 0x40862E42 { #| if hx >= 0x7FF00000 { #| let lx : UInt = get_low_word(self) #| if ((hx & 0xFFFFF) | lx) != 0 { #| return self + self #| } else if xsb == 0 { #| return self #| } else { #| return 0.0 #| } #| } #| if self > o_threshold { #| return huge * huge #| } #| if self < u_threshold { #| return twom1000 * twom1000 #| } #| } #| if hx > 0x3FD62E42 { #| if hx < 0x3FF0A2B2 { #| if self == 1.0 { #| return e #| } #| hi = self - ln2HI[xsb] #| lo = ln2LO[xsb] #| k = 1 - xsb - xsb #| } else { #| k = (invln2 * self + halF[xsb]).to_int() #| let t = k.to_double() #| hi = self - t * ln2HI[0] #| lo = t * ln2LO[0] #| } #| x = hi - lo #| } else if hx < 0x3E300000 { #| if huge + x > one { #| return one + x #| } #| } else { #| k = 0 #| } #| let t = x * x #| let twopk = if k >= -1021 { #| insert_words( #| (0x3FF00000 + (k.reinterpret_as_uint() << 20).reinterpret_as_int()) #| .to_int64() #| .reinterpret_as_uint64(), #| 0, #| ) #| } else { #| insert_words( #| 0x3FF00000UL + ((k + 1000).reinterpret_as_uint() << 20).to_uint64(), #| 0, #| ) #| } #| let c = x - t * (p1 + t * (p2 + t * (p3 + t * (p4 + t * p5)))) #| if k == 0 { #| return one - (x * c / (c - 2.0) - x) #| } #| let y = one - (lo - x * c / (2.0 - c) - hi) #| if k >= -1021 { #| if k == 1024 { #| return y * 2.0 * two1023 #| } else { #| return y * twopk #| } #| } else { #| return y * twopk * twom1000 #| } #|} #|#deprecated("use `@math.expm1` instead") #|#coverage.skip #|pub fn Double::expm1(self : Double) -> Double { #| if self.is_nan() { #| return not_a_number #| } #| let o_threshold = 7.09782712893383973096e+02 #| if self > o_threshold { #| return infinity #| } #| if self.is_inf() { #| return -1.0 #| } #| let huge = 1.0e+300 #| let tiny = 1.0e-300 #| let ln2_hi = 6.93147180369123816490e-01 #| let ln2_lo = 1.90821492927058770002e-10 #| let invln2 = 1.44269504088896338700e+00 #| let q1 = -3.33333333333331316428e-02 #| let q2 = 1.58730158725481460165e-03 #| let q3 = -7.93650757867487942473e-05 #| let q4 = 4.00821782732936239552e-06 #| let q5 = -2.01099218183624371326e-07 #| let mut x = self #| let mut hx = get_high_word(x) #| let xsb : Int = (hx & 0x80000000).reinterpret_as_int() #| let mut y : Double = if xsb == 0 { x } else { -x } #| hx = hx & 0x7fffffff #| if hx >= 0x4043687A { #| if xsb != 0 { #| if x + tiny < 0.0 { #| return tiny - 1.0 #| } #| } #| } #| let mut hi = 0.0 #| let mut lo = 0.0 #| let mut k = 0 #| let mut c = 0.0 #| let mut t = 0.0 #| if hx > 0x3fd62e42 { #| if hx < 0x3FF0A2B2 { #| hi = if xsb == 0 { x - ln2_hi } else { x + ln2_hi } #| lo = if xsb == 0 { ln2_lo } else { -ln2_lo } #| k = if xsb == 0 { 1 } else { -1 } #| } else { #| k = (invln2 * x + (if xsb == 0 { 0.5 } else { -0.5 })).to_int() #| t = k.to_double() #| hi = x - t * ln2_hi #| lo = t * ln2_lo #| } #| x = hi - lo #| c = hi - x - lo #| } else if hx < 0x3c900000 { #| t = huge + x #| return x - (t - (huge + x)) #| } else { #| k = 0 #| } #| let hfx : Double = 0.5 * x #| let hxs : Double = x * hfx #| let r1 : Double = 1.0 + #| hxs * (q1 + hxs * (q2 + hxs * (q3 + hxs * (q4 + hxs * q5)))) #| let t : Double = 3.0 - r1 * hfx #| let e : Double = hxs * ((r1 - t) / (6.0 - x * t)) #| if k == 0 { #| return x - (x * e - hxs) #| } else { #| let e : Double = x * (e - c) - c #| let e : Double = e - hxs #| if k == -1 { #| return 0.5 * (x - e) - 0.5 #| } #| if k == 1 { #| return if x < -0.25 { #| -2.0 * (e - (x + 0.5)) #| } else { #| 1.0 + 2.0 * (x - e) #| } #| } #| if k <= -2 || k > 56 { #| y = 1.0 - (e - x) #| y = set_high_word(y, get_high_word(y) + (k << 20).reinterpret_as_uint()) #| return y - 1.0 #| } #| let mut t : Double = 1.0 #| if k < 20 { #| t = set_high_word(0, (0x3ff00000 - (0x200000 >> k)).reinterpret_as_uint()) #| y = t - (e - x) #| y = set_high_word(y, get_high_word(y) + (k << 20).reinterpret_as_uint()) #| } else { #| t = set_high_word(0, ((0x3ff - k) << 20).reinterpret_as_uint()) #| y = x - (e + t) + 1.0 #| y = set_high_word(y, get_high_word(y) + (k << 20).reinterpret_as_uint()) #| } #| } #| y #|} ), "hyperbolic_js.mbt": ( #|#deprecated("use `@math.sinh` instead") #|#coverage.skip #|pub fn Double::sinh(self : Double) -> Double = "Math" "sinh" #|#deprecated("use `@math.cosh` instead") #|#coverage.skip #|pub fn Double::cosh(self : Double) -> Double = "Math" "cosh" #|#deprecated("use `@math.tanh` instead") #|#coverage.skip #|pub fn Double::tanh(self : Double) -> Double = "Math" "tanh" #|#deprecated("use `@math.asinh` instead") #|#coverage.skip #|pub fn Double::asinh(self : Double) -> Double = "Math" "asinh" #|#deprecated("use `@math.acosh` instead") #|#coverage.skip #|pub fn Double::acosh(self : Double) -> Double = "Math" "acosh" #|#deprecated("use `@math.atanh` instead") #|#coverage.skip #|pub fn Double::atanh(self : Double) -> Double = "Math" "atanh" ), "hyperbolic_nonjs.mbt": ( #|#deprecated("use `@math.sinh` instead") #|#coverage.skip #|pub fn Double::sinh(self : Double) -> Double { #| if self.is_nan() || self.is_inf() { #| return self #| } #| let ix = get_high_word(self).reinterpret_as_int() & 0x7fffffff #| let abs_x = self.abs() #| let shuge = 1.0e307 #| let h = if self < 0.0 { -0.5 } else { 0.5 } #| if ix < 0x40360000 { #| if ix < 0x3e300000 { #| if shuge + self > 1.0 { #| return self #| } #| } #| let t = abs_x.expm1() #| if ix < 0x3ff00000 { #| return h * (2.0 * t - t * t / (t + 1.0)) #| } #| return h * (t + t / (t + 1.0)) #| } #| if ix < 0x40862E42 { #| return h * abs_x.exp() #| } #| if abs_x.reinterpret_as_uint64() < 0x408633ce8fb9f87d { #| let w = Double::exp(0.5 * abs_x) #| let t = h * w #| return t * w #| } #| self * shuge #|} #|#deprecated("use `@math.cosh` instead") #|#coverage.skip #|pub fn Double::cosh(self : Double) -> Double { #| if self.is_nan() { #| return self #| } #| if self.is_inf() { #| return infinity #| } #| let ix = get_high_word(self).reinterpret_as_int() & 0x7fffffff #| if ix < 0x3fd62e43 { #| let t = self.abs().expm1() #| let w = 1.0 + t #| if ix < 0x3c800000 { #| return w #| } #| return 1.0 + t * t / (w + w) #| } #| if ix < 0x40360000 { #| let t = self.abs().exp() #| return 0.5 * t + 0.5 / t #| } #| if ix < 0x40862E42 { #| return 0.5 * self.abs().exp() #| } #| let lx = get_low_word(self).reinterpret_as_int() #| if ix < 0x408633ce || (ix == 0x408633ce && lx <= 0x8fb9f87d) { #| let w = Double::exp(0.5 * self.abs()) #| let t = 0.5 * w #| return t * w #| } #| infinity #|} #|#deprecated("use `@math.tanh` instead") #|#coverage.skip #|pub fn Double::tanh(self : Double) -> Double { #| if self.is_nan() { #| return self #| } #| if self.is_pos_inf() { #| return 1.0 #| } #| if self.is_neg_inf() { #| return -1.0 #| } #| let ix = get_high_word(self).reinterpret_as_int() & 0x7fffffff #| let tiny = 1.0e-300 #| let z = if ix < 0x40360000 { #| if ix < 0x3c800000 { #| self * (1.0 + self) #| } else if ix >= 0x3ff00000 { #| let t = (2.0 * self.abs()).expm1() #| 1.0 - 2.0 / (t + 2.0) #| } else { #| let t = (-2.0 * self.abs()).expm1() #| -t / (t + 2.0) #| } #| } else { #| 1.0 - tiny #| } #| if self >= 0.0 { #| z #| } else { #| -z #| } #|} #|#deprecated("use `@math.asinh` instead") #|#coverage.skip #|pub fn Double::asinh(self : Double) -> Double { #| if self.is_nan() || self.is_inf() { #| return self #| } #| let one : Double = 1.0 #| let ln2 : Double = 6.93147180559945286227e-01 #| let huge : Double = 1.0e300 #| let hx = get_high_word(self).reinterpret_as_int() #| let ix = hx & 0x7fffffff #| if ix < 0x3e300000 { #| if huge + self > one { #| return self #| } #| } #| let w : Double = if ix > 0x41b00000 { #| self.abs().ln() + ln2 #| } else if ix > 0x40000000 { #| let t = self.abs() #| (2.0 * t + one / ((self * self + one).sqrt() + t)).ln() #| } else { #| let t = self * self #| (self.abs() + t / (one + (one + t).sqrt())).ln_1p() #| } #| if hx > 0 { #| w #| } else { #| -w #| } #|} #|#deprecated("use `@math.acosh` instead") #|#coverage.skip #|pub fn Double::acosh(self : Double) -> Double { #| let one = 1.0 #| let hx = get_high_word(self).reinterpret_as_int() #| if self < 1.0 || self.is_nan() { #| return not_a_number #| } else if self == 1.0 { #| return 0.0 #| } else if self.is_pos_inf() { #| return infinity #| } else if hx >= 0x41b00000 { #| return self.ln() + ln2 #| } else if hx > 0x40000000 { #| let t = self * self #| return (2.0 * self - one / (self + (t - one).sqrt())).ln() #| } else { #| let t = self - one #| return (t + (2.0 * t + t * t).sqrt()).ln_1p() #| } #|} #|#deprecated("use `@math.atanh` instead") #|#coverage.skip #|pub fn Double::atanh(self : Double) -> Double { #| let hx : Int = get_high_word(self).reinterpret_as_int() #| let ix = hx & 0x7fffffff #| if self.abs() > 1.0 { #| return not_a_number #| } #| if self == 1.0 { #| return infinity #| } #| if self == -1.0 { #| return neg_infinity #| } #| if ix < 0x3e300000 && 1.0e300 + self > 0.0 { #| return self #| } #| let self = self.abs() #| let t = if self <= 0.5 { #| let t = self + self #| 0.5 * (t + t * self / (1.0 - self)).ln_1p() #| } else { #| 0.5 * ((self + self) / (1.0 - self)).ln_1p() #| } #| if hx >= 0 { #| t #| } else { #| -t #| } #|} ), "hypot_js.mbt": ( #|#deprecated("use `@math.hypot` instead") #|#coverage.skip #|pub fn Double::hypot(self : Double, y : Double) -> Double = "Math" "hypot" ), "hypot_nonjs.mbt": ( #|#deprecated("use `@math.hypot` instead") #|#coverage.skip #|pub fn Double::hypot(self : Double, y : Double) -> Double { #| if self.is_nan() || y.is_nan() { #| return not_a_number #| } #| if self.is_inf() || y.is_inf() { #| return infinity #| } #| let x = self.abs() #| let y = y.abs() #| let double_epsilon : Double = 0x0.0000000000001P-1022 #| let (x, y) = if y > x { (y, x) } else { (x, y) } #| if x * double_epsilon >= y { #| return x #| } #| let r = y / x #| x * (1.0 + r * r).sqrt() #|} ), "log_js.mbt": ( #|#deprecated("use `@math.ln` instead") #|#converage.skip #|pub fn Double::ln(self : Double) -> Double = "Math" "log" #|#deprecated("use `@math.log2` instead") #|#converage.skip #|pub fn Double::log2(self : Double) -> Double = "Math" "log2" #|#deprecated("use `@math.log10` instead") #|#converage.skip #|pub fn Double::log10(self : Double) -> Double = "Math" "log10" #|#deprecated("use `@math.ln_1p` instead") #|#converage.skip #|pub fn Double::ln_1p(self : Double) -> Double = "Math" "log1p" ), "log_nonjs.mbt": ( #|let sqrt2 = 1.41421356237309504880168872420969807856967187537694807317667974 #|let ln2 = 0.693147180559945309417232121458176568075500134360255254120680009 #|let ln2_hi = 6.93147180369123816490e-01 // 3fe62e42 fee00000 #|let ln2_lo = 1.90821492927058770002e-10 // 3dea39ef 35793c76 #|let l1 = 6.666666666666735130e-01 // 3FE55555 55555593 #|let l2 = 3.999999999940941908e-01 // 3FD99999 9997FA04 #|let l3 = 2.857142874366239149e-01 // 3FD24924 94229359 #|let l4 = 2.222219843214978396e-01 // 3FCC71C5 1D8E78AF #|let l5 = 1.818357216161805012e-01 // 3FC74664 96CB03DE #|let l6 = 1.531383769920937332e-01 // 3FC39A09 D078C69F #|let l7 = 1.479819860511658591e-01 // 3FC2F112 DF3E5244 #|fn normalize(f : Double) -> (Double, Int) { #| if f.abs() < min_positive { #| return (f * (1L << 52).to_double(), -52) #| } #| (f, 0) #|} #|fn frexp(f : Double) -> (Double, Int) { #| if f == 0.0 || f.is_inf() || f.is_nan() { #| return (f, 0) #| } #| let (norm_f, exp) = normalize(f) #| let u = norm_f.reinterpret_as_uint64() #| let exp = exp + ((u >> 52) & 0x7FF).to_int() - 1022 #| let frac = ((u & (0x7FFUL << 52).lnot()) | (1022UL << 52)).reinterpret_as_double() #| return (frac, exp) #|} #|#deprecated("use `@math.ln` instead") #|#coverage.skip #|pub fn Double::ln(self : Double) -> Double { #| if self < 0.0 { #| return not_a_number #| } else if self.is_nan() || self.is_inf() { #| return self #| } else if self == 0.0 { #| return neg_infinity #| } #| let (f1, ki) = frexp(self) #| let (f, k) = if f1 < sqrt2 / 2.0 { #| (f1 * 2.0 - 1.0, (ki - 1).to_double()) #| } else { #| (f1 - 1.0, ki.to_double()) #| } #| let s = f / (2.0 + f) #| let s2 = s * s #| let s4 = s2 * s2 #| let t1 = s2 * (l1 + s4 * (l3 + s4 * (l5 + s4 * l7))) #| let t2 = s4 * (l2 + s4 * (l4 + s4 * l6)) #| let r = t1 + t2 #| let hfsq = 0.5 * f * f #| k * ln2_hi - (hfsq - (s * (hfsq + r) + k * ln2_lo) - f) #|} #|#deprecated("use `@math.log2` instead") #|#coverage.skip #|pub fn Double::log2(self : Double) -> Double { #| let (f, e) = frexp(self) #| if f == 0.5 { #| return e.to_double() - 1.0 #| } #| Double::ln(f) / ln2 + e.to_double() #|} #|#deprecated("use `@math.log10` instead") #|#coverage.skip #|pub fn Double::log10(self : Double) -> Double { #| if self < 0.0 { #| return not_a_number #| } else if self.is_nan() || self.is_inf() { #| return self #| } else if self == 0.0 { #| return neg_infinity #| } #| let ivln10 = 4.34294481903251816668e-01 #| let log10_2hi = 3.01029995663611771306e-01 #| let log10_2lo = 3.69423907715893078616e-13 #| let (f, e) = frexp(self) #| let (f, e) = if e >= 1 { #| (f * 2.0, (e - 1).to_double()) #| } else { #| (f, e.to_double()) #| } #| let z = e * log10_2lo + ivln10 * f.ln() #| z + e * log10_2hi #|} #|#deprecated("use `@math.ln_1p` instead") #|#coverage.skip #|pub fn Double::ln_1p(self : Double) -> Double { #| if self < -1.0 || self.is_nan() { #| return not_a_number #| } #| if self == -1.0 { #| return neg_infinity #| } #| if self.is_inf() { #| return infinity #| } #| let ln2_hi = 6.93147180369123816490e-01 #| let ln2_lo = 1.90821492927058770002e-10 #| let two54 = 1.80143985094819840000e+16 #| let lp1 = 6.666666666666735130e-01 #| let lp2 = 3.999999999940941908e-01 #| let lp3 = 2.857142874366239149e-01 #| let lp4 = 2.222219843214978396e-01 #| let lp5 = 1.818357216161805012e-01 #| let lp6 = 1.531383769920937332e-01 #| let zero = 0.0 #| let lp7 = 1.479819860511658591e-01 #| let hx = get_high_word(self).reinterpret_as_int() #| let ax = hx & 0x7fffffff #| let mut f = 0.0 #| let mut c = 0.0 #| let mut s = 0.0 #| let mut z = 0.0 #| let mut r = 0.0 #| let mut u = 0.0 #| let mut hu = 0 #| let mut k = 1 #| if hx < 0x3FDA827A { #| if ax < 0x3e200000 { #| if two54 + self > zero && ax < 0x3c900000 { #| return self #| } else { #| return self - self * self * 0.5 #| } #| } #| if hx > 0 || hx <= 0xbfd2bec3 { #| k = 0 #| f = self #| hu = 1 #| } #| } #| if k != 0 { #| if hx < 0x43400000 { #| u = 1.0 + self #| hu = get_high_word(u).reinterpret_as_int() #| k = (hu >> 20) - 1023 #| c = if k > 0 { 1.0 - (u - self) } else { self - (u - 1.0) } #| c /= u #| } else { #| u = self #| hu = get_high_word(u).reinterpret_as_int() #| k = (hu >> 20) - 1023 #| c = 0.0 #| } #| hu = hu & 0x000fffff #| if hu < 0x6a09e { #| u = set_high_word(u, hu.reinterpret_as_uint() | 0x3ff00000) #| } else { #| k += 1 #| u = set_high_word(u, hu.reinterpret_as_uint() | 0x3fe00000) #| hu = (0x00100000 - hu) >> 2 #| } #| f = u - 1.0 #| } #| let hfsq = 0.5 * f * f #| if hu == 0 { #| if f == zero { #| if k == 0 { #| return zero #| } else { #| c += k.to_double() * ln2_lo #| return k.to_double() * ln2_hi + c #| } #| } #| r = hfsq * (1.0 - 0.66666666666666666 * f) #| if k == 0 { #| return f - r #| } else { #| return k.to_double() * ln2_hi - (r - (k.to_double() * ln2_lo + c) - f) #| } #| } #| s = f / (2.0 + f) #| z = s * s #| r = z * #| (lp1 + z * (lp2 + z * (lp3 + z * (lp4 + z * (lp5 + z * (lp6 + z * lp7)))))) #| if k == 0 { #| return f - (hfsq - s * (hfsq + r)) #| } else { #| return k.to_double() * ln2_hi - #| (hfsq - (s * (hfsq + r) + (k.to_double() * ln2_lo + c)) - f) #| } #|} ), "math_functions.mbt": ( #|pub fnalias Double::( #| sin, #| cos, #| tan, #| asin, #| acos, #| atan, #| atan2, #| exp, #| expm1, #| pow, #| ln, #| log2, #| log10, #| ln_1p, #| sinh, #| cosh, #| tanh, #| asinh, #| acosh, #| atanh, #| hypot, #| cbrt, #| is_close, #| trunc, #| floor, #| ceil, #| round, #| abs #|) ), "mod_js.mbt": ( #|extern "js" fn mod_ffi(self : Double, other : Double) -> Double = #| #| (a, b) => (a % b) #|pub impl Mod for Double with op_mod(self, other) { #| self.mod_ffi(other) #|} ), "mod_nonjs.mbt": ( #|pub impl Mod for Double with op_mod(self : Double, other : Double) -> Double { #| let x = self #| let y = other #| let mut uint64_x = x.reinterpret_as_uint64() #| let mut uint64_y = y.reinterpret_as_uint64() #| let mut ex = ((uint64_x >> 52) & 0x7FF).to_int() #| let mut ey = ((uint64_y >> 52) & 0x7FF).to_int() #| let sign_x = uint64_x >> 63 #| let mut i : UInt64 = 0 #| if uint64_y << 1 == 0 || y.is_nan() || ex == 0x7ff { #| return x * y / (x * y) #| } #| if uint64_x << 1 <= uint64_y << 1 { #| if uint64_x << 1 == uint64_y << 1 { #| return 0.0 * x #| } #| return x #| } #| if ex == 0 { #| i = uint64_x << 12 #| while i >> 63 == 0 { #| ex -= 1 #| i = i << 1 #| } #| uint64_x = uint64_x << (-ex + 1) #| } else { #| uint64_x = uint64_x & (18446744073709551615UL >> 12) #| uint64_x = uint64_x | (1UL << 52) #| } #| if ey == 0 { #| i = uint64_y << 12 #| while i >> 63 == 0 { #| ey -= 1 #| i = i << 1 #| } #| uint64_y = uint64_y << (-ey + 1) #| } else { #| uint64_y = uint64_y & (18446744073709551615UL >> 12) #| uint64_y = uint64_y | (1UL << 52) #| } #| while ex > ey { #| i = uint64_x - uint64_y #| if i >> 63 == 0 { #| if i == 0 { #| return 0.0 * x #| } #| uint64_x = i #| } #| uint64_x = uint64_x << 1 #| ex -= 1 #| } #| i = uint64_x - uint64_y #| if i >> 63 == 0 { #| if i == 0 { #| return 0.0 * x #| } #| uint64_x = i #| } #| while uint64_x >> 52 == 0 { #| uint64_x = uint64_x << 1 #| ex -= 1 #| } #| if ex > 0 { #| uint64_x = uint64_x - (1UL << 52) #| uint64_x = uint64_x | (ex.to_uint64() << 52) #| } else { #| uint64_x = uint64_x >> (-ex + 1) #| } #| uint64_x = uint64_x | (sign_x << 63) #| uint64_x.reinterpret_as_double() #|} ), "pow_js.mbt": ( #|pub fn Double::pow(self : Double, other : Double) -> Double = "Math" "pow" ), "pow_nonjs.mbt": ( #|let pow_bp : FixedArray[Double] = [1.0, 1.5] #|let pow_dp_h : FixedArray[Double] = [0.0, 5.84962487220764160156e-01] #|let pow_dp_l : FixedArray[Double] = [0.0, 1.35003920212974897128e-08] #|const ZERO = 0.0 #|const ONE = 1.0 #|const TWO = 2.0 #|const POW_two53 = 9007199254740992.0 #|const POW_huge = 1.0e300 #|const POW_tiny = 1.0e-300 #|const POW_L1 = 5.99999999999994648725e-01 #|const POW_L2 = 4.28571428578550184252e-01 #|const POW_L3 = 3.33333329818377432918e-01 #|const POW_L4 = 2.72728123808534006489e-01 #|const POW_L5 = 2.30660745775561754067e-01 #|const POW_L6 = 2.06975017800338417784e-01 #|const POW_P1 = 1.66666666666666019037e-01 #|const POW_P2 = -2.77777777770155933842e-03 #|const POW_P3 = 6.61375632143793436117e-05 #|const POW_P4 = -1.65339022054652515390e-06 #|const POW_P5 = 4.13813679705723846039e-08 #|const POW_lg2 = 6.93147180559945286227e-01 #|const POW_lg2_h = 6.93147182464599609375e-01 #|const POW_lg2_l = -1.90465429995776804525e-09 #|const POW_ovt = 8.0085662595372944372e-0017 #|const POW_cp = 9.61796693925975554329e-01 #|const POW_cp_h = 9.61796700954437255859e-01 #|const POW_cp_l = -7.02846165095275826516e-09 #|const POW_ivln2 = 1.44269504088896338700e+00 #|const POW_ivln2_h = 1.44269502162933349609e+00 #|const POW_ivln2_l = 1.92596299112661746887e-08 #|pub fn Double::pow(self : Double, other : Double) -> Double { #| fn set_low_word(d : Double, v : UInt) -> Double { #| let bits : UInt64 = d.reinterpret_as_uint64() #| let bits = bits & 0xFFFF_FFFF_0000_0000 #| let bits = bits | v.to_uint64() #| bits.reinterpret_as_double() #| } #| fn set_high_word(d : Double, v : UInt) -> Double { #| let bits : UInt64 = d.reinterpret_as_uint64() #| let bits = bits & 0x0000_0000_FFFF_FFFF #| let bits = bits | (v.to_uint64() << 32) #| bits.reinterpret_as_double() #| } #| fn get_high_word(x : Double) -> UInt { #| (x.reinterpret_as_uint64() >> 32).to_uint() #| } #| fn get_low_word(x : Double) -> UInt { #| x.reinterpret_as_uint64().to_uint() #| } #| let x = self #| let y = other #| let mut z : Double = 0.0 #| let mut ax : Double = 0.0 #| let mut z_h : Double = 0.0 #| let mut z_l : Double = 0.0 #| let mut p_h : Double = 0.0 #| let mut p_l : Double = 0.0 #| let mut y1 : Double = 0.0 #| let mut t1 : Double = 0.0 #| let mut t2 : Double = 0.0 #| let mut r : Double = 0.0 #| let mut s : Double = 0.0 #| let mut t : Double = 0.0 #| let mut u : Double = 0.0 #| let mut v : Double = 0.0 #| let mut w : Double = 0.0 #| let mut i : Int = 0 #| let mut j : Int = 0 #| let mut k : Int = 0 #| let mut yisint : Int = 0 #| let mut n : Int = 0 #| let hx : Int = (x.reinterpret_as_uint64() >> 32).to_int() #| let lx : UInt = (x.reinterpret_as_uint64() & 0xFFFFFFFF).to_uint() #| let hy : Int = (y.reinterpret_as_uint64() >> 32).to_int() #| let ly : UInt = (y.reinterpret_as_uint64() & 0xFFFFFFFF).to_uint() #| let mut ix : Int = hx & 0x7FFFFFFF #| let iy : Int = hy & 0x7FFFFFFF #| if (iy.reinterpret_as_uint() | ly) == 0 { #| return ONE #| } #| if ix > 0x7FF00000 || #| (ix == 0x7FF00000 && lx != 0) || #| iy > 0x7FF00000 || #| (iy == 0x7FF00000 && ly != 0) { #| return x + y #| } #| if hx < 0 { #| if iy >= 0x43400000 { #| yisint = 2 // even integer y #| } else if iy >= 0x3ff00000 { #| k = (iy >> 20) - 0x3ff // exponent #| if k > 20 { #| j = (ly >> (52 - k)).reinterpret_as_int() #| if j << (52 - k) == ly.reinterpret_as_int() { #| yisint = 2 - (j & 1) #| } #| } else if ly == 0 { #| j = iy >> (20 - k) #| if j << (20 - k) == iy { #| yisint = 2 - (j & 1) #| } #| } #| } #| } #| if ly == 0 { #| if iy == 0x7ff00000 { // y is +-inf #| if ((ix.reinterpret_as_uint() - 0x3ff00000) | lx) == 0 { #| return y - y // inf**+-1 is NaN #| } else if ix >= 0x3ff00000 { // (|x|>1)**+-inf = inf,0 #| return if hy >= 0 { y } else { ZERO } #| } else { // (|x|<1)**-,+inf = inf,0 #| return if hy < 0 { -y } else { ZERO } #| } #| } #| if iy == 0x3ff00000 { // y is +-1 #| if hy < 0 { #| return ONE / x #| } else { #| return x #| } #| } #| if hy == 0x40000000 { // y is 2 #| return x * x #| } #| if hy == 0x3fe00000 { // y is 0.5 #| if hx >= 0 { // x >= +0 #| return x.sqrt() #| } #| } #| } #| ax = x.abs() #| if lx == 0 { #| if ix == 0x7ff00000 || ix == 0 || ix == 0x3ff00000 { #| z = ax // x is +-0,+-inf,+-1 */ #| if hy < 0 { #| z = ONE / z // z = (1/|x|) #| } #| if hx < 0 { #| if ((ix - 0x3ff00000) | yisint) == 0 { #| z = not_a_number #| } else if yisint == 1 { #| z = -z // (x<0)**odd = -(|x|**odd) #| } #| } #| return z #| } #| } #| n = (hx >> 31) + 1 #| if (n | yisint) == 0 { #| return not_a_number #| } #| s = ONE // s (sign of result -ve**odd) = -1 else = 1 #| if (n | (yisint - 1)) == 0 { #| s = -ONE // (-ve)**(odd int) #| } #| if iy > 0x41e00000 { // if |y| > 2**31 */ #| if iy > 0x43f00000 { // if |y| > 2**64, must o/uflow */ #| if ix <= 0x3fefffff { #| return if hy < 0 { POW_huge * POW_huge } else { POW_tiny * POW_tiny } #| } #| if ix >= 0x3ff00000 { #| return if hy > 0 { POW_huge * POW_huge } else { POW_tiny * POW_tiny } #| } #| } #| if ix < 0x3fefffff { #| return if hy < 0 { #| s * POW_huge * POW_huge #| } else { #| s * POW_tiny * POW_tiny #| } #| } #| if ix > 0x3ff00000 { #| return if hy > 0 { #| s * POW_huge * POW_huge #| } else { #| s * POW_tiny * POW_tiny #| } #| } #| t = ax - ONE // t has 20 trailing zeros */ #| w = t * t * (0.5 - t * (0.3333333333333333333333 - t * 0.25)) #| u = POW_ivln2_h * t // POW_ivln2_h has 21 sig. bits */ #| v = t * POW_ivln2_l - w * POW_ivln2 #| t1 = u + v #| t1 = set_low_word(t1, 0) #| t2 = v - (t1 - u) #| } else { #| n = 0 #| if ix < 0x00100000 { #| ax *= POW_two53 #| n -= 53 #| ix = get_high_word(ax).reinterpret_as_int() #| } #| n += (ix >> 20) - 0x3ff #| j = ix & 0x000fffff #| ix = j | 0x3ff00000 // normalize ix #| if j <= 0x3988E { #| k = 0 // |x|> 1) | 0x20000000) + #| 0x00080000 + #| (k.reinterpret_as_uint() << 18), #| ) #| let mut t_l : Double = ax - (t_h - pow_bp[k]) #| let s_l : Double = v * (u - s_h * t_h - s_h * t_l) #| let mut s2 : Double = ss * ss #| r = s2 * #| s2 * #| ( #| POW_L1 + #| s2 * #| (POW_L2 + s2 * (POW_L3 + s2 * (POW_L4 + s2 * (POW_L5 + s2 * POW_L6)))) #| ) #| r += s_l * (s_h + ss) #| s2 = s_h * s_h #| t_h = 3.0 + s2 + r #| t_h = set_low_word(t_h, 0) #| t_l = r - (t_h - 3.0 - s2) #| u = s_h * t_h #| v = s_l * t_h + t_l * ss #| p_h = u + v #| p_h = set_low_word(p_h, 0) #| p_l = v - (p_h - u) #| z_h = POW_cp_h * p_h // cp_h+cp_l = 2/(3*log2) #| z_l = POW_cp_l * p_h + p_l * POW_cp + pow_dp_l[k] #| t = n.to_double() #| t1 = z_h + z_l + pow_dp_h[k] + t #| t1 = set_low_word(t1, 0) #| t2 = z_l - (t1 - t - pow_dp_h[k] - z_h) #| } #| y1 = y #| y1 = set_low_word(y1, 0) #| p_l = (y - y1) * t1 + y * t2 #| p_h = y1 * t1 #| z = p_l + p_h #| j = get_high_word(z).reinterpret_as_int() #| i = get_low_word(z).reinterpret_as_int() #| if j >= 0x40900000 { // z >= 1024 #| if ((j - 0x40900000) | i) != 0 { // if z > 1024 #| return s * POW_huge * POW_huge // overflow #| } else if p_l + POW_ovt > z - p_h { #| return s * POW_huge * POW_huge // overflow #| } #| } else if (j & 0x7fffffff) >= 0x4090cc00 { // z <= -1075 #| if ((j - 0xc090cc00) | i) != 0 { // z < -1075 #| return s * POW_tiny * POW_tiny // underflow #| } else if p_l <= z - p_h { #| return s * POW_tiny * POW_tiny // underflow #| } #| } #| i = j & 0x7fffffff #| k = (i >> 20) - 0x3ff #| n = 0 #| if i > 0x3fe00000 { // if |z| > 0.5, set n = [z+0.5] #| n = j + (0x00100000 >> (k + 1)) #| k = ((n & 0x7fffffff) >> 20) - 0x3ff // new k for n #| t = ZERO #| t = set_high_word(t, (n & (0x000fffff >> k).lnot()).reinterpret_as_uint()) #| n = ((n & 0x000fffff) | 0x00100000) >> (20 - k) #| if j < 0 { #| n = -n #| } #| p_h -= t #| } #| t = p_l + p_h #| t = set_low_word(t, 0) #| u = t * POW_lg2_h #| v = (p_l - (t - p_h)) * POW_lg2 + t * POW_lg2_l #| z = u + v #| w = v - (z - u) #| t = z * z #| t1 = z - #| t * (POW_P1 + t * (POW_P2 + t * (POW_P3 + t * (POW_P4 + t * POW_P5)))) #| r = z * t1 / (t1 - TWO - (w + z * w)) #| z = ONE - (r - z) #| j = get_high_word(z).reinterpret_as_int() #| j += (n.reinterpret_as_uint() << 20).reinterpret_as_int() #| if j >> 20 <= 0 { #| z = scalbn(z, n) #| } else { // subnormal output */ #| let tmp = get_high_word(z).reinterpret_as_int() #| z = set_high_word( #| z, #| (tmp + (n.reinterpret_as_uint() << 20).reinterpret_as_int()).reinterpret_as_uint(), #| ) #| } #| return s * z #|} ), "round.mbt": ( #|let sign_mask : UInt64 = 0x8000_0000_0000_0000 #|let exp_bias = 1023 #|let exp_bits = 11 #|let frac_bits = 52 #|pub fn Double::trunc(self : Double) -> Double { #| let u64 = self.reinterpret_as_uint64() #| let biased_exp = ((u64 >> frac_bits) & ((0x1UL << exp_bits) - 1)).to_int() #| if biased_exp < exp_bias { #| return (u64 & sign_mask).reinterpret_as_double() #| } else if biased_exp >= exp_bias + frac_bits { #| return self #| } #| let mask_shift = biased_exp - exp_bias + exp_bits #| let trunc_mask = (sign_mask.reinterpret_as_int64() >> mask_shift).reinterpret_as_uint64() #| return (u64 & trunc_mask).reinterpret_as_double() #|} #|pub fn Double::ceil(self : Double) -> Double { #| let trunced = self.trunc() #| if self > trunced { #| return trunced + 1.0 #| } else { #| return trunced #| } #|} #|pub fn Double::floor(self : Double) -> Double { #| let trunced = self.trunc() #| if self < trunced { #| return trunced - 1.0 #| } else { #| return trunced #| } #|} #|pub fn Double::round(self : Double) -> Double { #| floor(self + 0.5) #|} ), "round_js.mbt": ( #|pub fn Double::trunc(self : Double) -> Double = "Math" "trunc" #|pub fn Double::ceil(self : Double) -> Double = "Math" "ceil" #|pub fn Double::floor(self : Double) -> Double = "Math" "floor" #|pub fn Double::round(self : Double) -> Double = "Math" "round" ), "round_wasm.mbt": ( #|pub fn Double::trunc(self : Double) -> Double = "(func (param $d f64) (result f64) (f64.trunc (local.get $d)))" #|pub fn Double::ceil(self : Double) -> Double = "(func (param $d f64) (result f64) (f64.ceil (local.get $d)))" #|pub fn Double::floor(self : Double) -> Double = "(func (param $d f64) (result f64) (f64.floor (local.get $d)))" #|pub fn Double::round(self : Double) -> Double { #| floor(self + 0.5) #|} ), "scalbn.mbt": ( #|fn scalbn(x : Double, exp : Int) -> Double { #| let mut n = exp #| let mut y : Double = x #| if n > 1023 { #| y *= 0x1.0p1023 #| n -= 1023 #| if n > 1023 { #| y *= 0x1.0p1023 #| n -= 1023 #| if n > 1023 { #| n = 1023 #| } #| } #| } else if n < -1022 { #| y *= 0x1.0p-1022 * 0x1.0p53 #| n += 1022 - 53 #| if n < -1022 { #| y *= 0x1.0p-1022 * 0x1.0p53 #| n += 1022 - 53 #| if n < -1022 { #| n = -1022 #| } #| } #| } #| let ui = (0x3ff + n).to_uint64() << 52 #| return y * ui.reinterpret_as_double() #|} ), "to_uint.mbt": ( #|pub fn to_uint(self : Double) -> UInt { #| if self != self { #| 0 #| } else if self >= 4294967295.0 { #| 4294967295U #| } else if self <= 0 { #| 0 #| } else { #| UInt::trunc_double(self) #| } #|} ), "to_uint_wasm.mbt": ( #|pub fn to_uint(self : Double) -> UInt = "%f64.to_u32_saturate" ), "trig_js.mbt": ( #|#deprecated("use `@math.sin` instead") #|#coverage.skip #|pub fn Double::sin(self : Double) -> Double = "Math" "sin" #|#deprecated("use `@math.cos` instead") #|#coverage.skip #|pub fn Double::cos(self : Double) -> Double = "Math" "cos" #|#deprecated("use `@math.tan` instead") #|#coverage.skip #|pub fn Double::tan(self : Double) -> Double = "Math" "tan" #|#deprecated("use `@math.asin` instead") #|#coverage.skip #|pub fn Double::asin(self : Double) -> Double = "Math" "asin" #|#deprecated("use `@math.acos` instead") #|#coverage.skip #|pub fn Double::acos(self : Double) -> Double = "Math" "acos" #|#deprecated("use `@math.atan` instead") #|#coverage.skip #|pub fn Double::atan(self : Double) -> Double = "Math" "atan" #|#deprecated("use `@math.atan2` instead") #|#coverage.skip #|pub fn Double::atan2(self : Double, x : Double) -> Double = "Math" "atan2" ), "trig_nonjs.mbt": ( #|let two_over_pi : FixedArray[Int] = [ #| 0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, 0x95993C, 0x439041, #| 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, 0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, #| 0xFE1DEB, 0x1CB129, 0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, #| 0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8, 0x97FFDE, 0x05980F, #| 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF, 0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, #| 0x7527BA, 0xC7EBE5, 0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, #| 0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, 0x91615E, 0xE61B08, #| 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, 0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, #| 0x60E27B, 0xC08C6B, #|] #|let pi_over_2 : FixedArray[Double] = [ #| 1.57079625129699707031e+00, // 0x3FF921FB, 0x40000000 */ #| 7.54978941586159635335e-08, // 0x3E74442D, 0x00000000 */ #| 5.39030252995776476554e-15, // 0x3CF84698, 0x80000000 */ #| 3.28200341580791294123e-22, // 0x3B78CC51, 0x60000000 */ #| 1.27065575308067607349e-29, // 0x39F01B83, 0x80000000 */ #| 1.22933308981111328932e-36, // 0x387A2520, 0x40000000 */ #| 2.73370053816464559624e-44, // 0x36E38222, 0x80000000 */ #| 2.16741683877804819444e-51, // 0x3569F31D, 0x00000000 */ #|] #|let npio2_hw : FixedArray[Int] = [ #| 0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C, 0x4025FDBB, #| 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C, 0x40346B9C, 0x4035FDBB, #| 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A, 0x403DD85A, 0x403F6A7A, 0x40407E4C, #| 0x4041475C, 0x4042106C, 0x4042D97C, 0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, #| 0x4046C6CB, 0x40478FDB, 0x404858EB, 0x404921FB, #|] #|const PI_OVER_4 : Double = 0.785398163397448309616 #|const PIO2_1 : Double = 1.5707963267341256e+00 // 0x3FF921FB, 0x54400000 */ #|const PIO2_1T : Double = 6.0771005065061922e-11 // 0x3DD0B461, 0x1A600000 */ #|const PIO2_2 : Double = 6.0771005063039660e-11 // 0x3DD0B461, 0x1A600000 */ #|const PIO2_2T : Double = 2.0222662487959506e-21 // 0x3BA3198A, 0x2E037073 */ #|const PIO2_3 : Double = 2.0222662487111665e-21 // 0x3BA3198A, 0x2E037073 */ #|const PIO2_3T : Double = 8.4784276603688996e-32 // 0x397B839A, 0x252049C1 */ #|const INV_PIO2 : Double = 6.3661977236758138e-01 // 0x3FE45F30, 0x6DC9C883 */ #|const HALF : Double = 0.5 #|const TWO24 : Double = 16777216.0 // 0x41700000, 0x00000000 */ #|fn set_low_word(d : Double, v : UInt) -> Double { #| let bits : UInt64 = d.reinterpret_as_uint64() #| let bits = bits & 0xFFFF_FFFF_0000_0000 #| let bits = bits | v.to_uint64() #| bits.reinterpret_as_double() #|} #|fn set_high_word(d : Double, v : UInt) -> Double { #| let bits : UInt64 = d.reinterpret_as_uint64() #| let bits = bits & 0x0000_0000_FFFF_FFFF #| let bits = bits | (v.to_uint64() << 32) #| bits.reinterpret_as_double() #|} #|fn get_high_word(x : Double) -> UInt { #| (x.reinterpret_as_uint64() >> 32).to_uint() #|} #|fn get_low_word(x : Double) -> UInt { #| x.reinterpret_as_uint64().to_uint() #|} #|fn rem_pio2(x : Double, y : Array[Double]) -> Int { #| let hx = get_high_word(x).reinterpret_as_int() #| let ix : Int = hx & 0x7fffffff #| let mut z = 0.0 #| if ix <= 0x3fe921fb { #| y[0] = x #| y[1] = 0.0 #| return 0 #| } #| if ix < 0x4002d97c { #| if hx > 0 { #| z = x - PIO2_1 #| if ix != 0x3ff921fb { #| y[0] = z - PIO2_1T #| y[1] = z - y[0] - PIO2_1T #| } else { #| z = z - PIO2_2 #| y[0] = z - PIO2_2T #| y[1] = z - y[0] - PIO2_2T #| } #| return 1 #| } else { #| z = x + PIO2_1 #| if ix != 0x3ff921fb { #| y[0] = z + PIO2_1T #| y[1] = z - y[0] + PIO2_1T #| } else { #| let z = z + PIO2_2 #| y[0] = z + PIO2_2T #| y[1] = z - y[0] + PIO2_2T #| } #| return -1 #| } #| } #| if ix <= 0x413921fb { #| let t = x.abs() #| let n = (t * INV_PIO2 + HALF).to_int() #| let fn_ = n.to_double() #| let mut r = t - fn_ * PIO2_1 #| let mut w = fn_ * PIO2_1T #| if n < 32 && ix != npio2_hw[n - 1] { #| y[0] = r - w #| } else { #| let j = ix >> 20 #| y[0] = r - w #| let i = j - ((get_high_word(y[0]) >> 20).reinterpret_as_int() & 0x7ff) #| if i > 16 { #| let t = r #| w = fn_ * PIO2_2 #| r = t - w #| w = fn_ * PIO2_2T - (t - r - w) #| y[0] = r - w #| let i = j - ((get_high_word(y[0]) >> 20).reinterpret_as_int() & 0x7ff) #| if i > 49 { #| let t = r #| w = fn_ * PIO2_3 #| r = t - w #| w = fn_ * PIO2_3T - (t - r - w) #| y[0] = r - w #| } #| } #| } #| y[1] = r - y[0] - w #| if hx > 0 { #| return n #| } else { #| y[0] = -y[0] #| y[1] = -y[1] #| return -n #| } #| } #| if ix >= 0x7ff00000 { #| y[0] = x - x #| y[1] = y[0] #| return 0 #| } #| z = set_low_word(z, get_low_word(x)) #| let e0 = (ix >> 20) - 1046 // e0 = ilogb(z) - 23 #| z = set_high_word(z, (ix - (e0 << 20)).reinterpret_as_uint()) #| let tx = [0.0, 0.0, 0.0] #| for i in 0..<2 { #| tx[i] = z.to_int().to_double() #| z = (z - tx[i]) * TWO24 #| } #| tx[2] = z #| let mut nx = 3 #| while tx[nx - 1] == 0.0 { #| nx -= 1 #| } #| let n = __kernel_rem_pio2(tx, y, e0, nx, 2) #| if hx > 0 { #| n #| } else { #| y[0] = -y[0] #| y[1] = -y[1] #| -n #| } #|} #|fn __kernel_rem_pio2( #| x : Array[Double], #| y : Array[Double], #| e0 : Int, #| nx : Int, #| prec : Int, #|) -> Int { #| let init_jk = [2, 3, 4, 6] #| let two24 : Double = 16777216.0 // 0x41700000, 0x00000000 #| let twon24 : Double = 5.96046447753906250000e-08 // 0x3E700000, 0x00000000 #| let mut jz : Int = 0 #| let mut jx : Int = 0 #| let mut jv : Int = 0 #| let mut jp : Int = 0 #| let mut jk : Int = 0 #| let mut carry : Int = 0 #| let mut n : Int = 0 #| let iq : Array[Int] = Array::make(20, 0) #| let mut i : Int = 0 #| let mut j : Int = 0 #| let mut k : Int = 0 #| let mut m : Int = 0 #| let mut q0 : Int = 0 #| let mut ih : Int = 0 #| let mut z : Double = 0 #| let mut fw : Double = 0 #| let f : Array[Double] = Array::make(20, 0.0) #| let fq : Array[Double] = Array::make(20, 0.0) #| let q : Array[Double] = Array::make(20, 0.0) #| jk = init_jk[prec] #| jp = jk #| jx = nx - 1 #| jv = (e0 - 3) / 24 #| if jv < 0 { #| jv = 0 #| } #| q0 = e0 - 24 * (jv + 1) #| j = jv - jx #| m = jx + jk #| i = 0 #| while i <= m { #| f[i] = if j < 0 { 0.0 } else { two_over_pi[j].to_double() } #| i += 1 #| j += 1 #| } #| i = 0 #| while i <= jk { #| j = 0 #| fw = 0.0 #| while j <= jx { #| fw += x[j] * f[jx + i - j] #| j += 1 #| } #| q[i] = fw #| i += 1 #| } #| jz = jk #| let mut recompute = true #| while recompute { #| recompute = false #| i = 0 #| j = jz #| z = q[jz] #| while j > 0 { #| fw = (twon24 * z).floor() #| iq[i] = (z - two24 * fw).to_int() #| z = q[j - 1] + fw #| i += 1 #| j -= 1 #| } #| z = scalbn(z, q0) // actual value of z #| z -= 8.0 * (z * 0.125).floor() // trim off integer >= 8 #| n = z.to_int() #| z -= n.to_double() #| ih = 0 #| if q0 > 0 { #| i = iq[jz - 1] >> (24 - q0) #| n += i #| iq[jz - 1] -= i << (24 - q0) #| ih = iq[jz - 1] >> (23 - q0) #| } else if q0 == 0 { #| ih = iq[jz - 1] >> 23 #| } else if z >= 0.5 { #| ih = 2 #| } #| if ih > 0 { #| n += 1 #| carry = 0 #| i = 0 #| while i < jz { #| j = iq[i] #| if carry == 0 { #| if j != 0 { #| carry = 1 #| iq[i] = 0x1000000 - j #| } #| } else { #| iq[i] = 0xffffff - j #| } #| i += 1 #| } #| if q0 > 0 { #| match q0 { #| 1 => iq[jz - 1] = iq[jz - 1] & 0x7fffff #| 2 => iq[jz - 1] = iq[jz - 1] & 0x3fffff #| _ => () #| } #| } #| if ih == 2 { #| z = 1.0 - z #| if carry != 0 { #| z -= scalbn(1.0, q0) #| } #| } #| } #| if z == 0.0 { #| j = 0 #| i = jz - 1 #| while i >= jk { #| j = j | iq[i] #| i -= 1 #| } #| if j == 0 { #| k = 1 #| while iq[jk - k] == 0 { #| k += 1 #| } #| i = jz + 1 #| while i <= jz + k { #| f[jx + i] = two_over_pi[jv + i].to_double() #| j = 0 #| fw = 0.0 #| while j <= jx { #| fw += x[j] * f[jx + i - j] #| j += 1 #| } #| q[i] = fw #| i += 1 #| } #| jz += k #| recompute = true // Continue to recompute #| continue #| } #| } // Skip the rest of the loop and recompute #| if z == 0.0 { #| jz -= 1 #| q0 -= 24 #| while iq[jz] == 0 { #| jz -= 1 #| q0 -= 24 #| } #| } else { #| z = scalbn(z, -q0) #| if z >= two24 { #| fw = (twon24 * z).floor() #| iq[jz] = (z - two24 * fw).to_int() #| jz += 1 #| q0 += 24 #| iq[jz] = fw.to_int() #| } else { #| iq[jz] = z.to_int() #| } #| } #| fw = scalbn(1.0, q0) #| i = jz #| while i >= 0 { #| q[i] = fw * iq[i].to_double() #| fw *= twon24 #| i -= 1 #| } #| i = jz #| while i >= 0 { #| fw = 0.0 #| k = 0 #| while k <= jp && k <= jz - i { #| fw += pi_over_2[k] * q[i + k] #| k += 1 #| } #| fq[jz - i] = fw #| i -= 1 #| } #| match prec { #| 0 => { #| fw = 0.0 #| i = jz #| while i >= 0 { #| fw += fq[i] #| i -= 1 #| } #| y[0] = if ih == 0 { fw } else { -fw } #| } #| 1 | 2 => { #| fw = 0.0 #| i = jz #| while i >= 0 { #| fw += fq[i] #| i -= 1 #| } #| y[0] = if ih == 0 { fw } else { -fw } #| fw = fq[0] - fw #| i = 1 #| while i <= jz { #| fw += fq[i] #| i += 1 #| } #| y[1] = if ih == 0 { fw } else { -fw } #| } #| 3 => { #| i = jz #| while i > 0 { #| fw = fq[i - 1] + fq[i] #| fq[i] += fq[i - 1] - fw #| fq[i - 1] = fw #| i -= 1 #| } #| i = jz #| while i > 1 { #| fw = fq[i - 1] + fq[i] #| fq[i] += fq[i - 1] - fw #| fq[i - 1] = fw #| i -= 1 #| } #| fw = 0.0 #| i = jz #| while i >= 2 { #| fw += fq[i] #| i -= 1 #| } #| if ih == 0 { #| y[0] = fq[0] #| y[1] = fq[1] #| y[2] = fw #| } else { #| y[0] = -fq[0] #| y[1] = -fq[1] #| y[2] = -fw #| } #| } #| _ => () #| } #| } #| n & 7 #|} #|fn __kernel_sin(x : Double, y : Double, iy : Int) -> Double { #| let s1 = -1.66666666666666324348e-01 #| let s2 = 8.33333333332248946124e-03 #| let s3 = -1.98412698298579493134e-04 #| let s4 = 2.75573137070700676789e-06 #| let s5 = -2.50507602534068634195e-08 #| let s6 = 1.58969099521155010221e-10 #| let mut z = 0.0 #| let mut r = 0.0 #| let mut v = 0.0 #| let ix = get_high_word(x) & 0x7fffffff #| if ix < 0x3e400000 { #| if x.to_int() == 0 { #| return x #| } #| } #| z = x * x #| v = z * x #| r = s2 + z * (s3 + z * (s4 + z * (s5 + z * s6))) #| if iy == 0 { #| x + v * (s1 + z * r) #| } else { #| x - (z * (0.5 * y - v * r) - y - v * s1) #| } #|} #|fn __kernel_cos(x : Double, y : Double) -> Double { #| let one = 1.00000000000000000000e+00 #| let c1 = 4.16666666666666019037e-02 #| let c2 = -1.38888888888741095749e-03 #| let c3 = 2.48015872894767294178e-05 #| let c4 = -2.75573143513906633035e-07 #| let c5 = 2.08757232129817482790e-09 #| let c6 = -1.13596475577881948265e-11 #| let mut a = 0.0 #| let mut hz = 0.0 #| let mut z = 0.0 #| let mut r = 0.0 #| let mut qx = 0.0 #| let ix = get_high_word(x) & 0x7fffffff #| if ix < 0x3e400000 { #| if x.to_int() == 0 { #| return one #| } #| } #| z = x * x #| r = z * (c1 + z * (c2 + z * (c3 + z * (c4 + z * (c5 + z * c6))))) #| if ix < 0x3fd33333 { #| return one - (0.5 * z - (z * r - x * y)) #| } else { #| if ix > 0x3fe90000 { #| qx = 0.28125 #| } else { #| qx = ((ix - 0x00200000).to_uint64() << 32).reinterpret_as_double() #| } #| hz = 0.5 * z - qx #| a = one - qx #| return a - (hz - (z * r - x * y)) #| } #|} #|fn __kernal_tan(x : Double, y : Double, iy : Int) -> Double { #| let one = 1.0 #| let pio4 = 7.85398163397448278999e-01 #| let pio4lo = 3.06161699786838301793e-17 #| let mut x = x #| let mut y = y #| let mut z = 0.0 #| let mut r = 0.0 #| let mut v = 0.0 #| let mut w = 0.0 #| let mut s = 0.0 #| let t = [ #| 3.33333333333334091986e-01, // 3FD55555, 55555563 */ #| 1.33333333333201242699e-01, // 3FC11111, 1110FE7A */ #| 5.39682539762260521377e-02, // 3FABA1BA, 1BB341FE */ #| 2.18694882948595424599e-02, // 3F9664F4, 8406D637 */ #| 8.86323982359930005737e-03, // 3F8226E3, E96E8493 */ #| 3.59207910759131235356e-03, // 3F6D6D22, C9560328 */ #| 1.45620945432529025516e-03, // 3F57DBC8, FEE08315 */ #| 5.88041240820264096874e-04, // 3F4344D8, F2F26501 */ #| 2.46463134818469906812e-04, // 3F3026F7, 1A8D1068 */ #| 7.81794442939557092300e-05, // 3F147E88, A03792A6 */ #| 7.14072491382608190305e-05, // 3F12B80F, 32F0A7E9 */ #| -1.85586374855275456654e-05, // BEF375CB, DB605373 */ #| 2.59073051863633712884e-05, // 3EFB2A70, 74BF7AD4 */ #| 1.00000000000000000000e+00, // 3FF00000, 00000000 (one) */ #| 7.85398163397448278999e-01, // 3FE921FB, 54442D18 (pio4) */ #| 3.06161699786838301793e-17, // 3C81A626, 33145C07 (pio4lo) */ #| ] #| let hx = get_high_word(x).reinterpret_as_int() #| let ix = hx & 0x7fffffff #| if ix < 0x3e300000 { #| if x.to_int() == 0 { #| if (ix | get_low_word(x).reinterpret_as_int() | (iy + 1)) == 0 { #| return one / x.abs() #| } else if iy == 1 { #| return x #| } else { #| w = x + y #| z = w #| z = set_low_word(z, 0) #| v = y - (z - x) #| let a = -one / w #| let mut t = a #| t = set_low_word(t, 0) #| s = one + t * z #| return t + a * (s + t * v) #| } #| } #| } #| if ix >= 0x3fe59428 { #| if hx < 0 { #| x = -x #| y = -y #| } #| z = pio4 - x #| w = pio4lo - y #| x = z + w #| y = 0.0 #| } #| z = x * x #| w = z * z #| r = t[1] + w * (t[3] + w * (t[5] + w * (t[7] + w * (t[9] + w * t[11])))) #| v = z * #| (t[2] + w * (t[4] + w * (t[6] + w * (t[8] + w * (t[10] + w * t[12]))))) #| s = z * x #| r = y + z * (s * (r + v) + y) #| r += t[0] * s #| w = x + r #| if ix >= 0x3fe59428 { #| v = iy.to_double() #| return (1 - ((hx >> 30) & 2)).to_double() * #| (v - 2.0 * (x - (w * w / (w + v) - r))) #| } #| if iy == 1 { #| w #| } else { #| z = w #| z = set_low_word(z, 0) #| v = r - (z - x) #| let a = -1.0 / w #| let mut t = a #| t = set_low_word(t, 0) #| s = 1.0 + t * z #| t + a * (s + t * v) #| } #|} #|#deprecated("use `@math.sin` instead") #|#coverage.skip #|pub fn Double::sin(self : Double) -> Double { #| if self.is_inf() || self.is_nan() { #| return not_a_number #| } #| let y = [0.0, 0.0] #| let z = 0.0 #| if self.abs() <= PI_OVER_4 { #| return __kernel_sin(self, z, 0) #| } else { #| let n = rem_pio2(self, y) #| match n & 3 { #| 0 => __kernel_sin(y[0], y[1], 1) #| 1 => __kernel_cos(y[0], y[1]) #| 2 => -__kernel_sin(y[0], y[1], 1) #| _ => -__kernel_cos(y[0], y[1]) #| } #| } #|} #|#deprecated("use `@math.cos` instead") #|#coverage.skip #|pub fn Double::cos(self : Double) -> Double { #| if self.is_inf() || self.is_nan() { #| return not_a_number #| } #| let y = [0.0, 0.0] #| let z = 0.0 #| if self.abs() <= PI_OVER_4 { #| return __kernel_cos(self, z) #| } else { #| let n = rem_pio2(self, y) #| match n & 3 { #| 0 => __kernel_cos(y[0], y[1]) #| 1 => -__kernel_sin(y[0], y[1], 1) #| 2 => -__kernel_cos(y[0], y[1]) #| _ => __kernel_sin(y[0], y[1], 1) #| } #| } #|} #|#deprecated("use `@math.tan` instead") #|#coverage.skip #|pub fn Double::tan(self : Double) -> Double { #| if self.is_inf() || self.is_nan() { #| return not_a_number #| } #| let y = Array::make(2, 0.0) #| let z = 0.0 #| if self.abs() <= PI_OVER_4 { #| __kernal_tan(self, z, 1) #| } else { #| let n = rem_pio2(self, y) #| __kernal_tan(y[0], y[1], 1 - ((n & 1) << 1)) #| } #|} #|#deprecated("use `@math.asin` instead") #|#coverage.skip #|pub fn Double::asin(self : Double) -> Double { #| let huge = 1.0e+300 #| let pio4_hi = 7.85398163397448278999e-01 #| let pio2_hi = 1.57079632679489655800 #| let pio2_lo = 6.12323399573676603587e-17 #| let ps0 = 1.66666666666666657415e-01 #| let ps1 = -3.25565818622400915405e-01 #| let ps2 = 2.01212532134862925881e-01 #| let ps3 = -4.00555345006794114027e-02 #| let ps4 = 7.91534994289814532176e-04 #| let ps5 = 3.47933107596021167570e-05 #| let qs1 = -2.40339491173441421878e+00 #| let qs2 = 2.02094576023350569471e+00 #| let qs3 = -6.88283971605453293030e-01 #| let qs4 = 7.70381505559019352791e-02 #| let ix = get_high_word(self).reinterpret_as_int() & 0x7fffffff #| let absx = self.abs() #| if absx >= 1.0 { #| if absx == 1.0 { #| return self * pio2_hi + self * pio2_lo #| } else { #| return not_a_number #| } #| } else if absx < 0.5 { #| if ix < 0x3e400000 { #| if huge + self > 1.0 { #| return self #| } #| } else { #| let t = self * self #| let p = t * #| (ps0 + t * (ps1 + t * (ps2 + t * (ps3 + t * (ps4 + t * ps5))))) #| let q = 1.0 + t * (qs1 + t * (qs2 + t * (qs3 + t * qs4))) #| let w = p / q #| return self + self * w #| } #| } #| let w = 1.0 - absx #| let t = w * 0.5 #| let p = t * (ps0 + t * (ps1 + t * (ps2 + t * (ps3 + t * (ps4 + t * ps5))))) #| let q = 1.0 + t * (qs1 + t * (qs2 + t * (qs3 + t * qs4))) #| let s = t.sqrt() #| if ix >= 0x3FEF3333 { #| let w = p / q #| let t = pio2_hi - (2.0 * (s + s * w) - pio2_lo) #| return if self > 0.0 { t } else { -t } #| } else { #| let mut w = s #| w = set_low_word(w, 0) #| let c = (t - w * w) / (s + w) #| let r = p / q #| let p = 2.0 * s * r - (pio2_lo - 2.0 * c) #| let q = pio4_hi - 2.0 * w #| let t = pio4_hi - (p - q) #| return if self > 0.0 { t } else { -t } #| } #|} #|#deprecated("use `@math.acos` instead") #|#coverage.skip #|pub fn Double::acos(self : Double) -> Double { #| let one : Double = 1.0 #| let pi : Double = 3.14159265358979311600 #| let pio2_hi : Double = 1.57079632679489655800 #| let pio2_lo : Double = 6.12323399573676603587e-17 #| let ps0 : Double = 1.66666666666666657415e-01 #| let ps1 : Double = -3.25565818622400915405e-01 #| let ps2 : Double = 2.01212532134862925881e-01 #| let ps3 : Double = -4.00555345006794114027e-02 #| let ps4 : Double = 7.91534994289814532176e-04 #| let ps5 : Double = 3.47933107596021167570e-05 #| let qs1 : Double = -2.40339491173441421878e+00 #| let qs2 : Double = 2.02094576023350569471e+00 #| let qs3 : Double = -6.88283971605453293030e-01 #| let qs4 : Double = 7.70381505559019352791e-02 #| let ix = get_high_word(self).reinterpret_as_int() & 0x7fffffff #| let absx = self.abs() #| if absx >= 1.0 { #| if absx == 1.0 { #| if self > 0 { #| return 0.0 #| } else { #| return pi + 2.0 * pio2_lo #| } #| } #| return not_a_number #| } #| if absx < 0.5 { #| if ix <= 0x3c600000 { #| return pio2_hi + pio2_lo #| } #| let z = self * self #| let p = z * (ps0 + z * (ps1 + z * (ps2 + z * (ps3 + z * (ps4 + z * ps5))))) #| let q = one + z * (qs1 + z * (qs2 + z * (qs3 + z * qs4))) #| let r = p / q #| pio2_hi - (self - (pio2_lo - self * r)) #| } else if self < 0 { #| let z = (one + self) * 0.5 #| let p = z * (ps0 + z * (ps1 + z * (ps2 + z * (ps3 + z * (ps4 + z * ps5))))) #| let q = one + z * (qs1 + z * (qs2 + z * (qs3 + z * qs4))) #| let s = z.sqrt() #| let r = p / q #| let w = r * s - pio2_lo #| pi - 2.0 * (s + w) #| } else { #| let z = (one - self) * 0.5 #| let s = z.sqrt() #| let df = s #| let c = (z - df * df) / (s + df) #| let p = z * (ps0 + z * (ps1 + z * (ps2 + z * (ps3 + z * (ps4 + z * ps5))))) #| let q = one + z * (qs1 + z * (qs2 + z * (qs3 + z * qs4))) #| let r = p / q #| let w = r * s + c #| 2.0 * (df + w) #| } #|} #|#deprecated("use `@math.atan` instead") #|#coverage.skip #|pub fn Double::atan(self : Double) -> Double { #| if self.is_nan() || self == 0.0 { #| return self #| } #| let atan_hi = [ #| 4.63647609000806093515e-01, 7.85398163397448278999e-01, 9.82793723247329054082e-01, #| 1.57079632679489655800e+00, #| ] #| let atan_lo = [ #| 2.26987774529616870924e-17, 3.06161699786838301793e-17, 1.39033110312309984516e-17, #| 6.12323399573676603587e-17, #| ] #| let a_t = [ #| 3.33333333333329318027e-01, -1.99999999998764832476e-01, 1.42857142725034663711e-01, #| -1.11111104054623557880e-01, 9.09088713343650656196e-02, -7.69187620504482999495e-02, #| 6.66107313738753120669e-02, -5.83357013379057348645e-02, 4.97687799461593236017e-02, #| -3.65315727442169155270e-02, 1.62858201153657823623e-02, #| ] #| let one = 1.0 #| let huge = 1.0e300 #| let ix = get_high_word(self).reinterpret_as_int() & 0x7fffffff #| let mut id = 0 #| let mut z = 0.0 #| let mut w = 0.0 #| let mut self = self #| let x_is_neg = self < 0.0 #| if ix >= 0x44100000 { #| if self > 0 { #| return atan_hi[3] + atan_lo[3] #| } else { #| return -atan_hi[3] - atan_lo[3] #| } #| } #| if ix < 0x3fdc0000 { #| if ix < 0x3e200000 { #| if huge + self > one { #| return self #| } #| } #| id = -1 #| } else { #| self = self.abs() #| if ix < 0x3ff30000 { #| if ix < 0x3fe60000 { #| id = 0 #| self = (2.0 * self - one) / (2.0 + self) #| } else { #| id = 1 #| self = (self - one) / (self + one) #| } #| } else if ix < 0x40038000 { #| id = 2 #| self = (self - 1.5) / (one + 1.5 * self) #| } else { #| id = 3 #| self = -1.0 / self #| } #| } #| z = self * self #| w = z * z #| let s1 = z * #| ( #| a_t[0] + #| w * (a_t[2] + w * (a_t[4] + w * (a_t[6] + w * (a_t[8] + w * a_t[10])))) #| ) #| let s2 = w * #| (a_t[1] + w * (a_t[3] + w * (a_t[5] + w * (a_t[7] + w * a_t[9])))) #| if id < 0 { #| self - self * (s1 + s2) #| } else { #| z = atan_hi[id] - (self * (s1 + s2) - atan_lo[id] - self) #| if x_is_neg { #| -z #| } else { #| z #| } #| } #|} #|#deprecated("use `@math.atan2` instead") #|#coverage.skip #|pub fn Double::atan2(self : Double, x : Double) -> Double { #| if x.is_nan() || self.is_nan() { #| return not_a_number #| } #| let tiny = 1.0e-300 #| let zero = 0.0 #| let pi_o_4 = 7.8539816339744827900E-01 #| let pi_o_2 = 1.5707963267948965580E+00 #| let pi = 3.1415926535897931160E+00 #| let pi_lo = 1.2246467991473531772E-16 #| let hx = get_high_word(x).reinterpret_as_int() #| let hy = get_high_word(self).reinterpret_as_int() #| let ix = hx & 0x7fffffff #| let iy = hy & 0x7fffffff #| if x == 1.0 { #| return self.atan() #| } #| let m = ((hy >> 31) & 1) | ((hx >> 30) & 2) #| if self == 0 { #| match m { #| 0 | 1 => return self #| 2 => return pi + tiny #| _ => return -pi - tiny #| } #| } #| if x == 0 { #| return if hy < 0 { -pi_o_2 - tiny } else { pi_o_2 + tiny } #| } #| if x.is_inf() { #| if self.is_inf() { #| match m { #| 0 => return pi_o_4 + tiny #| 1 => return -pi_o_4 - tiny #| 2 => return 3.0 * pi_o_4 + tiny #| _ => return -3.0 * pi_o_4 - tiny #| } #| } else { #| match m { #| 0 => return zero #| 1 => return -zero #| 2 => return pi + tiny #| _ => return -pi - tiny #| } #| } #| } #| if self.is_inf() { #| return if hy < 0 { -pi_o_2 - tiny } else { pi_o_2 + tiny } #| } #| let k = (iy - ix) >> 20 #| let z = if k > 60 { #| pi_o_2 + 0.5 * pi_lo #| } else if hx < 0 && k < -60 { #| 0.0 #| } else { #| (self / x).abs().atan() #| } #| match m { #| 0 => z #| 1 => -z #| 2 => pi - (z - pi_lo) #| _ => z - pi_lo - pi #| } #|} ), }, ) ///| let moonbitlang_core_double_internal_ryu_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/double/internal/ryu", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/bool": moonbitlang_core_bool_module, }, files={ "moon.pkg.json": ( #|{ #| "import": ["moonbitlang/core/builtin", "moonbitlang/core/bool"] #|} ), "common.mbt": ( #|fn pow5bits(e : Int) -> Int { #| ((e * 1217359).reinterpret_as_uint() >> 19).reinterpret_as_int() + 1 #|} #|fn copy_special_str(sign : Bool, exponent : Bool, mantissa : Bool) -> String { #| if mantissa { #| return "NaN" #| } #| let s = if sign { "-" } else { "" } #| if exponent { #| return s + "Infinity" #| } #| return s + "0.0" #|} #|fn log10Pow5(e : Int) -> Int { #| ((e * 732923).reinterpret_as_uint() >> 20).reinterpret_as_int() #|} #|fn log10Pow2(e : Int) -> Int { #| ((e * 78913).reinterpret_as_uint() >> 18).reinterpret_as_int() #|} ), "ryu.mbt": ( #|fn string_from_bytes(bytes : FixedArray[Byte], from : Int, to : Int) -> String { #| let buf = StringBuilder::new(size_hint=bytes.length()) #| for i in from.. (UInt64, UInt64) { #| let aLo = a & 0xffffffff #| let aHi = a >> 32 #| let bLo = b & 0xffffffff #| let bHi = b >> 32 #| let x = aLo * bLo #| let y = aHi * bLo + (x >> 32) #| let z = aLo * bHi + (y & 0xffffffff) #| let w = aHi * bHi + (y >> 32) + (z >> 32) #| let lo = a * b #| let hi = w #| (lo, hi) #|} #|fn shiftright128(lo : UInt64, hi : UInt64, dist : Int) -> UInt64 { #| (hi << (64 - dist)) | (lo >> dist) #|} #|fn pow5Factor(value : UInt64) -> Int { #| if value % 5UL != 0UL { #| return 0 #| } #| if value % 25UL != 0UL { #| return 1 #| } #| if value % 125UL != 0UL { #| return 2 #| } #| if value % 625UL != 0UL { #| return 3 #| } #| let mut count = 4 #| let mut value = value / 625UL #| while value > 0UL { #| if value % 5UL != 0UL { #| return count #| } #| value = value / 5UL #| count = count + 1 #| } #| abort("IllegalArgumentException \{value}") #|} #|fn multipleOfPowerOf5(value : UInt64, p : Int) -> Bool { #| pow5Factor(value) >= p #|} #|fn multipleOfPowerOf2(value : UInt64, p : Int) -> Bool { #| (value & ((1UL << p) - 1UL)) == 0UL #|} #|fn mulShiftAll64( #| m : UInt64, #| mul : (UInt64, UInt64), #| j : Int, #| mmShift : Bool, #|) -> (UInt64, UInt64, UInt64) { #| let m = m << 1 #| let (lo, tmp) = umul128(m, mul.0) #| let (lo2, hi2) = umul128(m, mul.1) #| let mid = tmp + lo2 #| let hi = hi2 + (if mid < tmp { 1 } else { 0 }) #| let lo2 = lo + mul.0 #| let mid2 = mid + mul.1 + (if lo2 < lo { 1 } else { 0 }) #| let hi2 = hi + (if mid2 < mid { 1 } else { 0 }) #| let vp = shiftright128(mid2, hi2, j - 64 - 1) #| let mut vm : UInt64 = 0UL #| if mmShift { #| let lo3 = lo - mul.0 #| let mid3 = mid - mul.1 - (if lo < lo3 { 1 } else { 0 }) #| let hi3 = hi - (if mid < mid3 { 1 } else { 0 }) #| vm = shiftright128(mid3, hi3, j - 64 - 1) #| } else { #| let lo3 : UInt64 = lo + lo #| let mid3 : UInt64 = mid + mid + (if lo3 < lo { 1 } else { 0 }) #| let hi3 : UInt64 = hi + hi + (if mid3 < mid { 1 } else { 0 }) #| let lo4 : UInt64 = lo3 - mul.0 #| let mid4 : UInt64 = mid3 - mul.1 - (if lo3 < lo4 { 1 } else { 0 }) #| let hi4 : UInt64 = hi3 - (if mid3 < mid4 { 1 } else { 0 }) #| vm = shiftright128(mid4, hi4, j - 64) #| } #| let vr = shiftright128(mid, hi, j - 64 - 1) #| (vr, vp, vm) #|} #|let gPOW5_TABLE_SIZE = 26 #|let gDOUBLE_POW5_INV_SPLIT2 : FixedArray[UInt64] = [ #| 1, 2305843009213693952, 5955668970331000884, 1784059615882449851, 8982663654677661702, #| 1380349269358112757, 7286864317269821294, 2135987035920910082, 7005857020398200553, #| 1652639921975621497, 17965325103354776697, 1278668206209430417, 8928596168509315048, #| 1978643211784836272, 10075671573058298858, 1530901034580419511, 597001226353042382, #| 1184477304306571148, 1527430471115325346, 1832889850782397517, 12533209867169019542, #| 1418129833677084982, 5577825024675947042, 2194449627517475473, 11006974540203867551, #| 1697873161311732311, 10313493231639821582, 1313665730009899186, 12701016819766672773, #| 2032799256770390445, #|] #|let gPOW5_INV_OFFSETS : FixedArray[UInt] = [ #| 0x54544554, 0x04055545, 0x10041000, 0x00400414, 0x40010000, 0x41155555, 0x00000454, #| 0x00010044, 0x40000000, 0x44000041, 0x50454450, 0x55550054, 0x51655554, 0x40004000, #| 0x01000001, 0x00010500, 0x51515411, 0x05555554, 0x00000000, #|] #|let gDOUBLE_POW5_SPLIT2 : FixedArray[UInt64] = [ #| 0, 1152921504606846976, 0, 1490116119384765625, 1032610780636961552, 1925929944387235853, #| 7910200175544436838, 1244603055572228341, 16941905809032713930, 1608611746708759036, #| 13024893955298202172, 2079081953128979843, 6607496772837067824, 1343575221513417750, #| 17332926989895652603, 1736530273035216783, 13037379183483547984, 2244412773384604712, #| 1605989338741628675, 1450417759929778918, 9630225068416591280, 1874621017369538693, #| 665883850346957067, 1211445438634777304, 14931890668723713708, 1565756531257009982, #|] #|let gPOW5_OFFSETS : FixedArray[UInt] = [ #| 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40000000, 0x59695995, 0x55545555, #| 0x56555515, 0x41150504, 0x40555410, 0x44555145, 0x44504540, 0x45555550, 0x40004000, #| 0x96440440, 0x55565565, 0x54454045, 0x40154151, 0x55559155, 0x51405555, 0x00000105, #|] #|let gDOUBLE_POW5_TABLE : FixedArray[UInt64] = [ #| 1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625, 48828125, 244140625, #| 1220703125, 6103515625, 30517578125, 152587890625, 762939453125, 3814697265625, #| 19073486328125, 95367431640625, 476837158203125, 2384185791015625, 11920928955078125, #| 59604644775390625, 298023223876953125, #|] #|fn double_computePow5(i : Int) -> (UInt64, UInt64) { #| let base = i / gPOW5_TABLE_SIZE #| let base2 = base * gPOW5_TABLE_SIZE #| let offset = i - base2 #| let mul0 = gDOUBLE_POW5_SPLIT2[base * 2] #| let mul1 = gDOUBLE_POW5_SPLIT2[base * 2 + 1] #| if offset == 0 { #| return (mul0, mul1) #| } #| let m : UInt64 = gDOUBLE_POW5_TABLE[offset] #| let (low1, high1) = umul128(m, mul1) #| let (low0, high0) = umul128(m, mul0) #| let sum : UInt64 = high0 + low1 #| let mut high1 = high1 #| if sum < high0 { #| high1 = high1 + 1UL #| } #| let delta : Int = pow5bits(i) - pow5bits(base2) #| let a = shiftright128(low0, sum, delta) + #| ((gPOW5_OFFSETS[i / 16] >> ((i % 16) << 1)) & 3).to_uint64() #| let b = shiftright128(sum, high1, delta) #| (a, b) #|} #|fn double_computeInvPow5(i : Int) -> (UInt64, UInt64) { #| let base = (i + gPOW5_TABLE_SIZE - 1) / gPOW5_TABLE_SIZE #| let base2 = base * gPOW5_TABLE_SIZE #| let offset = base2 - i #| let mul0 = gDOUBLE_POW5_INV_SPLIT2[base * 2] #| let mul1 = gDOUBLE_POW5_INV_SPLIT2[base * 2 + 1] #| if offset == 0 { #| return (mul0, mul1) #| } #| let m = gDOUBLE_POW5_TABLE[offset] #| let (low1, high1) = umul128(m, mul1) #| let (low0, high0) = umul128(m, mul0) #| let sum = high0 + low1 #| let mut high1 = high1 #| if sum < high0 { #| high1 = high1 + 1 #| } #| let delta : Int = pow5bits(base2) - pow5bits(i) #| let a = shiftright128(low0, sum, delta) + #| 1 + #| ((gPOW5_INV_OFFSETS[i / 16] >> ((i % 16) << 1)) & 3).to_uint64() #| let b = shiftright128(sum, high1, delta) #| (a, b) #|} #|let gDOUBLE_MANTISSA_BITS : Int = 52 #|let gDOUBLE_EXPONENT_BITS : Int = 11 #|let gDOUBLE_BIAS : Int = 1023 #|let gDOUBLE_POW5_INV_BITCOUNT : Int = 125 #|let gDOUBLE_POW5_BITCOUNT : Int = 125 #|fn decimal_length17(v : UInt64) -> Int { #| if v >= 10000000000000000 { #| return 17 #| } #| if v >= 1000000000000000 { #| return 16 #| } #| if v >= 100000000000000 { #| return 15 #| } #| if v >= 10000000000000 { #| return 14 #| } #| if v >= 1000000000000 { #| return 13 #| } #| if v >= 100000000000 { #| return 12 #| } #| if v >= 10000000000 { #| return 11 #| } #| if v >= 1000000000 { #| return 10 #| } #| if v >= 100000000 { #| return 9 #| } #| if v >= 10000000 { #| return 8 #| } #| if v >= 1000000 { #| return 7 #| } #| if v >= 100000 { #| return 6 #| } #| if v >= 10000 { #| return 5 #| } #| if v >= 1000 { #| return 4 #| } #| if v >= 100 { #| return 3 #| } #| if v >= 10 { #| return 2 #| } #| return 1 #|} #|priv struct FloatingDecimal64 { #| mantissa : UInt64 #| exponent : Int #|} #|fn d2d(ieeeMantissa : UInt64, ieeeExponent : UInt) -> FloatingDecimal64 { #| let mut e2 : Int = 0 #| let mut m2 : UInt64 = 0 #| if ieeeExponent == 0 { #| e2 = 1 - gDOUBLE_BIAS - gDOUBLE_MANTISSA_BITS - 2 #| m2 = ieeeMantissa #| } else { #| e2 = ieeeExponent.reinterpret_as_int() - #| gDOUBLE_BIAS - #| gDOUBLE_MANTISSA_BITS - #| 2 #| m2 = (1UL << gDOUBLE_MANTISSA_BITS) | ieeeMantissa #| } #| let even = (m2 & 1UL) == 0UL #| let mv = 4UL * #| m2 #| let mmShift = ieeeMantissa != 0UL || ieeeExponent <= 1 #| let mut vr = 0UL #| let mut vp = 0UL #| let mut vm = 0UL #| let mut e10 : Int = 0 #| let mut vmIsTrailingZeros = false #| let mut vrIsTrailingZeros = false #| if e2 >= 0 { #| let q : Int = log10Pow2(e2) - (e2 > 3).to_int() #| e10 = q #| let k = gDOUBLE_POW5_INV_BITCOUNT + pow5bits(q) - 1 #| let i = -e2 + q + k #| let pow5 = double_computeInvPow5(q) #| let vs = mulShiftAll64(m2, pow5, i, mmShift) #| vr = vs.0 #| vp = vs.1 #| vm = vs.2 #| if q <= 21 { #| let mvMod5 : Int = mv.to_int() - 5 * (mv / 5UL).to_int() #| if mvMod5 == 0 { #| vrIsTrailingZeros = multipleOfPowerOf5(mv, q) #| } else if even { #| vmIsTrailingZeros = multipleOfPowerOf5( #| mv - 1UL - mmShift.to_uint64(), #| q, #| ) #| } else { #| vp = vp - multipleOfPowerOf5(mv + 2UL, q).to_uint64() #| } #| } #| } else { #| let q : Int = log10Pow5(-e2) - (-e2 > 1).to_int() #| e10 = q + e2 #| let i : Int = -e2 - q #| let k = pow5bits(i) - gDOUBLE_POW5_BITCOUNT #| let j = q - k #| let pow5 = double_computePow5(i) #| let vs = mulShiftAll64(m2, pow5, j, mmShift) #| vr = vs.0 #| vp = vs.1 #| vm = vs.2 #| if q <= 1 { #| vrIsTrailingZeros = true #| if even { #| vmIsTrailingZeros = mmShift.to_int() == 1 #| } else { #| vp = vp - 1 #| } #| } else if q < 63 { #| vrIsTrailingZeros = multipleOfPowerOf2(mv, q) #| } #| } #| let mut removed : Int = 0 #| let mut lastRemovedDigit : Int = 0 #| let mut output : UInt64 = 0UL #| if vmIsTrailingZeros || vrIsTrailingZeros { #| while true { #| let vpDiv10 = vp / 10 #| let vmDiv10 = vm / 10 #| if vpDiv10 <= vmDiv10 { #| break #| } #| let vmMod10 : Int = vm.to_int() - 10 * vmDiv10.to_int() #| let vrDiv10 = vr / 10 #| let vrMod10 : Int = vr.to_int() - 10 * vrDiv10.to_int() #| vmIsTrailingZeros = vmIsTrailingZeros && vmMod10 == 0 #| vrIsTrailingZeros = vrIsTrailingZeros && lastRemovedDigit == 0 #| lastRemovedDigit = vrMod10 #| vr = vrDiv10 #| vp = vpDiv10 #| vm = vmDiv10 #| removed = removed + 1 #| } #| if vmIsTrailingZeros { #| while true { #| let vmDiv10 = vm / 10 #| let vmMod10 : Int = vm.to_int() - 10 * vmDiv10.to_int() #| if vmMod10 != 0 { #| break #| } #| let vpDiv10 = vp / 10 #| let vrDiv10 = vr / 10 #| let vrMod10 : Int = vr.to_int() - 10 * vrDiv10.to_int() #| vrIsTrailingZeros = vrIsTrailingZeros && lastRemovedDigit == 0 #| lastRemovedDigit = vrMod10 #| vr = vrDiv10 #| vp = vpDiv10 #| vm = vmDiv10 #| removed = removed + 1 #| } #| } #| if vrIsTrailingZeros && lastRemovedDigit == 5 && vr % 2 == 0 { #| lastRemovedDigit = 4 #| } #| output = vr + #| ((vr == vm && (!even || !vmIsTrailingZeros)) || lastRemovedDigit >= 5) #| .to_int64() #| .reinterpret_as_uint64() #| } else { #| let mut roundUp = false #| let vpDiv100 = vp / 100 #| let vmDiv100 = vm / 100 #| if vpDiv100 > vmDiv100 { #| let vrDiv100 = vr / 100 #| let vrMod100 : Int = vr.to_int() - 100 * vrDiv100.to_int() #| roundUp = vrMod100 >= 50 #| vr = vrDiv100 #| vp = vpDiv100 #| vm = vmDiv100 #| removed = removed + 2 #| } #| while true { #| let vpDiv10 = vp / 10 #| let vmDiv10 = vm / 10 #| if vpDiv10 <= vmDiv10 { #| break #| } #| let vrDiv10 = vr / 10 #| let vrMod10 : Int = vr.to_int() - 10 * vrDiv10.to_int() #| roundUp = vrMod10 >= 5 #| vr = vrDiv10 #| vp = vpDiv10 #| vm = vmDiv10 #| removed = removed + 1 #| } #| output = vr + (vr == vm || roundUp).to_uint64() #| } #| let exp : Int = e10 + removed #| let fd : FloatingDecimal64 = { mantissa: output, exponent: exp } #| fd #|} #|fn to_chars(v : FloatingDecimal64, sign : Bool) -> String { #| let result = FixedArray::make(25, Byte::default()) #| let mut index : Int = 0 #| if sign { #| result[index] = b'-' #| index += 1 #| } #| let mut output = v.mantissa #| let olength = decimal_length17(output) #| let mut exp : Int = v.exponent + olength - 1 #| let scientificNotation = !(exp >= -6 && exp < 21) #| if scientificNotation { #| for i in 0..<(olength - 1) { #| let c = output % 10 #| output /= 10 #| result[index + olength - i] = (48 + c.to_int()).to_byte() #| } #| result[index] = (48 + output.to_int() % 10).to_byte() #| if olength > 1 { #| result[index + 1] = b'.' #| } else { #| index -= 1 #| } #| index += olength + 1 #| result[index] = b'e' #| index += 1 #| if exp < 0 { #| result[index] = b'-' #| index += 1 #| exp = -exp #| } else { #| result[index] = b'+' #| index += 1 #| } #| if exp >= 100 { #| let a = exp / 100 #| let b = exp / 10 % 10 #| let c = exp % 10 #| result[index + 0] = (48 + a).to_byte() #| result[index + 1] = (48 + b).to_byte() #| result[index + 2] = (48 + c).to_byte() #| index += 3 #| } else if exp >= 10 { #| let a = exp / 10 #| let b = exp % 10 #| result[index + 0] = (48 + a).to_byte() #| result[index + 1] = (48 + b).to_byte() #| index += 2 #| } else { #| result[index] = (48 + exp).to_byte() #| index += 1 #| } #| string_from_bytes(result, 0, index) #| } else { #| if exp < 0 { #| result[index] = b'0' #| index += 1 #| result[index] = b'.' #| index += 1 #| for i = -1; i > exp; i = i - 1 { #| result[index] = b'0' #| index += 1 #| } #| let current = index #| for i in 0..= olength { #| for i in 0.. FloatingDecimal64? { #| let m2 : UInt64 = (1UL << gDOUBLE_MANTISSA_BITS) | ieeeMantissa #| let e2 : Int = ieeeExponent - gDOUBLE_BIAS - gDOUBLE_MANTISSA_BITS #| if e2 > 0 { #| return None #| } #| if e2 < -52 { #| return None #| } #| let mask : UInt64 = (1UL << -e2) - 1UL #| let fraction : UInt64 = m2 & mask #| if fraction != 0UL { #| return None #| } #| Some({ mantissa: m2 >> -e2, exponent: 0 }) #|} #|pub fn ryu_to_string(val : Double) -> String { #| if val == 0.0 { #| return "0" #| } #| let bits : UInt64 = val.reinterpret_as_uint64() #| let ieeeSign = ( #| (bits >> (gDOUBLE_MANTISSA_BITS + gDOUBLE_EXPONENT_BITS)) & 1UL #| ) != #| 0UL #| let ieeeMantissa : UInt64 = bits & ((1UL << gDOUBLE_MANTISSA_BITS) - 1UL) #| let ieeeExponent : Int = ((bits >> gDOUBLE_MANTISSA_BITS) & #| ((1UL << gDOUBLE_EXPONENT_BITS) - 1UL)).to_int() #| if ieeeExponent == (1 << gDOUBLE_EXPONENT_BITS) - 1 || #| (ieeeExponent == 0 && ieeeMantissa == 0UL) { #| return copy_special_str(ieeeSign, ieeeExponent != 0, ieeeMantissa != 0UL) #| } #| let mut v : FloatingDecimal64 = { mantissa: 0UL, exponent: 0 } #| let small = d2d_small_int(ieeeMantissa, ieeeExponent) #| match small { #| Some(f) => { #| let mut x = f #| while true { #| let q : UInt64 = x.mantissa / 10 #| let r = x.mantissa - 10UL * q #| if r != 0 { #| break #| } #| x = { mantissa: q, exponent: x.exponent + 1 } #| } #| v = x #| } #| None => v = d2d(ieeeMantissa, ieeeExponent.reinterpret_as_uint()) #| } #| to_chars(v, ieeeSign) #|} #|test "double/ryu.mbt:205" { #| let m = 123456789UL #| let mul0 = 987654321UL #| let (_, high0) = umul128(m, mul0) #| let low1 = 111111111UL #| let high1 = 222222222UL #| let sum = high0 + low1 #| let mut high1 = high1 #| if sum < high0 { #| high1 = high1 + 1 #| } #| inspect(high1, content="222222222") #|} #|test "double/ryu.mbt:230" { #| let m = 123456789UL #| let mul0 = 987654321UL #| let (_, high0) = umul128(m, mul0) #| let low1 = 111111111UL #| let high1 = 222222222UL #| let sum = high0 + low1 #| let mut high1 = high1 #| if sum < high0 { #| high1 = high1 + 1UL #| } #| assert_eq(high1, 222222222UL) #|} #|test "double/ryu.mbt:252" { #| inspect(gDOUBLE_POW5_BITCOUNT, content="125") #|} #|test "double/ryu.mbt:205" { #| let m = 123456789UL #| let mul0 = 987654321UL #| let (_, high0) = umul128(m, mul0) #| let low1 = 111111111UL #| let high1 = 222222222UL #| let sum = high0 + low1 #| let mut high1 = high1 #| if sum < high0 { #| high1 = high1 + 1UL #| } #| assert_eq(high1, 222222222UL) #|} #|test "double/ryu.mbt:230" { #| let m = 123456789UL #| let mul0 = 987654321UL #| let (_, high0) = umul128(m, mul0) #| let low1 = 111111111UL #| let high1 = 222222222UL #| let sum = high0 + low1 #| let mut high1 = high1 #| if sum < high0 { #| high1 = high1 + 1UL #| } #| assert_eq(high1, 222222222UL) #|} #|test "double/ryu.mbt:252" { #| inspect(gDOUBLE_POW5_BITCOUNT, content="125") #|} ), }, ) ///| let moonbitlang_core_env_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/env", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/builtin" #| ], #| "test-import": [ #| "moonbitlang/core/option" #| ], #| "targets": { #| "env_wasm.mbt": ["wasm", "wasm-gc"], #| "env_js.mbt": ["js"], #| "env_native.mbt": ["native", "llvm"] #| } #|} ), "env.mbt": ( #|pub fn args() -> Array[String] { #| get_cli_args_internal() #|} #|pub fn now() -> UInt64 { #| now_internal() #|} #|pub fn current_dir() -> String? { #| current_dir_internal() #|} ), "env_js.mbt": ( #|extern "js" fn get_cli_args_internal() -> Array[String] = #| #| function() { #| #| if (typeof process !== "undefined" && typeof process.argv !== "undefined") { #| #| return process.argv; #| #| } else { #| #| return []; #| #| } #| #| } #|extern "js" fn now_internal() -> UInt64 = #| #| function() { #| #| const nowMs = Date.now(); #| #| return ({ hi : Number(BigInt(nowMs) >> 32n), lo : nowMs & 0xFFFFFFFF }); #| #| } #|extern "js" fn current_dir_internal() -> String? = #| #| function() { #| #| if (typeof process !== "undefined" && typeof process.cwd === "function") { #| #| return process.cwd(); #| #| } else { #| #| return null; #| #| } #| #| } ), "env_native.mbt": ( #|fn get_cli_args_ffi() -> FixedArray[Bytes] = "$moonbit.get_cli_args" #|fn get_cli_args_internal() -> Array[String] { #| let tmp = get_cli_args_ffi() #| let res = Array::new(capacity=tmp.length()) #| for i in 0.. String { #| let res = StringBuilder::new() #| let len = bytes.length() #| let mut i = 0 #| while i < len { #| let mut c = bytes[i].to_int() #| if c == 0 { #| break #| } else if c < 0x80 { #| res.write_char(c.unsafe_to_char()) #| i += 1 #| } else if c < 0xE0 { #| if i + 1 >= len { #| break #| } #| c = ((c & 0x1F) << 6) | (bytes[i + 1].to_int() & 0x3F) #| res.write_char(c.unsafe_to_char()) #| i += 2 #| } else if c < 0xF0 { #| if i + 2 >= len { #| break #| } #| c = ((c & 0x0F) << 12) | #| ((bytes[i + 1].to_int() & 0x3F) << 6) | #| (bytes[i + 2].to_int() & 0x3F) #| res.write_char(c.unsafe_to_char()) #| i += 3 #| } else { #| if i + 3 >= len { #| break #| } #| c = ((c & 0x07) << 18) | #| ((bytes[i + 1].to_int() & 0x3F) << 12) | #| ((bytes[i + 2].to_int() & 0x3F) << 6) | #| (bytes[i + 3].to_int() & 0x3F) #| c -= 0x10000 #| res.write_char(((c >> 10) + 0xD800).unsafe_to_char()) #| res.write_char(((c & 0x3FF) + 0xDC00).unsafe_to_char()) #| i += 4 #| } #| } #| res.to_string() #|} #|extern "c" fn time(ptr : Int) -> UInt64 = "time" #|fn now_internal() -> UInt64 { #| time(0) * 1000 #|} #|#borrow(ptr) #|extern "c" fn getcwd(ptr : Bytes, size : Int) -> Int = "getcwd" #|fn current_dir_internal() -> String? { #| let buf = Bytes::new(4096) #| let res = getcwd(buf, buf.length()) #| if res == 0 { #| None #| } else { #| Some(utf8_bytes_to_mbt_string(buf)) #| } #|} ), "env_wasm.mbt": ( #|#external #|priv type XStringReadHandle #|#external #|priv type XExternString #|fn begin_read_string(s : XExternString) -> XStringReadHandle = "__moonbit_fs_unstable" "begin_read_string" #|fn string_read_char(handle : XStringReadHandle) -> Int = "__moonbit_fs_unstable" "string_read_char" #|fn finish_read_string(handle : XStringReadHandle) = "__moonbit_fs_unstable" "finish_read_string" #|fn string_from_extern(e : XExternString) -> String { #| let buf = StringBuilder::new() #| let handle = begin_read_string(e) #| while true { #| let ch = string_read_char(handle) #| if ch == -1 { #| break #| } else { #| buf.write_char(ch.unsafe_to_char()) #| } #| } #| finish_read_string(handle) #| buf.to_string() #|} #|#external #|priv type XStringArrayReadHandle #|#external #|priv type XExternStringArray #|fn begin_read_string_array(sa : XExternStringArray) -> XStringArrayReadHandle = "__moonbit_fs_unstable" "begin_read_string_array" #|fn string_array_read_string(handle : XStringArrayReadHandle) -> XExternString = "__moonbit_fs_unstable" "string_array_read_string" #|fn finish_read_string_array(handle : XStringArrayReadHandle) = "__moonbit_fs_unstable" "finish_read_string_array" #|fn string_array_from_extern(e : XExternStringArray) -> Array[String] { #| let buf = Array::new() #| let handle = begin_read_string_array(e) #| while true { #| let extern_str = string_array_read_string(handle) #| let str = string_from_extern(extern_str) #| if str == "ffi_end_of_/string_array" { #| break #| } else { #| buf.push(str) #| } #| } #| finish_read_string_array(handle) #| buf #|} #|fn get_cli_args_internal() -> Array[String] { #| let args = get_cli_args_ffi() #| string_array_from_extern(args) #|} #|fn get_cli_args_ffi() -> XExternStringArray = "__moonbit_fs_unstable" "args_get" #|fn now_internal() -> UInt64 = "__moonbit_time_unstable" "now" #|fn current_dir_internal() -> String? { #| let dir = current_dir_ffi() #| let dir = string_from_extern(dir) #| if dir == "" { #| None #| } else { #| Some(dir) #| } #|} #|fn current_dir_ffi() -> XExternString = "__moonbit_fs_unstable" "current_dir" ), }, ) ///| let moonbitlang_core_error_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/error", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module }, files={ "moon.pkg.json": ( #|{ #| "import": ["moonbitlang/core/builtin"], #| "test-import": [ #| "moonbitlang/core/json" #| ] #|} ), "error.mbt": ( #|fn Error::to_string(self : Error) -> String = "%error.to_string" #|pub impl Show for Error with output(self, logger) { #| logger.write_string(self.to_string()) #|} #|fn Error::to_json(self : Error) -> Json = "%error.to_json" #|pub impl ToJson for Error with to_json(self) { #| self.to_json() #|} ), }, ) ///| let moonbitlang_core_float_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/float", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/double": moonbitlang_core_double_module, "moonbitlang/core/uint": moonbitlang_core_uint_module, }, files={ "moon.pkg.json": ( #|{ #| "import": ["moonbitlang/core/builtin", "moonbitlang/core/double", "moonbitlang/core/uint"], #| "targets": { #| "round_js.mbt": ["js"], #| "round_wasm.mbt": ["wasm", "wasm-gc"], #| "round.mbt": ["not", "js", "wasm", "wasm-gc"], #| "to_int.mbt": ["not", "wasm", "wasm-gc"], #| "to_int_wasm.mbt": ["wasm", "wasm-gc"] #| } #|} ), "deprecated.mbt": ( #|#deprecated("use `@math.cbtrf` instead") #|#coverage.skip #|pub fn Float::cbrt(self : Float) -> Float { #| let b1 : UInt = 709958130 // B1 = (127-127.0/3-0.03306235651)*2**23 */ #| let b2 : UInt = 642849266 // B2 = (127-127.0/3-24/3-0.03306235651)*2**23 */ #| let mut ui : UInt = self.reinterpret_as_uint() #| let mut hx : UInt = ui & 0x7fffffff #| if hx >= 0x7f800000 { #| return self + self #| } #| if hx < 0x00800000 { #| if hx == 0 { #| return self #| } // cbrt(+-0) is itx #| ui = (self * (0x1.0p24 : Float)).reinterpret_as_uint() #| hx = ui & 0x7fffffff #| hx = hx / 3 + b2 #| } else { #| hx = hx / 3 + b1 #| } #| ui = ui & 0x80000000 #| ui = ui | hx #| let dx = self.to_double() #| let t = ui.reinterpret_as_float().to_double() #| let r = t * t * t #| let t = t * (dx + dx + r) / (dx + r + r) #| let r = t * t * t #| let t = t * (dx + dx + r) / (dx + r + r) #| t.to_float() #|} #|#deprecated("use `@math.hypotf` instead") #|#coverage.skip #|pub fn Float::hypot(self : Float, y : Float) -> Float { #| let epsilon : Float = 1.1920928955078125e-7 #| let x = self.abs() #| let y = y.abs() #| if self.is_inf() || y.is_inf() { #| return infinity #| } #| let (x, y) = if y > x { (y, x) } else { (x, y) } #| if x * epsilon >= y { #| return x #| } #| let rat = y / x #| x * (rat * rat + 1.0).sqrt() #|} #|#deprecated("use `@math.expf` instead") #|#coverage.skip #|pub fn Float::exp(self : Float) -> Float { #| let xd = self.to_double() #| let abstop = top12(self) & 0x7ff #| if abstop >= top12(88.0) { #| if self.reinterpret_as_uint() == neg_infinity.reinterpret_as_uint() { #| return 0.0 #| } #| if abstop >= top12(infinity) { #| return self + self #| } #| if self > 0x1.62e42ep6 { #| return __math_oflowf(0) #| } #| if self < -0x1.9fe368p6 { #| return __math_uflowf(0) #| } #| } #| let z = exp2f_data.invln2_scaled * xd #| let kd = z + exp2f_data.shift #| let ki = kd.reinterpret_as_uint64() #| let kd = kd - exp2f_data.shift #| let r = z - kd #| let t = exp2f_data.tab[(ki % expf_n).to_int()] #| let t = t + (ki << (52 - exp2f_table_bits)) #| let s = t.reinterpret_as_double() #| let z = exp2f_data.poly_scaled[0] * r + exp2f_data.poly_scaled[1] #| let r2 = r * r #| let y = exp2f_data.poly_scaled[2] * r + 1 #| let y = z * r2 + y #| let y = y * s #| y.to_float() #|} #|#deprecated("use `@math.expm1f` instead") #|#coverage.skip #|pub fn Float::expm1(self : Float) -> Float { #| let float_ln2_hi : Float = 6.9314575195e-01 // 0x3f317200 #| let float_ln2_lo : Float = 1.4286067653e-06 // 0x35bfbe8e #| let inv_ln2 : Float = 1.4426950216e+00 // 0x3fb8aa3b #| let mut x = self #| let q1 : Float = -3.3333212137e-2 // -0x888868.0p-28 #| let q2 : Float = 1.5807170421e-3 // 0xcf3010.0p-33 #| let mut hx = x.reinterpret_as_uint() #| let sign = hx >> 31 != 0 #| hx = hx & 0x7fffffff #| if hx >= 0x4195b844 { #| if hx > 0x7f800000 { #| return x #| } #| if sign { #| return -1.0 #| } #| if hx > 0x42b17217 { #| x *= (0x1.0p127 : Float) #| return x #| } #| } #| let mut k : Int = 0 #| let mut hi : Float = 0 #| let mut lo : Float = 0 #| let mut c : Float = 0 #| if hx > 0x3eb17218 { #| if hx < 0x3F851592 { #| if !sign { #| hi = x - float_ln2_hi #| lo = float_ln2_lo #| k = 1 #| } else { #| hi = x + float_ln2_hi #| lo = -float_ln2_lo #| k = -1 #| } #| } else { #| k = (inv_ln2 * x + (if sign { -0.5 } else { 0.5 })).to_int() #| let t = k.to_float() #| hi = x - t * float_ln2_hi // t*ln2_hi is exact here #| lo = t * float_ln2_lo #| } #| x = hi - lo #| c = hi - x - lo #| } else if hx < 0x33000000 { #| return x #| } else { #| k = 0 #| } #| let hfx = (0.5 : Float) * x #| let hxs = x * hfx #| let r1 = (1.0 : Float) + hxs * (q1 + hxs * q2) #| let t = (3.0 : Float) - r1 * hfx #| let mut e = hxs * ((r1 - t) / ((6.0 : Float) - x * t)) #| if k == 0 { #| return x - (x * e - hxs) #| } #| e = x * (e - c) - c #| e -= hxs #| if k == -1 { #| return (0.5 : Float) * (x - e) - 0.5 #| } #| if k == 1 { #| if x < -0.25 { #| return -(2.0 : Float) * (e - (x + 0.5)) #| } #| return (1.0 : Float) + (2.0 : Float) * (x - e) #| } #| let twopk = ((0x7f + k) << 23).reinterpret_as_float() // 2^k #| if !(k is (0..=56)) { #| let mut y = x - e + 1.0 #| if k == 128 { #| y = y * 2.0 * (0x1.0p127 : Float) #| } else { #| y = y * twopk #| } #| return y - 1.0 #| } #| let uf = ((0x7f - k) << 23).reinterpret_as_float() // 2^-k #| if k < 23 { #| (x - e + ((1.0 : Float) - uf)) * twopk #| } else { #| (x - (e + uf) + 1.0) * twopk #| } #|} #|#deprecated("use `@math.sinh` instead") #|#coverage.skip #|pub fn Float::sinh(self : Float) -> Float { #| let x = self #| let mut h : Float = 0.5 #| let mut ix = x.reinterpret_as_uint() #| if ix >> 31 != 0 { #| h = -h #| } #| ix = ix & 0x7fffffff #| let absx = ix.reinterpret_as_float() #| let w = ix #| if w < 0x42b17217 { #| let t = absx.expm1() #| if w < 0x3f800000 { #| if w < 0x3f800000U - (12U << 23) { #| return x #| } #| return h * ((2.0 : Float) * t - t * t / (t + 1.0)) #| } #| return h * (t + t / (t + 1.0)) #| } #| h * k_expo2f(absx) * 2.0 #|} #|#deprecated("use `@math.cosh` instead") #|#coverage.skip #|pub fn Float::cosh(self : Float) -> Float { #| let mut x = self #| let mut ix = x.reinterpret_as_uint() #| ix = ix & 0x7fffffff #| x = ix.reinterpret_as_float() #| let w = ix #| if w < 0x3f317217 { #| if w < 0x3f800000U - (12U << 23) { #| return 1.0 #| } #| let t = x.expm1() #| return (1.0 : Float) + t * t / ((2.0 : Float) * (t + 1.0)) #| } #| if w < 0x42b17217 { #| let t = x.exp() #| return (t + (1.0 : Float) / t) * 0.5 #| } #| k_expo2f(x) #|} #|#deprecated("use `@math.tanh` instead") #|#coverage.skip #|pub fn Float::tanh(self : Float) -> Float { #| let x = self #| let mut ix = x.reinterpret_as_uint() #| let sign = ix >> 31 != 0 #| ix = ix & 0x7fffffff #| let x = ix.reinterpret_as_float() #| let w = ix #| let tt = if w > 0x3f0c9f54 { #| if w > 0x41200000 { #| (1.0 : Float) + (0.0 : Float) / x #| } else { #| let t = (x * 2.0).expm1() #| (1.0 : Float) - (2.0 : Float) / (t + 2.0) #| } #| } else if w > 0x3e82c578 { #| let t = (x * 2.0).expm1() #| t / (t + 2.0) #| } else if w >= 0x00800000 { #| let t = (x * -2.0).expm1() #| -t / (t + 2.0) #| } else { #| x #| } #| if sign { #| -tt #| } else { #| tt #| } #|} #|#deprecated("use `@math.asinh` instead") #|#coverage.skip #|pub fn Float::asinh(self : Float) -> Float { #| let x = self #| let u = x.reinterpret_as_uint() #| let i = u & 0x7fffffff #| let sign = u >> 31 != 0 #| let ln2 : Float = 0.693147180559945309417232121458176568 #| let x = i.reinterpret_as_float() #| let x = if i >= 0x3f800000U + (12U << 23) { #| x.ln() + ln2 #| } else if i >= 0x3f800000U + (1U << 23) { #| (x * 2.0 + (1.0 : Float) / ((x * x + 1.0).sqrt() + x)).ln() #| } else if i >= 0x3f800000U - (12U << 23) { #| (x + x * x / ((x * x + 1.0).sqrt() + 1.0)).ln_1p() #| } else { #| x #| } #| if sign { #| -x #| } else { #| x #| } #|} #|#deprecated("use `@math.acosh` instead") #|#coverage.skip #|pub fn Float::acosh(self : Float) -> Float { #| let x = self #| let ln2 : Float = 693147180559945309417232121458176568 #| let u = x.reinterpret_as_uint() #| let a = u & 0x7fffffffU #| if a < 0x3f800000U + (1U << 23) { #| return (x - 1.0 + ((x - 1.0) * (x - 1.0) + (2.0 : Float) * (x - 1.0)).sqrt()).ln_1p() #| } #| if a < 0x3f800000U + (12U << 23) { #| return (x * 2.0 - (1.0 : Float) / (x + (x * x - 1.0).sqrt())).ln() #| } #| return x.ln() + ln2 #|} #|#deprecated("use `@math.atanh` instead") #|#coverage.skip #|pub fn Float::atanh(self : Float) -> Float { #| let x = self #| let u = x.reinterpret_as_uint() #| let sign = u >> 31 != 0 #| let u = u & 0x7fffffff #| let x = u.reinterpret_as_float() #| let x = if u < 0x3f800000U - (1U << 23) { #| if u < 0x3f800000U - (32U << 23) { #| x #| } else { #| (x * 2.0 + x * 2.0 * x / ((1.0 : Float) - x)).ln_1p() * 0.5 #| } #| } else { #| (x / ((1.0 : Float) - x) * 2.0).ln_1p() * 0.5 #| } #| if sign { #| -x #| } else { #| x #| } #|} #|#deprecated("use `@math.lnf` instead") #|#coverage.skip #|pub fn Float::ln(self : Float) -> Float { #| let mut ix : UInt = self.reinterpret_as_uint() #| if ix == 0x3f800000U { #| return 0.0 #| } #| if ix - 0x00800000U >= 0x7f800000U - 0x00800000U { #| if ix * 2 == 0 { #| return neg_infinity #| } #| if ix == 0x7f800000U { #| return self #| } #| if (ix & 0x80000000U) != 0 || ix * 2 >= 0xff000000U { #| return not_a_number #| } #| ix = (self * 0x1.0p23).reinterpret_as_uint() #| ix -= (23 << 23).reinterpret_as_uint() #| } #| let tmp = ix - logf_off #| let i = ((tmp >> (23 - logf_table_bits)) % logf_n).reinterpret_as_int() #| let k = tmp.reinterpret_as_int() >> 23 #| let iz = ix - (tmp & 0xff800000U) #| let invc = logf_data.invc[i] #| let logc = logf_data.logc[i] #| let z = iz.reinterpret_as_float().to_double() #| let r = z * invc - 1 #| let y0 = logc + k.to_double() * logf_data.ln2 #| let r2 = r * r #| let y = logf_data.poly[1] * r + logf_data.poly[2] #| let y = logf_data.poly[0] * r2 + y #| let y = y * r2 + (y0 + r) #| y.to_float() #|} #|#deprecated("use `@math.ln_1pf` instead") #|#coverage.skip #|pub fn Float::ln_1p(self : Float) -> Float { #| let lg1_f : Float = 0.66666662693 #| let lg2_f : Float = 0.40000972152 #| let lg3_f : Float = 0.28498786688 #| let lg4_f : Float = 0.24279078841 #| let float_ln2_hi : Float = 6.9314575195e-01 // 0x3f317200 #| let float_ln2_lo : Float = 1.4286067653e-06 // 0x35bfbe8e #| let mut ui : UInt = self.reinterpret_as_uint() #| let mut f : Float = 0 #| let mut c : Float = 0 #| let mut iu : UInt = 0 #| let one : Float = 1.0 #| let mut k = 1 #| if ui < 0x3ed413d0 || ui >> 31 > 0 { #| if ui >= 0xbf800000 { #| if self == -1.0 { #| return self / 0.0 #| } #| return (self - self) / 0.0 #| } #| if ui << 1 < 0x33800000U << 1 { #| return self #| } #| if ui <= 0xbe95f619 { #| k = 0 #| c = 0.0 #| f = self #| } #| } else if ui >= 0x7f800000 { #| return self #| } #| if k > 0 { #| ui = (one + self).reinterpret_as_uint() #| iu = ui #| iu += 0x3f800000U - 0x3f3504f3U #| k = (iu >> 23).reinterpret_as_int() - 0x7f #| if k < 25 { #| let fui = ui.reinterpret_as_float() #| c = if k >= 2 { one - (fui - self) } else { self - (fui - 1.0) } #| c /= ui.reinterpret_as_float() #| } else { #| c = 0.0 #| } #| iu = (iu & 0x007fffff) + 0x3f3504f3 #| ui = iu #| f = ui.reinterpret_as_float() - 1.0 #| } #| let s = f / (f + 2.0) #| let z = s * s #| let w = z * z #| let t1 = w * (lg2_f + w * lg4_f) #| let t2 = z * (lg1_f + w * lg3_f) #| let r = t2 + t1 #| let hfsq = f * f * 0.5 #| let dk = k.to_float() #| s * (hfsq + r) + (dk * float_ln2_lo + c) - hfsq + f + dk * float_ln2_hi #|} #|#deprecated("use `@math.sinf` instead") #|#coverage.skip #|pub fn Float::sin(self : Float) -> Float { #| let x = self #| if x.is_nan() || x.is_inf() { #| return not_a_number #| } #| if x == 0.0 { #| return x #| } #| let (x, q) = trig_reduce(x, SIN_SWITCHOVER) #| sin_cos_core(x, q) #|} #|#deprecated("use `@math.cosf` instead") #|#coverage.skip #|pub fn Float::cos(self : Float) -> Float { #| let x = self #| if x.is_nan() || x.is_inf() { #| return not_a_number #| } #| if x == 0.0 { #| return 1.0 #| } #| let (x, q) = trig_reduce(x, COS_SWITCHOVER) #| sin_cos_core(x, q + 1) #|} #|#deprecated("use `@math.tanf` instead") #|#coverage.skip #|pub fn Float::tan(self : Float) -> Float { #| let x = self #| if x.is_nan() || x.is_inf() { #| return not_a_number #| } #| if x == 0.0 { #| return x #| } #| let (x, q) = trig_reduce(x, COS_SWITCHOVER) #| tanf_poly(x, (q & 1) != 0) #|} #|#deprecated("use `@math.asinf` instead") #|#coverage.skip #|pub fn Float::asin(self : Float) -> Float { #| let x = self #| let x1p120 = 0x3870000000000000UL.reinterpret_as_double() #| let pio2 : Double = 1.570796326794896558e+00 #| let ps0 : Float = 1.6666586697e-01 #| let ps1 : Float = -4.2743422091e-02 #| let ps2 : Float = -8.6563630030e-03 #| let qs2 : Float = -7.0662963390e-01 #| fn r(z : Float) -> Float { #| let p = z * (ps0 + z * (ps1 + z * ps2)) #| let q = z * qs2 + 1.0 #| p / q #| } #| let hx = x.reinterpret_as_uint() #| let ix = hx & 0x7fffffff #| if ix >= 0x3f800000 { #| if ix == 0x3f800000 { #| return (x.to_double() * pio2 + x1p120).to_float() #| } #| return not_a_number // asin(|x|>1) is NaN #| } #| if ix < 0x3f000000 { #| if ix is (0x00800000..=0x39800000) { #| return x #| } #| return x + x * r(x * x) #| } #| let z = ((1.0 : Float) - x.abs()) * 0.5 #| let s = z.to_double().sqrt() #| let x = (pio2 - 2.0 * (s + s * r(z).to_double())).to_float() #| if hx >> 31 != 0 { #| -x #| } else { #| x #| } #|} #|#deprecated("use `@math.acosf` instead") #|#coverage.skip #|pub fn Float::acos(self : Float) -> Float { #| let x = self #| let pio2_hi : Float = 1.5707962513 #| let pio2_lo : Float = 7.5497894159e-08 #| let ps0 : Float = 1.6666586697e-01 #| let ps1 : Float = -4.2743422091e-02 #| let ps2 : Float = -8.6563630030e-03 #| let qs1 : Float = -7.0662963390e-01 #| let one : Float = 1.0 #| let two : Float = 2.0 #| fn r(z : Float) -> Float { #| let p = z * (ps0 + z * (ps1 + z * ps2)) #| let q = z * qs1 + 1.0 #| p / q #| } #| let hx = x.reinterpret_as_int() #| let ix = hx & 0x7fffffff #| if ix >= 0x3f800000 { #| if ix == 0x3f800000 { #| if hx >> 31 != 0 { #| return two * pio2_hi + 0x1.0p-120 #| } #| return 0.0 #| } #| return not_a_number #| } #| if ix < 0x3f000000 { #| if ix <= 0x32800000 { #| return pio2_hi + 0x1.0p-120 #| } #| return pio2_hi - (x - (pio2_lo - x * r(x * x))) #| } #| if hx >> 31 != 0 { #| let z = (x + 1.0) * 0.5 #| let s = z.sqrt() #| let w = r(z) * s - pio2_lo #| return two * (pio2_hi - (s + w)) #| } #| let z = (one - x) * 0.5 #| let s = z.sqrt() #| let df = s #| let c = (z - df * df) / (s + df) #| let w = r(z) * s + c #| two * (df + w) #|} #|#deprecated("use `@math.atanf` instead") #|#coverage.skip #|pub fn Float::atan(self : Float) -> Float { #| let x = self #| let atanhi : Array[Float] = [ #| 4.6364760399e-01, 7.8539812565e-01, 9.8279368877e-01, 1.5707962513e+00, #| ] #| let atanlo : Array[Float] = [ #| 5.0121582440e-09, 3.7748947079e-08, 3.4473217170e-08, 7.5497894159e-08, #| ] #| let a_t : Array[Float] = [ #| 3.3333328366e-01, -1.9999158382e-01, 1.4253635705e-01, -1.0648017377e-01, 6.1687607318e-02, #| ] #| let ix = x.reinterpret_as_int() #| let sign = ix >> 31 #| let ix = ix & 0x7fffffff #| let mut id = 0 #| let mut x = x #| let one : Float = 1.0 #| let two : Float = 2.0 #| if ix >= 0x4c800000 { #| if x.is_nan() { #| return x #| } #| let z = atanhi[3] + 0x1.0p-120 #| let z = if sign != 0 { -z } else { z } #| return z #| } #| if ix < 0x3ee00000 { #| if ix < 0x39800000 { #| return x #| } #| id = -1 #| } else { #| x = x.abs() #| if ix < 0x3f980000 { #| if ix < 0x3f300000 { #| id = 0 #| x = (two * x - one) / (two + x) #| } else { #| id = 1 #| x = (x - one) / (x + one) #| } #| } else if ix < 0x401c0000 { #| id = 2 #| x = (x - 1.5) / (one + x * 1.5) #| } else { #| id = 3 #| x = -one / x #| } #| } #| let z = x * x #| let w = z * z #| let s1 = z * (a_t[0] + w * (a_t[2] + w * a_t[4])) #| let s2 = w * (a_t[1] + w * a_t[3]) #| if id < 0 { #| return x - x * (s1 + s2) #| } #| let z = atanhi[id] - (x * (s1 + s2) - atanlo[id] - x) #| if sign != 0 { #| -z #| } else { #| z #| } #|} #|#deprecated("use `@math.atan2f` instead") #|#coverage.skip #|pub fn Float::atan2(self : Float, other : Float) -> Float { #| let (y, x) = (self, other) #| if x.is_nan() || y.is_nan() { #| return not_a_number #| } #| let pi : Float = 3.1415927410e+00 #| let pi_lo : Float = -8.7422776573e-08 #| let zero : Float = 0.0 #| let ix = x.reinterpret_as_uint() #| let iy = y.reinterpret_as_uint() #| if ix == 0x3f800000 { #| return y.atan() #| } #| let m = ((iy >> 31) & 1) | ((ix >> 30) & 2) #| let ix = ix & 0x7fffffff #| let iy = iy & 0x7fffffff #| if iy == 0 { #| match m { #| 0 | 1 => return y #| 2 => return pi #| _ => return -pi #| } #| } #| if ix == 0 { #| let res = if (m & 1) != 0 { -pi / 2 } else { pi / 2 } #| return res #| } #| if ix == 0x7f800000 { #| if iy == 0x7f800000 { #| match m { #| 0 => return pi / 4 #| 1 => return -pi / 4 #| 2 => return pi * 3.0 / 4 #| _ => return -pi * 3.0 / 4 #| } #| } else { #| match m { #| 0 => return 0.0 #| 1 => return -0.0 #| 2 => return pi #| _ => return -pi #| } #| } #| } #| if ix + (26U << 23) < iy || iy == 0x7f800000 { #| let res = if (m & 1) != 0 { -pi / 2 } else { pi / 2 } #| return res #| } #| let z = if (m & 2) != 0 && iy + (26U << 23) < ix { #| zero #| } else { #| (y / x).atan() #| } #| match m { #| 0 => z #| 1 => -z #| 2 => pi - (z - pi_lo) #| _ => z - pi_lo - pi #| } #|} ), "exp.mbt": ( #|fn top12(x : Float) -> UInt { #| x.reinterpret_as_uint() >> 20 #|} #|fn __math_xflowf(sign : UInt, y : Float) -> Float { #| return (if sign != 0 { -y } else { y }) * y #|} #|fn __math_oflowf(sign : UInt) -> Float { #| return __math_xflowf(sign, 0x1.0p97) #|} #|fn __math_uflowf(sign : UInt) -> Float { #| return __math_xflowf(sign, 0x1.0p-95) #|} #|let exp2f_table_bits = 5 #|priv struct Exp2fData { #| tab : FixedArray[UInt64] #| shift : Double #| invln2_scaled : Double #| poly_scaled : FixedArray[Double] #|} #|let expf_n : UInt64 = (1 << exp2f_table_bits).to_uint64() #|let exp2f_data_n : Double = (1 << exp2f_table_bits).to_double() #|let exp2f_data : Exp2fData = { #| tab: [ #| 0x3ff0000000000000, 0x3fefd9b0d3158574, 0x3fefb5586cf9890f, 0x3fef9301d0125b51, #| 0x3fef72b83c7d517b, 0x3fef54873168b9aa, 0x3fef387a6e756238, 0x3fef1e9df51fdee1, #| 0x3fef06fe0a31b715, 0x3feef1a7373aa9cb, 0x3feedea64c123422, 0x3feece086061892d, #| 0x3feebfdad5362a27, 0x3feeb42b569d4f82, 0x3feeab07dd485429, 0x3feea47eb03a5585, #| 0x3feea09e667f3bcd, 0x3fee9f75e8ec5f74, 0x3feea11473eb0187, 0x3feea589994cce13, #| 0x3feeace5422aa0db, 0x3feeb737b0cdc5e5, 0x3feec49182a3f090, 0x3feed503b23e255d, #| 0x3feee89f995ad3ad, 0x3feeff76f2fb5e47, 0x3fef199bdd85529c, 0x3fef3720dcef9069, #| 0x3fef5818dcfba487, 0x3fef7c97337b9b5f, 0x3fefa4afa2a490da, 0x3fefd0765b6e4540, #| ], #| shift: 0x1.8p+52, #| invln2_scaled: 0x1.71547652b82fep+0 * exp2f_data_n, #| poly_scaled: [ #| 0x1.c6af84b912394p-5 / exp2f_data_n / exp2f_data_n / exp2f_data_n, #| 0x1.ebfce50fac4f3p-3 / exp2f_data_n / exp2f_data_n, #| 0x1.62e42ff0c52d6p-1 / exp2f_data_n, #| ], #|} ), "float.mbt": ( #|pub let not_a_number : Float = (0x7FC00000).reinterpret_as_float() #|pub let infinity : Float = (0x7F800000).reinterpret_as_float() #|pub let neg_infinity : Float = (0xFF800000).reinterpret_as_float() #|pub let max_value : Float = (0x7F7FFFFF).reinterpret_as_float() #|pub let min_value : Float = (0xFF7FFFFF).reinterpret_as_float() #|pub let min_positive : Float = (0x00800000).reinterpret_as_float() #|pub fn Float::abs(self : Float) -> Float = "%f32.abs" #|pub impl Show for Float with output(self, logger) { #| logger.write_string(self.to_double().to_string()) #|} #|pub impl Default for Float with default() { #| 0.0 #|} #|pub fn default() -> Float { #| 0.0 #|} #|pub impl Hash for Float with hash(self) { #| self.reinterpret_as_int() |> Hash::hash() #|} #|pub impl Hash for Float with hash_combine(self, hasher) { #| hasher.combine_float(self) #|} #|pub fn to_be_bytes(self : Float) -> Bytes { #| self.reinterpret_as_uint().to_be_bytes() #|} #|pub fn to_le_bytes(self : Float) -> Bytes { #| self.reinterpret_as_uint().to_le_bytes() #|} #|pub fn is_inf(self : Float) -> Bool { #| self.is_pos_inf() || self.is_neg_inf() #|} #|pub fn is_pos_inf(self : Float) -> Bool { #| self > max_value #|} #|pub fn is_neg_inf(self : Float) -> Bool { #| self < min_value #|} #|pub fn is_nan(self : Float) -> Bool { #| self != self #|} #|pub fn Float::is_close( #| self : Self, #| other : Self, #| relative_tolerance? : Self = 1.0e-09, #| absolute_tolerance? : Self = 0.0, #|) -> Bool { #| if relative_tolerance < 0.0 || absolute_tolerance < 0.0 { #| abort("Tolerances must be non-negative") #| } #| if self == other { #| return true #| } #| if self.is_inf() || other.is_inf() { #| return false #| } #| let diff = (other - self).abs() #| return ( #| diff <= (relative_tolerance * other).abs() || #| diff <= (relative_tolerance * self).abs() #| ) || #| diff <= absolute_tolerance #|} ), "hyperbolic.mbt": ( #|fn k_expo2f(x : Float) -> Float { #| let k = 235 #| let k_ln2 = (0x4322e3bc).reinterpret_as_float() #| let scale = ((0x7f + k / 2) << 23).reinterpret_as_float() #| (x - k_ln2).exp() * scale * scale #|} ), "log.mbt": ( #|let logf_off = 0x3f330000U #|let logf_table_bits = 4 #|let logf_n : UInt = 1U << logf_table_bits #|priv struct LogfData { #| invc : FixedArray[Double] #| logc : FixedArray[Double] #| ln2 : Double #| poly : FixedArray[Double] #|} #|let logf_data : LogfData = { #| invc: [ #| 0x1.661ec79f8f3bep+0, 0x1.571ed4aaf883dp+0, 0x1.49539f0f010bp+0, 0x1.3c995b0b80385p+0, #| 0x1.30d190c8864a5p+0, 0x1.25e227b0b8eap+0, 0x1.1bb4a4a1a343fp+0, 0x1.12358f08ae5bap+0, #| 0x1.0953f419900a7p+0, 0x1.0p+0, 0x1.e608cfd9a47acp-1, 0x1.ca4b31f026aap-1, 0x1.b2036576afce6p-1, #| 0x1.9c2d163a1aa2dp-1, 0x1.886e6037841edp-1, 0x1.767dcf5534862p-1, #| ], #| logc: [ #| -0x1.57bf7808caadep-2, -0x1.2bef0a7c06ddbp-2, -0x1.01eae7f513a67p-2, -0x1.b31d8a68224e9p-3, #| -0x1.6574f0ac07758p-3, -0x1.1aa2bc79c81p-3, -0x1.a4e76ce8c0e5ep-4, -0x1.1973c5a611cccp-4, #| -0x1.252f438e10c1ep-5, 0x0.0p+0, 0x1.aa5aa5df25984p-5, 0x1.c5e53aa362eb4p-4, #| 0x1.526e57720db08p-3, 0x1.bc2860d22477p-3, 0x1.1058bc8a07ee1p-2, 0x1.4043057b6ee09p-2, #| ], #| ln2: 0x1.62e42fefa39efp-1, #| poly: [-0x1.00ea348b88334p-2, 0x1.5575b0be00b6ap-2, -0x1.ffffef20a4123p-2], #|} ), "math_functions.mbt": ( #|pub fnalias Float::( #| sin, #| cos, #| tan, #| asin, #| acos, #| atan, #| atan2, #| exp, #| expm1, #| pow, #| ln, #| ln_1p, #| sinh, #| cosh, #| tanh, #| asinh, #| acosh, #| atanh, #| hypot, #| cbrt, #| trunc, #| ceil, #| floor, #| round, #| abs #|) ), "mod.mbt": ( #|pub impl Mod for Float with op_mod(self : Float, other : Float) -> Float { #| (self.to_double() % other.to_double()).to_float() #|} ), "pow.mbt": ( #|pub fn Float::pow(self : Float, other : Float) -> Float { #| self.to_double().pow(other.to_double()).to_float() #|} ), "round.mbt": ( #|let sign_mask : UInt = 0x8000_0000 #|let exp_bias = 127 #|let exp_bits = 8 #|let frac_bits = 23 #|pub fn Float::trunc(self : Float) -> Float { #| let u32 = self.reinterpret_as_uint() #| let biased_exp = ((u32 >> frac_bits) & ((0x1U << exp_bits) - 1)).reinterpret_as_int() #| if biased_exp < exp_bias { #| return (u32 & sign_mask).reinterpret_as_float() #| } else if biased_exp >= exp_bias + frac_bits { #| return self #| } #| let mask_shift = biased_exp - exp_bias + exp_bits #| let trunc_mask = (sign_mask.reinterpret_as_int() >> mask_shift).reinterpret_as_uint() #| return (u32 & trunc_mask).reinterpret_as_float() #|} #|pub fn Float::ceil(self : Float) -> Float { #| let trunced = self.trunc() #| if self > trunced { #| return trunced + 1.0 #| } else { #| return trunced #| } #|} #|pub fn Float::floor(self : Float) -> Float { #| let trunced = self.trunc() #| if self < trunced { #| return trunced - 1.0 #| } else { #| return trunced #| } #|} #|pub fn Float::round(self : Float) -> Float { #| floor(self + 0.5) #|} ), "round_js.mbt": ( #|pub fn Float::trunc(self : Float) -> Float = "Math" "trunc" #|pub fn Float::ceil(self : Float) -> Float = "Math" "ceil" #|pub fn Float::floor(self : Float) -> Float = "Math" "floor" #|pub fn Float::round(self : Float) -> Float = "Math" "round" ), "round_wasm.mbt": ( #|pub fn Float::trunc(self : Float) -> Float = "(func (param $f f32) (result f32) (f32.trunc (local.get $f)))" #|pub fn Float::ceil(self : Float) -> Float = "(func (param $f f32) (result f32) (f32.ceil (local.get $f)))" #|pub fn Float::floor(self : Float) -> Float = "(func (param $f f32) (result f32) (f32.floor (local.get $f)))" #|pub fn Float::round(self : Float) -> Float { #| floor(self + 0.5) #|} ), "to_int.mbt": ( #|fn Float::to_unchecked_int(self : Float) -> Int = "%f32.to_i32" #|pub fn to_int(self : Float) -> Int { #| if self != self { #| 0 #| } else if self >= 2147483647 { #| 2147483647 #| } else if self <= -2147483648 { #| -2147483648 #| } else { #| self.to_unchecked_int() #| } #|} ), "to_int_wasm.mbt": ( #|pub fn to_int(self : Float) -> Int = "%f32.to_i32_saturate" ), "trig.mbt": ( #|const SIN_SWITCHOVER : Float = 201.15625 #|const COS_SWITCHOVER : Float = 142.90625 #|fn mulh(a : UInt, b : UInt) -> UInt { #| let a = a.to_uint64() #| let b = b.to_uint64() #| let res = a * b #| (res >> 32).to_uint() #|} #|fn mul(a : UInt, b : UInt) -> (UInt, UInt) { #| let a = a.to_uint64() #| let b = b.to_uint64() #| let res = a * b #| ((res >> 32).to_uint(), res.to_uint()) #|} #|fn trig_reduce(x : Float, switch_over : Float) -> (Float, Int) { #| if x.abs() <= switch_over { #| let mut j : Float = 0.0 #| let mut r : Float = 0.0 #| j = x * (0x3f22f983).reinterpret_as_float() + #| (0x4b40_0000).reinterpret_as_float() #| j = (j.reinterpret_as_int() - 0x4b40_0000).to_float() #| r = x - j * (0x3fc90f80).reinterpret_as_float() #| r = r - j * (0x37354440).reinterpret_as_float() #| r = r - j * (0x2c34611a).reinterpret_as_float() #| return (r, j.to_int()) #| } #| let xispos = x > 0.0 #| let mut exp : Int = ((x.reinterpret_as_int() >> 23) & 0xff) - 126 #| let ix = ((x.reinterpret_as_uint() & 0x007fffff) << 8) | 0x80000000 #| let ind = exp >> 5 #| exp = exp & 0x1f #| let two_over_pi : Array[UInt] = [ #| 0x00000000, 0x28be60db, 0x9391054a, 0x7f09d5f4, 0x7d4d3770, 0x36d8a566, 0x4f10e410, #| 0000000000, #| ] #| let mut hi = two_over_pi[ind] #| let mut mi = two_over_pi[ind + 1] #| let mut lo = two_over_pi[ind + 2] #| let tp = two_over_pi[ind + 3] #| if exp > 0 { #| hi = (hi << exp) | (mi >> (32 - exp)) #| mi = (mi << exp) | (lo >> (32 - exp)) #| lo = (lo << exp) | (tp >> (32 - exp)) #| } #| let phi = 0U #| let (h, l) = mul(ix, lo) #| let plo = phi + l #| let phi = h + (if plo < l { 1 } else { 0 }) #| let (h, l) = mul(ix, mi) #| let mut plo = phi + l #| let phi = h + (if plo < l { 1 } else { 0 }) #| let l = ix * hi #| let mut phi = phi + l #| let mut q : Int = (phi >> 30).reinterpret_as_int() #| phi = phi & 0x3fffffff #| if (phi & 0x2000_0000) != 0 { #| phi = phi - 0x4000_0000 #| q = q + 1 #| } #| let s : UInt = phi & 0x8000_0000 #| if phi >= 0x8000_0000 { #| phi = phi.lnot() #| plo = 0U - plo #| phi += if plo == 0 { 1 } else { 0 } #| } #| exp = 0 #| while phi < 0x8000_0000 { #| phi = (phi << 1) | (plo >> 31) #| plo = plo << 1 #| exp = exp - 1 #| } #| phi = mulh(phi, 0xc90f_daa2) #| if phi < 0x8000_0000 { #| phi = phi << 1 #| exp = exp - 1 #| } #| let mut r = s + #| ((exp + 128) << 23).reinterpret_as_uint() + #| (phi >> 8) + #| (if (phi & 0xff) > 0x7e { 1 } else { 0 }) #| if !xispos { #| r = r ^ 0x8000_0000 #| q = -q #| } #| let r = r.reinterpret_as_float() #| return (r, q) #|} #|fn sinf_poly(x : Float) -> Float { #| let s = x * x #| let mut r = (0x3640_5000).reinterpret_as_float() #| r = r * s - (0x3950_3486).reinterpret_as_float() #| r = r * s + (0x3c08_88c1).reinterpret_as_float() #| r = r * s - (0x3e2a_aaab).reinterpret_as_float() #| let t = x * s #| r = r * t + x #| r #|} #|fn cosf_poly(x : Float) -> Float { #| let s = x * x #| let mut r = (0x37cd_4000).reinterpret_as_float() #| r = r * s - (0x3ab6_077d).reinterpret_as_float() #| r = r * s + (0x3d2a_aaa8).reinterpret_as_float() #| r = r * s - (0x3f00_0000).reinterpret_as_float() #| r = r * s + (0x3f80_0000).reinterpret_as_float() #| r #|} #|fn sin_cos_core(x : Float, q : Int) -> Float { #| let mut r = if (q & 1) != 0 { cosf_poly(x) } else { sinf_poly(x) } #| if (q & 2) != 0 { #| r = -r #| } #| r #|} #|fn tanf_poly(x : Float, odd : Bool) -> Float { #| let x = x.to_double() #| let coef : FixedArray[Double] = [ #| 0.333331395030791399758, // 0x15554d3418c99f.0p-54 */ #| 0.133392002712976742718, // 0x1112fd38999f72.0p-55 */ #| 0.0533812378445670393523, // 0x1b54c91d865afe.0p-57 */ #| 0.0245283181166547278873, // 0x191df3908c33ce.0p-58 */ #| 0.00297435743359967304927, // 0x185dadfcecf44e.0p-61 */ #| 0.00946564784943673166728, // 0x1362b9bf971bcd.0p-59 */ #| ] #| let z = x * x #| let mut r = coef[4] + z * coef[5] #| let t = coef[2] + z * coef[3] #| let w = z * z #| let s = z * x #| let u = coef[0] + z * coef[1] #| r = x + s * u + s * w * (t + w * r) #| (if odd { -1.0 / r } else { r }).to_float() #|} ), }, ) ///| let moonbitlang_core_hashmap_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/hashmap", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/test": moonbitlang_core_test_module, "moonbitlang/core/array": moonbitlang_core_array_module, "moonbitlang/core/tuple": moonbitlang_core_tuple_module, "moonbitlang/core/quickcheck": moonbitlang_core_quickcheck_module, "moonbitlang/core/int": moonbitlang_core_int_module, }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/builtin", #| "moonbitlang/core/test", #| "moonbitlang/core/array", #| "moonbitlang/core/tuple", #| "moonbitlang/core/quickcheck", #| "moonbitlang/core/int" #| ], #| "test-import": ["moonbitlang/core/string", "moonbitlang/core/json"] #|} ), "deprecated.mbt": "", "hashmap.mbt": ( #|pub fn[K, V] new(capacity? : Int = 8) -> T[K, V] { #| let capacity = capacity.next_power_of_two() #| { #| size: 0, #| capacity, #| entries: FixedArray::make(capacity, None), #| capacity_mask: capacity - 1, #| } #|} #|pub fn[K : Hash + Eq, V] from_array(arr : Array[(K, V)]) -> T[K, V] { #| let m = new(capacity=arr.length()) #| arr.each(e => m.set(e.0, e.1)) #| m #|} #|pub fn[K : Hash + Eq, V] set(self : T[K, V], key : K, value : V) -> Unit { #| self.set_with_hash(key, value, key.hash()) #|} #|fn[K : Eq, V] set_with_hash( #| self : T[K, V], #| key : K, #| value : V, #| hash : Int, #|) -> Unit { #| if self.size >= self.capacity / 2 { #| self.grow() #| } #| let (idx, psl) = for psl = 0, idx = hash & self.capacity_mask { #| match self.entries[idx] { #| None => break (idx, psl) #| Some(curr_entry) => { #| if curr_entry.hash == hash && curr_entry.key == key { #| curr_entry.value = value #| return #| } #| if psl > curr_entry.psl { #| self.push_away(idx, curr_entry) #| break (idx, psl) #| } #| continue psl + 1, (idx + 1) & self.capacity_mask #| } #| } #| } #| let entry = { psl, key, value, hash } #| self.entries[idx] = Some(entry) #| self.size += 1 #|} #|fn[K, V] T::push_away(self : T[K, V], idx : Int, entry : Entry[K, V]) -> Unit { #| for psl = entry.psl + 1, idx = (idx + 1) & self.capacity_mask, entry = entry { #| match self.entries[idx] { #| None => { #| entry.psl = psl #| self.entries[idx] = Some(entry) #| break #| } #| Some(curr_entry) => #| if psl > curr_entry.psl { #| entry.psl = psl #| self.entries[idx] = Some(entry) #| continue curr_entry.psl + 1, #| (idx + 1) & self.capacity_mask, #| curr_entry #| } else { #| continue psl + 1, (idx + 1) & self.capacity_mask, entry #| } #| } #| } #|} #|pub fn[K : Hash + Eq, V] op_set(self : T[K, V], key : K, value : V) -> Unit { #| self.set(key, value) #|} #|pub fn[K : Hash + Eq, V] get(self : T[K, V], key : K) -> V? { #| let hash = key.hash() #| for i = 0, idx = hash & self.capacity_mask { #| guard self.entries[idx] is Some(entry) else { break None } #| if entry.hash == hash && entry.key == key { #| break Some(entry.value) #| } #| if i > entry.psl { #| break None #| } #| continue i + 1, (idx + 1) & self.capacity_mask #| } #|} #|pub fn[K : Hash + Eq, V] op_get(self : T[K, V], key : K) -> V { #| let hash = key.hash() #| for i = 0, idx = hash & self.capacity_mask { #| guard self.entries[idx] is Some(entry) #| if entry.hash == hash && entry.key == key { #| break entry.value #| } #| guard entry.psl <= i #| continue i + 1, (idx + 1) & self.capacity_mask #| } #|} #|pub fn[K : Hash + Eq, V] get_or_init( #| self : T[K, V], #| key : K, #| init : () -> V, #|) -> V { #| let hash = key.hash() #| let (idx, psl, new_value, push_away) = for psl = 0, idx = hash & #| self.capacity_mask { #| match self.entries[idx] { #| Some(entry) => { #| if entry.hash == hash && entry.key == key { #| return entry.value #| } #| if psl > entry.psl { #| let new_value = init() #| break (idx, psl, new_value, Some(entry)) #| } #| continue psl + 1, (idx + 1) & self.capacity_mask #| } #| None => { #| let new_value = init() #| break (idx, psl, new_value, None) #| } #| } #| } #| if self.size >= self.capacity / 2 { #| self.grow() #| self.set_with_hash(key, new_value, hash) #| } else { #| if push_away is Some(entry) { #| self.push_away(idx, entry) #| } #| let entry = { psl, hash, key, value: new_value } #| self.entries[idx] = Some(entry) #| self.size += 1 #| } #| new_value #|} #|pub fn[K : Hash + Eq, V] get_or_default( #| self : T[K, V], #| key : K, #| default : V, #|) -> V { #| let hash = key.hash() #| for i = 0, idx = hash & self.capacity_mask { #| guard self.entries[idx] is Some(entry) else { break default } #| if entry.hash == hash && entry.key == key { #| break entry.value #| } #| if i > entry.psl { #| break default #| } #| continue i + 1, (idx + 1) & self.capacity_mask #| } #|} #|pub fn[K : Hash + Eq, V] contains(self : T[K, V], key : K) -> Bool { #| let hash = key.hash() #| for i = 0, idx = hash & self.capacity_mask { #| guard self.entries[idx] is Some(entry) else { return false } #| if entry.hash == hash && entry.key == key { #| return true #| } #| if i > entry.psl { #| return false #| } #| continue i + 1, (idx + 1) & self.capacity_mask #| } #|} #|pub fn[K : Hash + Eq, V : Eq] contains_kv( #| self : T[K, V], #| key : K, #| value : V, #|) -> Bool { #| let hash = key.hash() #| for i = 0, idx = hash & self.capacity_mask { #| guard self.entries[idx] is Some(entry) else { return false } #| if entry.hash == hash && entry.key == key && entry.value == value { #| return true #| } #| if i > entry.psl { #| return false #| } #| continue i + 1, (idx + 1) & self.capacity_mask #| } #|} #|pub fn[K : Hash + Eq, V] remove(self : T[K, V], key : K) -> Unit { #| let hash = key.hash() #| for i = 0, idx = hash & self.capacity_mask { #| match self.entries[idx] { #| Some(entry) => { #| if entry.hash == hash && entry.key == key { #| self.shift_back(idx) #| self.size -= 1 #| break #| } #| if i > entry.psl { #| break #| } #| continue i + 1, (idx + 1) & self.capacity_mask #| } #| None => break #| } #| } #|} #|fn[K, V] shift_back(self : T[K, V], idx : Int) -> Unit { #| let next = (idx + 1) & self.capacity_mask #| match self.entries[next] { #| None | Some({ psl: 0, .. }) => self.entries[idx] = None #| Some(entry) => { #| entry.psl -= 1 #| self.entries[idx] = Some(entry) #| self.shift_back(next) #| } #| } #|} #|fn[K : Eq, V] grow(self : T[K, V]) -> Unit { #| let old_entries = self.entries #| let new_capacity = self.capacity << 1 #| self.entries = FixedArray::make(new_capacity, None) #| self.capacity = new_capacity #| self.capacity_mask = new_capacity - 1 #| self.size = 0 #| for i in 0.. T[K, V] { #| let m = new(capacity=arr.length()) #| arr.each(e => m.set(e.0, e.1)) #| m #|} #|test "of" { #| let m = of([(1, 2), (3, 4)]) #| inspect(m.get(1), content="Some(2)") #| inspect(m.get(3), content="Some(4)") #|} #|pub impl[K : @quickcheck.Arbitrary + Hash + Eq, V : @quickcheck.Arbitrary] @quickcheck.Arbitrary for T[ #| K, #| V, #|] with arbitrary(size, rs) { #| let m = new() #| (@quickcheck.Arbitrary::arbitrary(size, rs) : Iter[(K, V)]).each(kv => m.set( #| kv.0, #| kv.1, #| )) #| m #|} #|pub impl[K, V] Default for T[K, V] with default() { #| new() #|} #|pub fn[K, V, V2] T::map(self : T[K, V], f : (K, V) -> V2) -> T[K, V2] { #| let other = { #| capacity: self.capacity, #| entries: FixedArray::make(self.capacity, None), #| size: self.size, #| capacity_mask: self.capacity_mask, #| } #| if self.size == 0 { #| return other #| } #| for i in 0.. T[K, V] { #| let other = { #| capacity: self.capacity, #| entries: FixedArray::make(self.capacity, None), #| size: self.size, #| capacity_mask: self.capacity_mask, #| } #| if self.size == 0 { #| return other #| } #| for i in 0.. 1), content="1") #| inspect(m.get("a"), content="Some(1)") #| inspect(m.get_or_init("a", () => 2), content="1") #| inspect(m.get("a"), content="Some(1)") #|} ), "json.mbt": ( #|pub impl[K : Show, V : ToJson] ToJson for T[K, V] with to_json(self) { #| let object = Map::new(capacity=self.capacity) #| for k, v in self { #| object[k.to_string()] = v.to_json() #| } #| Json::object(object) #|} ), "types.mbt": ( #|priv struct Entry[K, V] { #| mut psl : Int #| hash : Int #| key : K #| mut value : V #|} derive(Show) #|struct T[K, V] { #| mut entries : FixedArray[Entry[K, V]?] #| mut capacity : Int #| mut capacity_mask : Int // capacity_mask = capacity - 1, used to find idx #| mut size : Int // active key-value pairs count #|} #|pub impl[K : Hash + Eq, V : Eq] Eq for T[K, V] with op_equal( #| self : T[K, V], #| that : T[K, V], #|) -> Bool { #| guard self.size == that.size else { return false } #| for k, v in self { #| guard that.contains_kv(k, v) else { return false } #| } else { #| true #| } #|} ), "utils.mbt": ( #|fn[K : Show, V : Show] debug_entries(self : T[K, V]) -> String { #| for s = "", i = 0; i < self.entries.length(); { #| let s = if i > 0 { s + "," } else { s } #| match self.entries[i] { #| None => continue s + "_", i + 1 #| Some({ psl, key, value, .. }) => #| continue s + "(\{psl},\{key},\{value})", i + 1 #| } #| } else { #| s #| } #|} #|pub fn[K, V] clear(self : T[K, V]) -> Unit { #| self.entries.fill(None) #| self.size = 0 #|} #|pub fn[K, V] iter(self : T[K, V]) -> Iter[(K, V)] { #| Iter::new(yield_ => for entry in self.entries { #| if entry is Some({ key, value, .. }) { #| guard yield_((key, value)) is IterContinue else { break IterEnd } #| } #| } else { #| IterContinue #| }) #|} #|pub fn[K, V] iter2(self : T[K, V]) -> Iter2[K, V] { #| Iter2::new(yield_ => for entry in self.entries { #| if entry is Some({ key, value, .. }) { #| guard yield_(key, value) is IterContinue else { break IterEnd } #| } #| } else { #| IterContinue #| }) #|} #|pub fn[K : Hash + Eq, V] from_iter(iter : Iter[(K, V)]) -> T[K, V] { #| let m = new() #| iter.each(e => m[e.0] = e.1) #| m #|} #|pub fn[K, V] to_array(self : T[K, V]) -> Array[(K, V)] { #| let mut i = 0 #| let res = while i < self.capacity { #| if self.entries[i] is Some({ key, value, .. }) { #| i += 1 #| break Array::make(self.size, (key, value)) #| } #| i += 1 #| } else { #| [] #| } #| if !res.is_empty() { #| let mut res_idx = 1 #| while res_idx < res.length() && i < self.capacity { #| if self.entries[i] is Some({ key, value, .. }) { #| res[res_idx] = (key, value) #| res_idx += 1 #| } #| i += 1 #| } #| } #| res #|} #|pub fn[K, V] size(self : T[K, V]) -> Int { #| self.size #|} #|pub fn[K, V] capacity(self : T[K, V]) -> Int { #| self.capacity #|} #|pub fn[K, V] is_empty(self : T[K, V]) -> Bool { #| self.size == 0 #|} #|#locals(f) #|pub fn[K, V] each(self : T[K, V], f : (K, V) -> Unit raise?) -> Unit raise? { #| for i in 0.. Unit raise?, #|) -> Unit raise? { #| for i = 0, idx = 0; i < self.capacity; { #| match self.entries[i] { #| Some({ key, value, .. }) => { #| f(idx, key, value) #| continue i + 1, idx + 1 #| } #| None => continue i + 1, idx #| } #| } #|} #|pub impl[K : Show, V : Show] Show for T[K, V] with output(self, logger) { #| logger.write_string("HashMap::of([") #| self.eachi((i, k, v) => { #| if i > 0 { #| logger.write_string(", ") #| } #| logger #| ..write_string("(") #| ..write_object(k) #| ..write_string(", ") #| ..write_object(v) #| ..write_string(")") #| }) #| logger.write_string("])") #|} #|pub fn[K, V] T::keys(self : T[K, V]) -> Iter[K] { #| Iter::new(yield_ => for entry in self.entries { #| if entry is Some({ key, .. }) { #| guard yield_(key) is IterContinue else { break IterEnd } #| } #| } else { #| IterContinue #| }) #|} #|pub fn[K, V] T::values(self : T[K, V]) -> Iter[V] { #| Iter::new(yield_ => for entry in self.entries { #| if entry is Some({ value, .. }) { #| guard yield_(value) is IterContinue else { break IterEnd } #| } #| } else { #| IterContinue #| }) #|} ), }, ) ///| let moonbitlang_core_hashset_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/hashset", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/test": moonbitlang_core_test_module, "moonbitlang/core/array": moonbitlang_core_array_module, "moonbitlang/core/quickcheck": moonbitlang_core_quickcheck_module, }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/builtin", #| "moonbitlang/core/test", #| "moonbitlang/core/array", #| "moonbitlang/core/quickcheck" #| ], #| "test-import": [ #| "moonbitlang/core/string", #| "moonbitlang/core/int", #| "moonbitlang/core/json" #| ] #|} ), "deprecated.mbt": ( #|#deprecated("Use `add` instead.") #|#coverage.skip #|pub fn[K : Hash + Eq] insert(self : T[K], key : K) -> Unit { #| self.add(key) #|} ), "hashset.mbt": ( #|let default_init_capacity = 8 #|pub fn[K] T::new(capacity? : Int = default_init_capacity) -> T[K] { #| { #| size: 0, #| capacity, #| capacity_mask: capacity - 1, #| grow_at: calc_grow_threshold(capacity), #| entries: FixedArray::make(capacity, None), #| } #|} #|pub fn[K : Hash + Eq] T::from_array(arr : Array[K]) -> T[K] { #| let m = new() #| arr.each(e => m.add(e)) #| m #|} #|pub fn[K : Hash + Eq] T::of(arr : FixedArray[K]) -> T[K] { #| let m = new() #| arr.each(e => m.add(e)) #| m #|} #|pub fn[K : Hash + Eq] add(self : T[K], key : K) -> Unit { #| self.add_with_hash(key, key.hash()) #|} #|fn[K : Eq] add_with_hash(self : T[K], key : K, hash : Int) -> Unit { #| if self.size >= self.grow_at { #| self.grow() #| } #| let (idx, psl) = for psl = 0, idx = abs(hash) & self.capacity_mask { #| match self.entries[idx] { #| None => break (idx, psl) #| Some(curr_entry) => { #| if curr_entry.hash == hash && curr_entry.key == key { #| return #| } #| if psl > curr_entry.psl { #| self.push_away(idx, curr_entry) #| break (idx, psl) #| } #| continue psl + 1, (idx + 1) & self.capacity_mask #| } #| } #| } #| let entry = { psl, key, hash } #| self.set_entry(entry, idx) #| self.size += 1 #|} #|fn[K] push_away(self : T[K], idx : Int, entry : Entry[K]) -> Unit { #| for psl = entry.psl + 1, idx = (idx + 1) & self.capacity_mask, entry = entry { #| match self.entries[idx] { #| None => { #| entry.psl = psl #| self.set_entry(entry, idx) #| break #| } #| Some(curr_entry) => #| if psl > curr_entry.psl { #| entry.psl = psl #| self.set_entry(entry, idx) #| continue curr_entry.psl + 1, #| (idx + 1) & self.capacity_mask, #| curr_entry #| } else { #| continue psl + 1, (idx + 1) & self.capacity_mask, entry #| } #| } #| } #|} #|#inline #|fn[K] set_entry(self : T[K], entry : Entry[K], new_idx : Int) -> Unit { #| self.entries[new_idx] = Some(entry) #|} #|pub fn[K : Hash + Eq] contains(self : T[K], key : K) -> Bool { #| let hash = key.hash() #| for i = 0, idx = abs(hash) & self.capacity_mask { #| guard self.entries[idx] is Some(entry) else { break false } #| if entry.hash == hash && entry.key == key { #| break true #| } #| if i > entry.psl { #| break false #| } #| continue i + 1, (idx + 1) & self.capacity_mask #| } #|} #|pub fn[K : Hash + Eq] remove(self : T[K], key : K) -> Unit { #| let hash = key.hash() #| for i = 0, idx = abs(hash) & self.capacity_mask { #| guard self.entries[idx] is Some(entry) else { break } #| if entry.hash == hash && entry.key == key { #| self.shift_back(idx) #| self.size -= 1 #| break #| } #| if i > entry.psl { #| break #| } #| continue i + 1, (idx + 1) & self.capacity_mask #| } #|} #|fn[K] shift_back(self : T[K], idx : Int) -> Unit { #| let next = (idx + 1) & self.capacity_mask #| match self.entries[next] { #| None | Some({ psl: 0, .. }) => self.entries[idx] = None #| Some(entry) => { #| entry.psl -= 1 #| self.set_entry(entry, idx) #| self.shift_back(next) #| } #| } #|} #|fn[K : Eq] grow(self : T[K]) -> Unit { #| if self.capacity == 0 { #| self.capacity = default_init_capacity #| self.capacity_mask = self.capacity - 1 #| self.grow_at = calc_grow_threshold(self.capacity) #| self.size = 0 #| self.entries = FixedArray::make(self.capacity, None) #| return #| } #| let old_entries = self.entries #| self.entries = FixedArray::make(self.capacity * 2, None) #| self.capacity = self.capacity * 2 #| self.capacity_mask = self.capacity - 1 #| self.grow_at = calc_grow_threshold(self.capacity) #| self.size = 0 #| for i in 0.. Int { #| self.size #|} #|pub fn[K] capacity(self : T[K]) -> Int { #| self.capacity #|} #|pub fn[K] is_empty(self : T[K]) -> Bool { #| self.size == 0 #|} #|#locals(f) #|pub fn[K] each(self : T[K], f : (K) -> Unit raise?) -> Unit raise? { #| for entry in self.entries { #| if entry is Some({ key, .. }) { #| f(key) #| } #| } #|} #|#locals(f) #|pub fn[K] eachi(self : T[K], f : (Int, K) -> Unit raise?) -> Unit raise? { #| let mut idx = 0 #| for i in 0.. Unit { #| self.entries.fill(None) #| self.size = 0 #|} #|pub fn[K] iter(self : T[K]) -> Iter[K] { #| Iter::new(yield_ => for entry in self.entries { #| if entry is Some({ key, .. }) { #| guard yield_(key) is IterContinue else { break IterEnd } #| } #| } else { #| IterContinue #| }) #|} #|pub fn[K] to_array(self : T[K]) -> Array[K] { #| let arr = Array::new(capacity=self.size) #| for entry in self.entries { #| if entry is Some({ key, .. }) { #| arr.push(key) #| } #| } #| arr #|} #|pub fn[K : Hash + Eq] T::from_iter(iter : Iter[K]) -> T[K] { #| let s = new() #| iter.each(e => s.add(e)) #| s #|} #|pub fn[K : Hash + Eq] union(self : T[K], other : T[K]) -> T[K] { #| let m = new() #| self.each(k => m.add(k)) #| other.each(k => m.add(k)) #| m #|} #|pub fn[K : Hash + Eq] intersection(self : T[K], other : T[K]) -> T[K] { #| let m = new() #| self.each(k => if other.contains(k) { m.add(k) }) #| m #|} #|pub fn[K : Hash + Eq] difference(self : T[K], other : T[K]) -> T[K] { #| let m = new() #| self.each(k => if !other.contains(k) { m.add(k) }) #| m #|} #|pub fn[K : Hash + Eq] symmetric_difference(self : T[K], other : T[K]) -> T[K] { #| let m = new() #| self.each(k => if !other.contains(k) { m.add(k) }) #| other.each(k => if !self.contains(k) { m.add(k) }) #| m #|} #|pub fn[K : Hash + Eq] is_disjoint(self : T[K], other : T[K]) -> Bool { #| if self.size() <= other.size() { #| self.iter().all(k => !other.contains(k)) #| } else { #| other.iter().all(k => !self.contains(k)) #| } #|} #|pub fn[K : Hash + Eq] is_subset(self : T[K], other : T[K]) -> Bool { #| if self.size() <= other.size() { #| self.iter().all(k => other.contains(k)) #| } else { #| false #| } #|} #|pub fn[K : Hash + Eq] is_superset(self : T[K], other : T[K]) -> Bool { #| other.is_subset(self) #|} #|pub impl[K : Hash + Eq] BitAnd for T[K] with land(self, other) { #| self.intersection(other) #|} #|pub impl[K : Hash + Eq] BitOr for T[K] with lor(self, other) { #| self.union(other) #|} #|pub impl[K : Hash + Eq] BitXOr for T[K] with lxor(self, other) { #| self.symmetric_difference(other) #|} #|pub impl[K : Hash + Eq] Sub for T[K] with op_sub(self, other) { #| self.difference(other) #|} #|pub impl[X : @quickcheck.Arbitrary + Eq + Hash] @quickcheck.Arbitrary for T[X] with arbitrary( #| size, #| rs, #|) { #| @quickcheck.Arbitrary::arbitrary(size, rs) |> from_iter #|} #|fn abs(n : Int) -> Int { #| if n < 0 { #| -n #| } else { #| n #| } #|} #|fn calc_grow_threshold(capacity : Int) -> Int { #| capacity * 13 / 16 #|} #|fn[K : Show] debug_entries(self : T[K]) -> String { #| let mut s = "" #| for i in 0.. 0 { #| s += "," #| } #| match self.entries[i] { #| None => s += "_" #| Some({ psl, key, .. }) => s += "(\{psl},\{key})" #| } #| } #| s #|} #|priv struct MyString(String) derive(Eq) #|impl Hash for MyString with hash(self) { #| let MyString(self) = self #| self.length() #|} #|impl Hash for MyString with hash_combine(self, hasher) { #| let MyString(self) = self #| hasher.combine_string(self) #|} #|impl Show for MyString with output(self, logger) { #| let MyString(self) = self #| logger.write_string(self) #|} #|test "set" { #| let m : T[MyString] = new() #| m.add("a") #| m.add("b") #| m.add("bc") #| m.add("abc") #| m.add("cd") #| m.add("c") #| m.add("d") #| inspect(m.size, content="7") #| assert_eq( #| m.debug_entries(), #| "_,(0,a),(1,b),(2,c),(3,d),(3,bc),(4,cd),(4,abc),_,_,_,_,_,_,_,_", #| ) #|} #|test "remove" { #| let m : T[MyString] = new() #| fn i(s) { #| MyString::MyString(s) #| } #| m.add("a" |> i) #| m.add("ab" |> i) #| m.add("bc" |> i) #| m.add("cd" |> i) #| m.add("abc" |> i) #| m.add("abcdef" |> i) #| m.remove("ab" |> i) #| inspect(m.size(), content="5") #| inspect( #| m.debug_entries(), #| content="_,(0,a),(0,bc),(1,cd),(1,abc),_,(0,abcdef),_", #| ) #|} #|test "remove_unexist_key" { #| let m : T[MyString] = new() #| fn i(s) { #| MyString::MyString(s) #| } #| m.add("a" |> i) #| m.add("ab" |> i) #| m.add("abc" |> i) #| m.remove("d" |> i) #| inspect(m.size(), content="3") #| inspect(m.debug_entries(), content="_,(0,a),(0,ab),(0,abc),_,_,_,_") #|} #|test "grow" { #| let m : T[MyString] = new() #| fn i(s) { #| MyString::MyString(s) #| } #| m.add("C" |> i) #| m.add("Go" |> i) #| m.add("C++" |> i) #| m.add("Java" |> i) #| m.add("Scala" |> i) #| m.add("Julia" |> i) #| inspect(m.size, content="6") #| inspect(m.capacity, content="8") #| m.add("Cobol" |> i) #| inspect(m.size, content="7") #| inspect(m.capacity, content="16") #| m.add("Python" |> i) #| m.add("Haskell" |> i) #| m.add("Rescript" |> i) #| inspect(m.size, content="10") #| inspect(m.capacity, content="16") #| assert_eq( #| m.debug_entries(), #| "_,(0,C),(0,Go),(0,C++),(0,Java),(0,Scala),(1,Julia),(2,Cobol),(2,Python),(2,Haskell),(2,Rescript),_,_,_,_,_", #| ) #|} #|test "clear" { #| let m : T[MyString] = new() #| m.clear() #| inspect(m.size(), content="0") #| inspect(m.capacity(), content="8") #| for i in 0.. Bool { #| let old_size = self.size #| self.add(key) #| self.size > old_size #|} #|pub fn[K : Hash + Eq] remove_and_check(self : T[K], key : K) -> Bool { #| let old_size = self.size #| self.remove(key) #| self.size < old_size #|} #|pub fn[K] copy(self : T[K]) -> T[K] { #| let other = { #| capacity: self.capacity, #| entries: FixedArray::make(self.capacity, None), #| size: self.size, #| capacity_mask: self.capacity_mask, #| grow_at: self.grow_at, #| } #| for i in 0.. T[A] { #| { tree: Tree::empty(), size: 0, shift: 0 } #|} #|pub fn[A] make(len : Int, value : A) -> T[A] { #| let quot = len / branching_factor #| let rem = len % branching_factor #| let leaves = if rem == 0 { #| Array::make(quot, FixedArray::make(branching_factor, value)) #| } else { #| let arr : Array[FixedArray[A]] = Array::make( #| quot + 1, #| FixedArray::make(branching_factor, value), #| ) #| arr[quot] = FixedArray::make(rem, value) #| arr #| } #| let size = len #| let (shift, cap) = shift_cap_of_size(size) #| let tree = if size == 0 { Empty } else { from_leaves(leaves[:], cap) } #| { shift, tree, size } #|} #|pub fn[A] makei(len : Int, f : (Int) -> A raise?) -> T[A] raise? { #| let quot = len / branching_factor #| let rem = len % branching_factor #| let leaves = if rem == 0 { #| Array::makei(quot, k => FixedArray::makei(branching_factor, i => f( #| k * branching_factor + i, #| ))) #| } else { #| let arr : Array[FixedArray[A]] = Array::make(quot + 1, []) #| for k in 0.. f( #| k * branching_factor + i, #| )) #| } #| arr[quot] = FixedArray::makei(rem, i => f(quot * branching_factor + i)) #| arr #| } #| let size = len #| let (shift, cap) = shift_cap_of_size(size) #| let tree = if size == 0 { Empty } else { from_leaves(leaves[:], cap) } #| { shift, tree, size } #|} #|pub fn[A] of(arr : FixedArray[A]) -> T[A] { #| makei(arr.length(), i => arr[i]) #|} #|#deprecated("We don't copy immutable array") #|#coverage.skip #|pub fn[A] copy(self : T[A]) -> T[A] { #| fn copy(t : Tree[A]) -> Tree[A] { #| match t { #| Leaf(l) => Leaf(l.copy()) #| Empty => Empty #| Node(node, sizes) => #| Node( #| FixedArray::makei(node.length(), i => copy(node[i])), #| match sizes { #| Some(sizes) => Some(FixedArray::copy(sizes)) #| None => None #| }, #| ) #| } #| } #| { tree: copy(self.tree), size: self.size, shift: self.shift } #|} #|pub fn[A] from_array(arr : Array[A]) -> T[A] { #| makei(arr.length(), i => arr[i]) #|} #|pub fn[A] from_iter(iter : Iter[A]) -> T[A] { #| let mut buf : FixedArray[A] = [] #| let mut index = 0 #| let leaves = [] #| iter.each(x => if index == 0 { #| buf = FixedArray::make(branching_factor, x) #| index += 1 #| } else if index < branching_factor { #| buf[index] = x #| index += 1 #| } else { #| leaves.push(buf) #| index = 1 #| buf = FixedArray::make(branching_factor, x) #| }) #| if index == branching_factor { #| leaves.push(buf) #| } else if index > 0 { #| let res = FixedArray::make(index, buf[0]) #| buf.blit_to(res, len=index) #| leaves.push(res) #| } #| let size = leaves.fold(init=0, (acc, xs) => acc + xs.length()) #| let (shift, cap) = shift_cap_of_size(size) #| let tree = if size == 0 { Empty } else { from_leaves(leaves[:], cap) } #| { shift, tree, size } #|} #|pub fn[A] to_array(self : T[A]) -> Array[A] { #| if self.is_empty() { #| [] #| } else { #| let arr = Array::make(self.length(), self[0]) #| self.eachi((i, v) => arr[i] = v) #| arr #| } #|} #|pub fn[A] is_empty(self : T[A]) -> Bool { #| self.size == 0 #|} #|pub fn[A] length(self : T[A]) -> Int { #| self.size #|} #|pub fn[A] op_get(self : T[A], index : Int) -> A { #| if index == 0 { #| self.tree.get_first() #| } else if index == self.size - 1 { #| self.tree.get_last() #| } else { #| self.tree.get(index, self.shift) #| } #|} #|pub fn[A] get(self : T[A], index : Int) -> A? { #| guard 0 <= index && index < self.size else { None } #| Some(self[index]) #|} #|pub fn[A] set(self : T[A], index : Int, value : A) -> T[A] { #| { #| tree: self.tree.set(index, self.shift, value), #| size: self.size, #| shift: self.shift, #| } #|} #|pub fn[A] push(self : T[A], value : A) -> T[A] { #| let (tree, shift) = self.tree.push_end(self.shift, value) #| { tree, size: self.size + 1, shift } #|} #|pub fn[A] concat(self : T[A], other : T[A]) -> T[A] { #| if self.is_empty() { #| return other #| } #| if other.is_empty() { #| return self #| } #| let (tree, shift) = Tree::concat( #| self.tree, #| self.shift, #| other.tree, #| other.shift, #| true, #| ) #| { tree, size: self.size + other.size, shift } #|} #|pub impl[A] Add for T[A] with op_add(self, other) { #| self.concat(other) #|} #|pub fn[A] iter(self : T[A]) -> Iter[A] { #| self.tree.iter() #|} #|pub fn[A] each(self : T[A], f : (A) -> Unit raise?) -> Unit raise? { #| self.tree.each(f) #|} #|pub fn[A] eachi(self : T[A], f : (Int, A) -> Unit raise?) -> Unit raise? { #| self.tree.eachi(f, self.shift, 0) #|} #|pub fn[A, B] fold(self : T[A], init~ : B, f : (B, A) -> B raise?) -> B raise? { #| self.tree.fold(init, f) #|} #|pub fn[A, B] rev_fold( #| self : T[A], #| init~ : B, #| f : (B, A) -> B raise?, #|) -> B raise? { #| self.tree.rev_fold(init, f) #|} #|#deprecated("Use `fold` instead") #|#coverage.skip #|pub fn[A] fold_left(self : T[A], f : (A, A) -> A raise?, init~ : A) -> A raise? { #| self.fold(init~, f) #|} #|#deprecated("Use `rev_fold` instead") #|#coverage.skip #|pub fn[A] fold_right( #| self : T[A], #| f : (A, A) -> A raise?, #| init~ : A, #|) -> A raise? { #| self.rev_fold(init~, f) #|} #|pub fn[A, B] map(self : T[A], f : (A) -> B raise?) -> T[B] raise? { #| { tree: self.tree.map(f), size: self.size, shift: self.shift } #|} #|pub impl[X : @quickcheck.Arbitrary] @quickcheck.Arbitrary for T[X] with arbitrary( #| size, #| rs, #|) { #| @quickcheck.Arbitrary::arbitrary(size, rs) |> from_array #|} #|pub impl[A : Hash] Hash for T[A] with hash_combine(self, hasher) { #| for e in self { #| hasher.combine(e) #| } #|} #|pub impl[A : Eq] Eq for T[A] with op_equal(self, other) { #| self.size == other.size && self.tree == other.tree #|} #|pub impl[A : Show] Show for T[A] with output(self, logger) { #| logger.write_iter(self.iter(), prefix="@immut/array.of([", suffix="])") #|} #|pub impl[A : Compare] Compare for T[A] with compare(self, other) { #| let len_self = self.length() #| let len_other = other.length() #| let cmp = len_self.compare(len_other) #| guard cmp is 0 else { return cmp } #| for i in 0.. Tree[A] { #| if cap == branching_factor { #| Leaf(leaves[0]) #| } else if leaves.length() <= branching_factor { #| let arr = FixedArray::make(leaves.length(), Empty) #| for i in 0.. from_leaves( #| leaves[i * times:(i + 1) * times], #| child_cap, #| )) #| } else { #| let arr = FixedArray::make(quot + 1, Tree::Empty) #| for i in 0.. (Int, Int) { #| let mut cap = branching_factor #| let mut depth = 0 #| while cap < size { #| cap *= branching_factor #| depth += 1 #| } #| let shift = num_bits * depth #| (shift, cap) #|} ), "deprecated.mbt": ( #|#deprecated("use `@immut/array.new` instead") #|#coverage.skip #|pub fn[A] T::new() -> T[A] { #| new() #|} #|#deprecated("use `@immut/array.from_iter` instead") #|#coverage.skip #|pub fn[A] T::from_iter(iter : Iter[A]) -> T[A] { #| from_iter(iter) #|} #|#deprecated("use `@immut/array.from_array` instead") #|#coverage.skip #|pub fn[A] T::from_array(arr : Array[A]) -> T[A] { #| from_array(arr) #|} #|#deprecated("use `@immut/array.make` instead") #|#coverage.skip #|pub fn[A] T::make(len : Int, value : A) -> T[A] { #| make(len, value) #|} #|#deprecated("use `@immut/array.makei` instead") #|#coverage.skip #|pub fn[A] T::makei(len : Int, f : (Int) -> A) -> T[A] { #| makei(len, f) #|} #|#deprecated("use `@immut/array.of` instead") #|#coverage.skip #|pub fn[A] T::of(arr : FixedArray[A]) -> T[A] { #| of(arr) #|} ), "tree.mbt": ( #|let num_bits = 5 #|let branching_factor : Int = 1 << num_bits #|let bitmask : Int = branching_factor - 1 #|const LINEAR_THRESHOLD : Int = 4 #|const E_MAX : Int = 2 #|let e_max_2 : Int = E_MAX / 2 #|fn[T] Tree::empty() -> Tree[T] { #| Tree::Empty #|} #|fn[T] new_branch_left(leaf : FixedArray[T], shift : Int) -> Tree[T] { #| match shift { #| 0 => Leaf(leaf) #| s => Node([new_branch_left(leaf, s - num_bits)], None) // size is None because we can use radix indexing #| } #|} #|fn[T] Tree::get_first(self : Tree[T]) -> T { #| match self { #| Leaf(leaf) => leaf[0] #| Node(node, _) => node[0].get_first() #| Empty => abort("Index out of bounds") #| } #|} #|fn[T] Tree::get_last(self : Tree[T]) -> T { #| match self { #| Leaf(leaf) => leaf[leaf.length() - 1] #| Node(node, _) => node[node.length() - 1].get_last() #| Empty => abort("Index out of bounds") #| } #|} #|fn[T] Tree::get(self : Tree[T], index : Int, shift : Int) -> T { #| fn get_radix(node : Tree[T], shift : Int) -> T { #| match node { #| Leaf(leaf) => leaf[index & bitmask] #| Node(node, None) => #| get_radix(node[radix_indexing(index, shift)], shift - num_bits) #| Node(_, Some(_)) => #| abort("Unreachable: Node should not have sizes in get_radix") #| Empty => abort("Index out of bounds") #| } #| } #| match self { #| Leaf(leaf) => leaf[index] #| Node(children, Some(sizes)) => { #| let branch_index = get_branch_index(sizes, index) #| let sub_index = if branch_index == 0 { #| index #| } else { #| index - sizes[branch_index - 1] #| } #| children[branch_index].get(sub_index, shift - num_bits) #| } #| Node(_, None) => get_radix(self, shift) #| Empty => abort("Index out of bounds") #| } #|} #|fn[T] Tree::set(self : Tree[T], index : Int, shift : Int, value : T) -> Tree[T] { #| fn set_radix(node : Tree[T], shift : Int) -> Tree[T] { #| match node { #| Leaf(leaf) => Leaf(immutable_set(leaf, index & bitmask, value)) #| Node(node, None) => { #| let sub_idx = radix_indexing(index, shift) #| Node( #| immutable_set( #| node, #| sub_idx, #| set_radix(node[radix_indexing(index, shift)], shift - num_bits), #| ), #| None, #| ) #| } #| Node(_, Some(_)) => #| abort("Unreachable: Node should not have sizes in set_radix") #| Empty => abort("Index out of bounds") #| } #| } #| match self { #| Leaf(leaf) => Leaf(immutable_set(leaf, index & bitmask, value)) #| Node(children, Some(sizes)) => { #| let branch_index = get_branch_index(sizes, index) #| let sub_index = if branch_index == 0 { #| index #| } else { #| index - sizes[branch_index - 1] #| } #| Node( #| immutable_set( #| children, #| branch_index, #| children[branch_index].set(sub_index, shift - num_bits, value), #| ), #| Some(sizes), #| ) #| } #| Node(_children, None) => set_radix(self, shift) #| Empty => abort("Index out of bounds") #| } #|} #|fn[T] Tree::push_end(self : Tree[T], shift : Int, value : T) -> (Tree[T], Int) { #| fn update_sizes_last(sizes : FixedArray[Int]?) -> FixedArray[Int]? { #| match sizes { #| Some(sizes) => { #| let new_sizes = sizes.copy() #| new_sizes[new_sizes.length() - 1] += 1 #| Some(new_sizes) #| } #| None => None #| } #| } #| fn push_sizes_last(sizes : FixedArray[Int]?) -> FixedArray[Int]? { #| match sizes { #| Some(sizes) => Some(immutable_push(sizes, 1 + sizes[sizes.length() - 1])) #| None => None #| } #| } #| fn worker(node : Tree[T], shift : Int) -> Tree[T]? { #| match node { #| Leaf(leaf) => { #| if shift != 0 { #| abort( #| "Unreachable: Leaf should not have a non-zero shift, which means we have not reached the bottom of the tree", #| ) #| } #| if leaf.length() < branching_factor { #| Some(Leaf(immutable_push(leaf, value))) #| } else { #| None #| } #| } #| Node(nodes, sizes) => { #| let len = nodes.length() #| match worker(nodes[len - 1], shift - num_bits) { #| Some(new_node) => { #| let new_nodes = nodes.copy() #| new_nodes[len - 1] = new_node #| let sizes = update_sizes_last(sizes) #| Some(Node(new_nodes, sizes)) #| } #| None => #| if len < branching_factor { #| let sizes = push_sizes_last(sizes) #| Some( #| Node( #| immutable_push( #| nodes, #| new_branch_left([value], shift - num_bits), #| ), #| sizes, #| ), #| ) #| } else { #| None #| } #| } #| } #| Empty => Some(Leaf([value])) #| } #| } #| match worker(self, shift) { #| Some(new_tree) => (new_tree, shift) #| None => { #| let new_branch = new_branch_left([value], shift) #| ( #| match self { #| Leaf(_leaf) => Node([self, new_branch], None) #| Node(_nodes, Some(sizes)) => { #| let len = sizes[sizes.length() - 1] #| let sizes = FixedArray::from_array([len, 1 + len]) #| Node([self, new_branch], Some(sizes)) #| } #| Node(_nodes, None) => Node([self, new_branch], None) #| Empty => #| abort( #| "Unreachable: Empty tree should have fallen into the Some(new_tree) branch", #| ) #| }, #| shift + num_bits, #| ) #| } #| } #|} #|fn[A] Tree::each(self : Tree[A], f : (A) -> Unit raise?) -> Unit raise? { #| match self { #| Empty => () #| Leaf(l) => l.each(f) #| Node(ns, _) => ns.each(t => t.each(f)) #| } #|} #|fn[A] Tree::iter(self : Tree[A]) -> Iter[A] { #| Iter::new(yield_ => match self { #| Empty => IterContinue #| Leaf(l) => l.iter().run(yield_) #| Node(ns, _) => #| for n in ns { #| guard n.iter().run(yield_) is IterContinue else { break IterEnd } #| } else { #| IterContinue #| } #| }) #|} #|fn[A] Tree::eachi( #| self : Tree[A], #| f : (Int, A) -> Unit raise?, #| shift : Int, #| start : Int, #|) -> Unit raise? { #| match self { #| Empty => () #| Leaf(l) => #| for i in 0.. { #| let child_shift = shift - num_bits #| let mut start = start #| for i in 0.. { #| let child_shift = shift - num_bits #| let mut start = start #| for i in 0.. B raise?, #|) -> B raise? { #| match self { #| Empty => acc #| Leaf(l) => l.fold(f, init=acc) #| Node(n, _) => n.fold((acc, t) => t.fold(acc, f), init=acc) #| } #|} #|fn[A, B] Tree::rev_fold( #| self : Tree[A], #| acc : B, #| f : (B, A) -> B raise?, #|) -> B raise? { #| match self { #| Empty => acc #| Leaf(l) => l.rev_fold(f, init=acc) #| Node(n, _) => n.rev_fold((acc, t) => t.rev_fold(acc, f), init=acc) #| } #|} #|fn[A, B] Tree::map(self : Tree[A], f : (A) -> B raise?) -> Tree[B] raise? { #| match self { #| Empty => Empty #| Leaf(l) => Leaf(l.map(f)) #| Node(n, szs) => #| Node(FixedArray::makei(n.length(), i => n[i].map(f)), copy_sizes(szs)) #| } #|} #|fn[A] Tree::concat( #| left : Tree[A], #| left_shift : Int, #| right : Tree[A], #| right_shift : Int, #| top : Bool, #|) -> (Tree[A], Int) { #| if left_shift > right_shift { #| let (c, c_shift) = Tree::concat( #| left.right_child(), #| left_shift - num_bits, #| right, #| right_shift, #| false, #| ) #| guard c_shift == left_shift #| return rebalance(left, c, Empty, left_shift, top) #| } else if right_shift > left_shift { #| let (c, c_shift) = Tree::concat( #| left, #| left_shift, #| right.left_child(), #| right_shift - num_bits, #| false, #| ) #| guard c_shift == right_shift #| return rebalance(Empty, c, right, right_shift, top) #| } else if left_shift == 0 { #| let left_elems = left.leaf_elements() #| let right_elems = right.leaf_elements() #| let left_len = left_elems.length() #| let right_len = right_elems.length() #| let len = left_len + right_len #| if top && len <= branching_factor { #| return ( #| Leaf( #| FixedArray::makei(len, (i : Int) => if i < left_len { #| left_elems[i] #| } else { #| right_elems[i - left_len] #| }), #| ), #| 0, #| ) #| } else { #| return ( #| Node( #| FixedArray::from_array([left, right]), #| Some(FixedArray::from_array([left_len, len])), #| ), #| num_bits, #| ) #| } #| } else { #| let (c, c_shift) = Tree::concat( #| left.right_child(), #| left_shift - num_bits, #| right.left_child(), #| right_shift - num_bits, #| false, #| ) #| guard c_shift == left_shift #| guard c_shift == right_shift #| return rebalance(left, c, right, left_shift, top) #| } #|} #|fn[A] rebalance( #| left : Tree[A], #| center : Tree[A], #| right : Tree[A], #| shift : Int, #| top : Bool, #|) -> (Tree[A], Int) { #| let t = tri_merge(left, center, right) // t is a list of trees of (H-1) height #| let (nc, nc_len) = redis_plan(t) #| let new_t = redis(t, nc, nc_len, shift - num_bits) // new_t is a list of trees of (H-1) height #| guard new_t.length() == nc_len #| if nc_len <= branching_factor { #| let node = Node(new_t, compute_sizes(new_t, shift - num_bits)) // node of H height #| if !top { #| return (Node(FixedArray::from_array([node]), None), shift + num_bits) #| } else { #| return (node, shift) #| } #| } else { #| let new_child_1 = FixedArray::makei(branching_factor, i => new_t[i]) #| let new_child_2 = FixedArray::makei(new_t.length() - branching_factor, i => new_t[i + #| branching_factor]) #| let new_node_1 = Node( #| new_child_1, #| compute_sizes(new_child_1, shift - num_bits), #| ) // height H #| let new_node_2 = Node( #| new_child_2, #| compute_sizes(new_child_2, shift - num_bits), #| ) // height H #| let new_children = FixedArray::from_array([new_node_1, new_node_2]) #| return ( #| Node(new_children, compute_sizes(new_children, shift)), #| shift + num_bits, #| ) // return (H+1) height node #| } #|} #|fn[A] tri_merge( #| left : Tree[A], #| center : Tree[A], #| right : Tree[A], #|) -> FixedArray[Tree[A]] { #| if left.is_leaf() || !center.is_node() || right.is_leaf() { #| abort("Unreachable: input to merge is invalid") #| } #| fn get_children(self : Tree[A]) -> FixedArray[Tree[A]] { #| match self { #| Node(children, _) => children #| Empty => [] #| Leaf(_) => abort("Unreachable") #| } #| } #| let left_children = get_children(left) #| let center_children = get_children(center) #| let right_children = get_children(right) #| let left_len = left_children.length() #| let left_len = if left_len == 0 { 0 } else { left_len - 1 } #| let center_len = center_children.length() #| let right_len = right_children.length() #| let right_len = if right_len == 0 { 0 } else { right_len - 1 } #| FixedArray::makei(left_len + center_len + right_len, i => if i < left_len { #| left_children[i] #| } else if i < left_len + center_len { #| center_children[i - left_len] #| } else if right_len > 0 { #| right_children[1 + i - left_len - center_len] #| } else { #| abort("Unreachable") #| }) #|} #|fn[A] redis_plan(t : FixedArray[Tree[A]]) -> (FixedArray[Int], Int) { #| let node_counts = FixedArray::makei(t.length(), i => t[i].local_size()) #| let total_nodes = node_counts.fold(init=0, (acc, x) => acc + x) #| let opt_len = (total_nodes + branching_factor - 1) / branching_factor #| let mut new_len = t.length() #| let mut i = 0 #| while opt_len + e_max_2 < new_len { #| while node_counts[i] > branching_factor - e_max_2 { #| i += 1 #| } #| let mut remaining_nodes = node_counts[i] #| while remaining_nodes > 0 { #| let min_size = min(remaining_nodes + node_counts[i + 1], branching_factor) #| node_counts[i] = min_size #| remaining_nodes = remaining_nodes + node_counts[i + 1] - min_size #| i += 1 #| } #| for j in i..<(new_len - 1) { #| node_counts[j] = node_counts[j + 1] #| } #| new_len -= 1 #| i -= 1 #| } #| return (node_counts, new_len) #|} #|fn[A] redis( #| old_t : FixedArray[Tree[A]], #| node_counts : FixedArray[Int], #| node_nums : Int, #| shift : Int, #|) -> FixedArray[Tree[A]] { #| let old_len = old_t.length() #| let new_t = FixedArray::make(node_nums, Empty) #| let mut old_offset = 0 #| let mut j = 0 // the index of in the old tree #| if shift == 0 { #| let mut old_leaf_elems = FixedArray::default() #| let mut old_leaf_len = 0 #| for i in 0.. FixedArray[Int]? { #| let len = children.length() #| let sizes = FixedArray::make(len, 0) #| let mut sum = 0 #| let mut flag = true #| let full_subtree_size = branching_factor << shift #| for i in 0.. String { #| String::make(indent, ' ') + s #| } #| fn aux(t : Tree[A], ident : Int) { #| match t { #| Empty => indent_str("Empty", ident) #| Leaf(l) => { #| let mut s = "Leaf(" #| for i in 0.. { #| let mut s = indent_str("Node(", ident) + "\n" #| for i in 0.. Bool { #| self is Node(_, _) #|} #|fn[A] Tree::is_leaf(self : Tree[A]) -> Bool { #| self is Leaf(_) #|} #|fn[A] Tree::right_child(self : Tree[A]) -> Tree[A] { #| match self { #| Node(children, _) => children[children.length() - 1] #| Leaf(_) | Empty => abort("Should not get children on non-`Node`s") #| } #|} #|fn[A] Tree::left_child(self : Tree[A]) -> Tree[A] { #| match self { #| Node(children, _) => children[0] #| Leaf(_) | Empty => abort("Should not get children on non-`Node`s") #| } #|} #|fn[A] Tree::leaf_elements(self : Tree[A]) -> FixedArray[A] { #| guard self is Leaf(children) else { #| abort("Should not call `get_leaf_elements` on non-leaf nodes") #| } #| children #|} #|fn[A] Tree::node_children(self : Tree[A]) -> FixedArray[Tree[A]] { #| guard self is Node(children, _) else { #| abort("Should not call `node_children` on non-`Node`s") #| } #| children #|} #|fn[A] Tree::local_size(self : Tree[A]) -> Int { #| match self { #| Empty => 0 #| Leaf(l) => l.length() #| Node(children, _) => children.length() #| } #|} #|fn[A] Tree::size(self : Tree[A], shift : Int) -> Int { #| match self { #| Empty => 0 #| Leaf(l) => l.length() #| Node(_, Some(sizes)) => sizes[sizes.length() - 1] #| Node(children, None) => { #| let len_1 = children.length() - 1 #| (len_1 << shift) + children[len_1].size(shift - num_bits) #| } #| } #|} ), "types.mbt": ( #|struct T[A] { #| tree : Tree[A] #| size : Int #| shift : Int #|} #|priv enum Tree[A] { #| Empty #| Node(FixedArray[Tree[A]], FixedArray[Int]?) // (Subtrees, Sizes of subtrees) #| Leaf(FixedArray[A]) #|} derive(Eq) ), "utils.mbt": ( #|fn[T] immutable_set(arr : FixedArray[T], i : Int, v : T) -> FixedArray[T] { #| let arr = arr.copy() #| arr[i] = v #| arr #|} #|fn[T] immutable_push(arr : FixedArray[T], val : T) -> FixedArray[T] { #| let len = arr.length() #| let new_arr = FixedArray::make(len + 1, val) #| arr.blit_to(new_arr, len~) #| new_arr[len] = val #| new_arr #|} #|fn shr_as_uint(x : Int, y : Int) -> Int { #| (x.reinterpret_as_uint() >> y).reinterpret_as_int() #|} #|fn radix_indexing(index : Int, shift : Int) -> Int { #| shr_as_uint(index, shift) & bitmask #|} #|fn get_branch_index(sizes : FixedArray[Int], index : Int) -> Int { #| let mut lo = 0 #| let mut hi = sizes.length() #| while LINEAR_THRESHOLD < hi - lo { #| let mid = (lo + hi) / 2 #| if sizes[mid] <= index { #| lo = mid #| } else { #| hi = mid #| } #| } #| while sizes[lo] <= index { #| lo += 1 #| } #| lo #|} #|fn copy_sizes(sizes : FixedArray[Int]?) -> FixedArray[Int]? { #| match sizes { #| Some(sizes) => Some(sizes.copy()) #| None => None #| } #|} #|fn min(a : Int, b : Int) -> Int { #| if a < b { #| a #| } else { #| b #| } #|} ), "utils_wbtest2.mbt": ( #|test "immutable_set" { #| let arr = FixedArray::from_array([1, 2, 3, 4, 5]) #| let new_arr = immutable_set(arr, 2, 10) #| inspect(new_arr[2], content="10") #| inspect(arr[2], content="3") // Original array unchanged #| inspect(new_arr.length(), content="5") #|} #|test "immutable_push" { #| let arr = FixedArray::from_array([1, 2, 3]) #| let new_arr = immutable_push(arr, 4) #| inspect(new_arr.length(), content="4") #| inspect(new_arr[3], content="4") #| inspect(arr.length(), content="3") // Original array unchanged #|} #|test "shr_as_uint" { #| inspect(shr_as_uint(16, 2), content="4") #| inspect(shr_as_uint(8, 1), content="4") #| inspect(shr_as_uint(-1, 1), content="2147483647") // Handle negative numbers as unsigned #|} #|test "radix_indexing" { #| inspect(radix_indexing(35, 5), content="1") // 35 >> 5 = 1, 1 & 31 = 1 #| inspect(radix_indexing(100, 5), content="3") // 100 >> 5 = 3, 3 & 31 = 3 #| inspect(radix_indexing(7, 5), content="0") // 7 >> 5 = 0, 0 & 31 = 0 #|} #|test "get_branch_index" { #| let sizes = FixedArray::from_array([3, 6, 10, 15]) #| inspect(get_branch_index(sizes, 2), content="0") // Index 2 is in first branch (contains indexes 0-2) #| inspect(get_branch_index(sizes, 5), content="1") // Index 5 is in second branch (contains indexes 3-5) #| inspect(get_branch_index(sizes, 8), content="2") // Index 8 is in third branch (contains indexes 6-9) #|} #|test "copy_sizes with Some" { #| let original = FixedArray::from_array([1, 2, 3]) #| let sizes = Some(original) #| let copied = copy_sizes(sizes) #| match copied { #| Some(copied_arr) => { #| inspect(copied_arr.length(), content="3") #| inspect(copied_arr[0], content="1") #| inspect(copied_arr[1], content="2") #| inspect(copied_arr[2], content="3") #| original[0] = 100 #| inspect(copied_arr[0], content="1") // Should still be 1 #| } #| None => inspect("Should not be None", content="error") #| } #|} #|test "copy_sizes with None" { #| let sizes : FixedArray[Int]? = None #| let copied = copy_sizes(sizes) #| match copied { #| None => inspect("None copied correctly", content="None copied correctly") #| Some(_) => inspect("Should be None", content="error") #| } #|} #|test "min function" { #| inspect(min(5, 3), content="3") #| inspect(min(1, 10), content="1") #| inspect(min(-5, 0), content="-5") #| inspect(min(42, 42), content="42") #|} ), }, ) ///| let moonbitlang_core_immut_hashmap_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/immut/hashmap", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/array": moonbitlang_core_array_module, "moonbitlang/core/tuple": moonbitlang_core_tuple_module, "moonbitlang/core/quickcheck": moonbitlang_core_quickcheck_module, "moonbitlang/core/immut/internal/sparse_array": moonbitlang_core_immut_internal_sparse_array_module, "moonbitlang/core/immut/internal/path": moonbitlang_core_immut_internal_path_module, "moonbitlang/core/list": moonbitlang_core_list_module, }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/builtin", #| "moonbitlang/core/array", #| "moonbitlang/core/tuple", #| "moonbitlang/core/quickcheck", #| "moonbitlang/core/immut/internal/sparse_array", #| "moonbitlang/core/immut/internal/path", #| "moonbitlang/core/list" #| ], #| "test-import": [ #| "moonbitlang/core/int", #| "moonbitlang/core/string", #| "moonbitlang/core/option" #| ] #|} ), "HAMT.mbt": ( #|pub fn[K, V] new() -> T[K, V] { #| None #|} #|pub fn[K : Hash, V] singleton(key : K, value : V) -> T[K, V] { #| Some(Flat(key, value, @path.of(key))) #|} #|pub fn[K : Eq + Hash, V] contains(self : T[K, V], key : K) -> Bool { #| self.get(key) is Some(_) #|} #|#deprecated("Use `get()` instead") #|#coverage.skip #|pub fn[K : Eq + Hash, V] find(self : T[K, V], key : K) -> V? { #| self.get(key) #|} #|pub fn[K : Eq + Hash, V] get(self : T[K, V], key : K) -> V? { #| match self.0 { #| None => None #| Some(node) => node.get_with_path(key, @path.of(key)) #| } #|} #|fn[K : Eq, V] Node::get_with_path( #| self : Node[K, V], #| key : K, #| path : Path, #|) -> V? { #| loop (self, path) { #| (Leaf(key1, value1, bucket), _) => #| if key == key1 { #| Some(value1) #| } else { #| bucket.lookup(key) #| } #| (Flat(key1, value1, path1), path) => #| if path == path1 && key == key1 { #| Some(value1) #| } else { #| None #| } #| (Branch(children), path) => { #| let idx = path.idx() #| if children[idx] is Some(child) { #| continue (child, path.next()) #| } #| None #| } #| } #|} #|#deprecated("Use `get` instead. `op_get` will return `V` instead of `Option[V]` in the future.") #|pub fn[K : Eq + Hash, V] op_get(self : T[K, V], key : K) -> V? { #| self.get(key) #|} #|fn[K, V] join_2( #| key1 : K, #| value1 : V, #| path1 : Path, #| key2 : K, #| value2 : V, #| path2 : Path, #|) -> Node[K, V] { #| let idx1 = path1.idx() #| let idx2 = path2.idx() #| if idx1 == idx2 { #| let node = if path1.is_last() { #| Leaf(key2, value2, @list.singleton((key1, value1))) #| } else { #| join_2(key1, value1, path1.next(), key2, value2, path2.next()) #| } #| Branch(@sparse_array.singleton(idx1, node)) #| } else { #| let (node1, node2) = if path1.is_last() { #| (Leaf(key1, value1, @list.empty()), Leaf(key2, value2, @list.empty())) #| } else { #| (Flat(key1, value1, path1.next()), Flat(key2, value2, path2.next())) #| } #| Branch(@sparse_array.doubleton(idx1, node1, idx2, node2)) #| } #|} #|fn[K : Eq, V] add_with_path( #| self : Node[K, V], #| key : K, #| value : V, #| path : Path, #|) -> Node[K, V] { #| match self { #| Leaf(key1, value1, bucket) => #| if key == key1 { #| Leaf(key, value, bucket) #| } else { #| let new_bucket = match bucket.find_index(kv => kv.0 == key) { #| None => bucket #| Some(index) => bucket.remove_at(index) #| } #| Leaf(key, value, new_bucket.add((key1, value1))) #| } #| Flat(key1, value1, path1) => #| if path == path1 && key == key1 { #| Flat(key1, value, path1) #| } else { #| join_2(key1, value1, path1, key, value, path) #| } #| Branch(children) => { #| let idx = path.idx() #| match children[idx] { #| Some(child) => { #| let child = child.add_with_path(key, value, path.next()) #| Branch(children.replace(idx, child)) #| } #| None => { #| let child = Flat(key, value, path.next()) #| Branch(children.add(idx, child)) #| } #| } #| } #| } #|} #|pub fn[K, V] filter( #| self : T[K, V], #| pred : (V) -> Bool raise?, #|) -> T[K, V] raise? { #| fn go(node) raise? { #| match node { #| Leaf(key1, value1, bucket) => { #| let new_bucket = bucket.filter(kv => pred(kv.1)) #| if pred(value1) { #| Some(Leaf(key1, value1, new_bucket)) #| } else { #| match new_bucket { #| Empty => None #| More((k1, v1), tail~) => Some(Leaf(k1, v1, tail)) #| } #| } #| } #| Flat(_, value1, _) => if pred(value1) { Some(node) } else { None } #| Branch(children) => #| match children.filter(go) { #| None => None #| Some(new_children) => Some(Branch(new_children)) #| } #| } #| } #| match self.0 { #| None => None #| Some(node) => go(node) #| } #|} #|pub fn[K, V, A] fold( #| self : T[K, V], #| init~ : A, #| f : (A, V) -> A raise?, #|) -> A raise? { #| self.fold_with_key((acc, _k, v) => f(acc, v), init~) #|} #|pub fn[K, V, A] fold_with_key( #| self : T[K, V], #| init~ : A, #| f : (A, K, V) -> A raise?, #|) -> A raise? { #| fn go(acc, node) raise? { #| match node { #| Leaf(k, v, bucket) => #| bucket.fold(init=f(acc, k, v), (acc, kv) => f(acc, kv.0, kv.1)) #| Flat(k, v, _) => f(acc, k, v) #| Branch(children) => children.data.fold(init=acc, go) #| } #| } #| match self.0 { #| None => init #| Some(node) => go(init, node) #| } #|} #|pub fn[K, V, A] map(self : T[K, V], f : (V) -> A raise?) -> T[K, A] raise? { #| self.map_with_key((_k, v) => f(v)) #|} #|pub fn[K, V, A] map_with_key( #| self : T[K, V], #| f : (K, V) -> A raise?, #|) -> T[K, A] raise? { #| fn go(m : Node[K, V]) -> Node[K, A] raise? { #| match m { #| Leaf(k, v, bucket) => #| Leaf(k, f(k, v), bucket.map(kv => (kv.0, f(kv.0, kv.1)))) #| Flat(k, v, path) => Flat(k, f(k, v), path) #| Branch(children) => Branch(children.map(go)) #| } #| } #| match self.0 { #| None => None #| Some(node) => Some(go(node)) #| } #|} #|pub fn[K : Eq + Hash, V] add(self : T[K, V], key : K, value : V) -> T[K, V] { #| match self.0 { #| None => Some(Flat(key, value, @path.of(key))) #| Some(node) => Some(node.add_with_path(key, value, @path.of(key))) #| } #|} #|pub fn[K : Eq + Hash, V] remove(self : T[K, V], key : K) -> T[K, V] { #| match self.0 { #| None => None #| Some(node) => node.remove_with_path(key, @path.of(key)) #| } #|} #|fn[K : Eq, V] remove_with_path( #| self : Node[K, V], #| key : K, #| path : Path, #|) -> Node[K, V]? { #| match self { #| Leaf(key1, value1, bucket) => #| if key1 == key { #| match bucket { #| @list.Empty => None #| More((key2, value2), tail~) => Some(Leaf(key2, value2, tail)) #| } #| } else if bucket.find_index(kv => kv.0 == key) is Some(index) { #| Some(Leaf(key1, value1, bucket.remove_at(index))) #| } else { #| Some(self) #| } #| Flat(key1, _, path1) => #| if path == path1 && key == key1 { #| None #| } else { #| Some(self) #| } #| Branch(children) => { #| let idx = path.idx() #| match children[idx] { #| None => Some(self) #| Some(child) => { #| let new_child = child.remove_with_path(key, path.next()) #| let new_children = match (children.size(), new_child) { #| (1, None) => return None #| (_, None) => children.remove(idx) #| (_, Some(new_child)) => children.replace(idx, new_child) #| } #| match new_children.data { #| [Flat(key1, value1, path1)] => #| Some( #| Flat( #| key1, #| value1, #| path1.push(new_children.elem_info.first_idx()), #| ), #| ) #| _ => Some(Branch(new_children)) #| } #| } #| } #| } #| } #|} #|pub fn[K, V] size(self : T[K, V]) -> Int { #| fn node_size(node) { #| match node { #| Leaf(_, _, bucket) => 1 + bucket.length() #| Flat(_) => 1 #| Branch(children) => #| for i = 0, total_size = 0; i < children.data.length(); { #| continue i + 1, total_size + node_size(children.data[i]) #| } else { #| total_size #| } #| } #| } #| match self.0 { #| None => 0 #| Some(node) => node_size(node) #| } #|} #|pub fn[K : Eq, V] T::union(self : T[K, V], other : T[K, V]) -> T[K, V] { #| fn go(node1 : Node[_], node2) { #| match (node1, node2) { #| (_, Flat(key2, value2, path2)) => node1.add_with_path(key2, value2, path2) #| (Flat(key1, value1, path1), _) => #| match node2.get_with_path(key1, path1) { #| Some(_) => node2 #| None => node2.add_with_path(key1, value1, path1) #| } #| (Branch(children1), Branch(children2)) => #| Branch(children1.union(children2, go)) #| (Leaf(key1, value1, bucket1), Leaf(key2, value2, bucket2)) => { #| let kvs1 = bucket1.add((key1, value1)) #| let kvs2 = bucket2.add((key2, value2)) #| match kvs1.filter(kv => kvs2.lookup(kv.0) is None) { #| Empty => node2 #| More(head, tail~) => Leaf(key2, value2, bucket2 + tail.add(head)) #| } #| } #| _ => abort("Unreachable") #| } #| } #| match (self.0, other.0) { #| (None, x) | (x, None) => x #| (Some(a), Some(b)) => Some(go(a, b)) #| } #|} #|pub fn[K : Eq, V] T::union_with( #| self : T[K, V], #| other : T[K, V], #| f : (K, V, V) -> V raise?, #|) -> T[K, V] raise? { #| fn go(node1 : Node[_], node2) raise? { #| match (node1, node2) { #| (_, Flat(key2, value2, path2)) => { #| let new_value = match node1.get_with_path(key2, path2) { #| Some(value1) => f(key2, value1, value2) #| None => value2 #| } #| node1.add_with_path(key2, new_value, path2) #| } #| (Flat(key1, value1, path1), _) => { #| let new_value = match node2.get_with_path(key1, path1) { #| Some(value2) => f(key1, value1, value2) #| None => value1 #| } #| node2.add_with_path(key1, new_value, path1) #| } #| (Branch(children1), Branch(children2)) => #| Branch(children1.union(children2, go)) #| (Leaf(key1, value1, bucket1), Leaf(key2, value2, bucket2)) => { #| let kvs1 = bucket1.add((key1, value1)) #| let kvs2 = bucket2.add((key2, value2)) #| kvs1.union_with(kvs2, f) #| } #| _ => abort("Unreachable") #| } #| } #| match (self.0, other.0) { #| (None, x) | (x, None) => x #| (Some(a), Some(b)) => Some(go(a, b)) #| } #|} #|fn[K : Eq, V] @list.List::union_with( #| self : Self[(K, V)], #| other : Self[(K, V)], #| f : (K, V, V) -> V raise?, #|) -> Node[K, V] raise? { #| let res = self.to_array() #| for kv2 in other { #| for i, kv1 in res { #| if kv1.0 == kv2.0 { #| res[i] = (kv1.0, f(kv1.0, kv1.1, kv2.1)) #| break #| } #| } else { #| res.push(kv2) #| } #| } #| guard @list.from_array(res) is More((k, v), tail~) #| Leaf(k, v, tail) #|} #|pub fn[K : Eq, V] T::intersection(self : T[K, V], other : T[K, V]) -> T[K, V] { #| fn go(node1 : Node[_], node2) { #| match (node1, node2) { #| (_, Flat(key2, _, path2)) => #| match node1.get_with_path(key2, path2) { #| Some(_) => Some(node2) #| None => None #| } #| (Flat(key1, _, path1), _) => #| match node2.get_with_path(key1, path1) { #| Some(value2) => Some(Flat(key1, value2, path1)) #| None => None #| } #| (Branch(children1), Branch(children2)) => #| match children1.intersection(children2, go) { #| None => None #| Some({ data: [Flat(key, value, path)], elem_info }) => #| Some(Flat(key, value, path.push(elem_info.first_idx()))) #| Some(children) => Some(Branch(children)) #| } #| (Leaf(key1, value1, bucket1), Leaf(key2, value2, bucket2)) => { #| let kvs1 = bucket1.add((key1, value1)) #| let kvs2 = bucket2.add((key2, value2)) #| match kvs2.filter(kv => kvs1.lookup(kv.0) is Some(_)) { #| Empty => None #| More(head, tail~) => Some(Leaf(head.0, head.1, tail)) #| } #| } #| _ => abort("Unreachable") #| } #| } #| match (self.0, other.0) { #| (None, _) | (_, None) => None #| (Some(a), Some(b)) => go(a, b) #| } #|} #|pub fn[K : Eq, V] T::intersection_with( #| self : T[K, V], #| other : T[K, V], #| f : (K, V, V) -> V raise?, #|) -> T[K, V] raise? { #| fn go(node1 : Node[_], node2) raise? { #| match (node1, node2) { #| (_, Flat(key2, value2, path2)) => #| match node1.get_with_path(key2, path2) { #| Some(value1) => Some(Flat(key2, f(key2, value1, value2), path2)) #| None => None #| } #| (Flat(key1, value1, path1), _) => #| match node2.get_with_path(key1, path1) { #| Some(value2) => Some(Flat(key1, f(key1, value1, value2), path1)) #| None => None #| } #| (Branch(children1), Branch(children2)) => #| match children1.intersection(children2, go) { #| None => None #| Some({ data: [Flat(key, value, path)], elem_info }) => #| Some(Flat(key, value, path.push(elem_info.first_idx()))) #| Some(children) => Some(Branch(children)) #| } #| (Leaf(key1, value1, bucket1), Leaf(key2, value2, bucket2)) => { #| let kvs1 = bucket1.add((key1, value1)) #| let kvs2 = bucket2.add((key2, value2)) #| kvs1.intersection_with(kvs2, f) #| } #| _ => abort("Unreachable") #| } #| } #| match (self.0, other.0) { #| (None, _) | (_, None) => None #| (Some(a), Some(b)) => go(a, b) #| } #|} #|fn[K : Eq, V] @list.List::intersection_with( #| self : Self[(K, V)], #| other : Self[(K, V)], #| f : (K, V, V) -> V raise?, #|) -> Node[K, V]? raise? { #| let res = [] #| for kv1 in self { #| for kv2 in other { #| if kv1.0 == kv2.0 { #| res.push((kv1.0, f(kv1.0, kv1.1, kv2.1))) #| break #| } #| } #| } #| match @list.from_array(res) { #| Empty => None #| More((k, v), tail~) => Some(Leaf(k, v, tail)) #| } #|} #|pub fn[K : Eq, V] T::difference(self : T[K, V], other : T[K, V]) -> T[K, V] { #| fn go(node1 : Node[_], node2) { #| match (node1, node2) { #| (node, Flat(k, _, path)) => node.remove_with_path(k, path) #| (Flat(key, _, path), _) => #| match node2.get_with_path(key, path) { #| Some(_) => None #| None => Some(node1) #| } #| (Branch(children1), Branch(children2)) => #| match children1.difference(children2, go) { #| None => None #| Some({ data: [Flat(key, value, path)], elem_info }) => #| Some(Flat(key, value, path.push(elem_info.first_idx()))) #| Some(children) => Some(Branch(children)) #| } #| (Leaf(key1, value1, bucket1), Leaf(key2, value2, bucket2)) => { #| let kvs1 = bucket1.add((key1, value1)) #| let kvs2 = bucket2.add((key2, value2)) #| match kvs1.filter(kv => not(kvs2.lookup(kv.0) is Some(_))) { #| Empty => None #| More(head, tail~) => Some(Leaf(head.0, head.1, tail)) #| } #| } #| _ => abort("Unreachable") #| } #| } #| match (self.0, other.0) { #| (None, _) => None #| (_, None) => self #| (Some(a), Some(b)) => go(a, b) #| } #|} #|pub fn[K, V] each(self : T[K, V], f : (K, V) -> Unit raise?) -> Unit raise? { #| fn go(node) raise? { #| match node { #| Leaf(k, v, bucket) => { #| f(k, v) #| bucket.each(kv => f(kv.0, kv.1)) #| } #| Flat(k, v, _) => f(k, v) #| Branch(children) => children.each(go) #| } #| } #| match self.0 { #| None => () #| Some(node) => go(node) #| } #|} #|pub fn[K, V] keys(self : T[K, V]) -> Iter[K] { #| self.iter().map(p => p.0) #|} #|pub fn[K, V] values(self : T[K, V]) -> Iter[V] { #| self.iter().map(p => p.1) #|} #|#deprecated("Use `values` instead") #|#coverage.skip #|pub fn[K, V] elems(self : T[K, V]) -> Iter[V] { #| self.values() #|} #|pub fn[K, V] iter(self : T[K, V]) -> Iter[(K, V)] { #| fn go(node) -> Iter[(K, V)] { #| match node { #| Leaf(k, v, bucket) => Iter::singleton((k, v)) + bucket.iter() #| Flat(k, v, _) => Iter::singleton((k, v)) #| Branch(children) => children.data.iter().flat_map(go) #| } #| } #| match self.0 { #| None => Iter::empty() #| Some(node) => go(node) #| } #|} #|pub fn[K, V] iter2(self : T[K, V]) -> Iter2[K, V] { #| Iter2::new(yield_ => for kv in self { #| guard yield_(kv.0, kv.1) is IterContinue else { break IterEnd } #| } else { #| IterContinue #| }) #|} #|pub fn[K : Eq + Hash, V] from_iter(iter : Iter[(K, V)]) -> T[K, V] { #| iter.fold(init=new(), (m, e) => m.add(e.0, e.1)) #|} #|pub impl[K : Show, V : Show] Show for T[K, V] with output(self, logger) { #| logger.write_iter(self.iter(), prefix="@immut/hashmap.of([", suffix="])") #|} #|pub fn[K : Eq + Hash, V] from_array(arr : Array[(K, V)]) -> T[K, V] { #| loop (arr.length(), new()) { #| (0, map) => map #| (n, map) => { #| let (k, v) = arr[n - 1] #| continue (n - 1, map.add(k, v)) #| } #| } #|} #|pub fn[K, V] to_array(self : T[K, V]) -> Array[(K, V)] { #| let arr = Array::new(capacity=self.size()) #| self.each((k, v) => arr.push((k, v))) #| arr #|} #|pub impl[K : Eq + Hash + @quickcheck.Arbitrary, V : @quickcheck.Arbitrary] @quickcheck.Arbitrary for T[ #| K, #| V, #|] with arbitrary(size, rs) { #| @quickcheck.Arbitrary::arbitrary(size, rs) |> from_array #|} #|pub fn[K : Eq + Hash, V] of(arr : FixedArray[(K, V)]) -> T[K, V] { #| loop (arr.length(), new()) { #| (0, map) => map #| (n, map) => { #| let (k, v) = arr[n - 1] #| continue (n - 1, map.add(k, v)) #| } #| } #|} #|impl[K : Eq, V : Eq] Eq for Node[K, V] with op_equal(self, other) { #| match (self, other) { #| (Flat(key1, value1, path1), Flat(key2, value2, path2)) => #| path1 == path2 && key1 == key2 && value1 == value2 #| (Branch(children1), Branch(children2)) => children1 == children2 #| (Leaf(key1, value1, bucket1), Leaf(key2, value2, bucket2)) => { #| guard bucket1.length() == bucket2.length() else { return false } #| let kvs1 = bucket1.add((key1, value1)) #| let kvs2 = bucket2.add((key2, value2)) #| kvs1.all(kv => kvs2.lookup(kv.0) is Some(v) && kv.1 == v) #| } #| _ => false #| } #|} #|pub impl[K : Hash, V : Hash] Hash for T[K, V] with hash_combine(self, hasher) { #| self.each((k, v) => hasher..combine(k)..combine(v)) #|} ), "deprecated.mbt": "", "types.mbt": ( #|typealias @path.Path #|priv enum Node[K, V] { #| Flat(K, V, Path) #| Leaf(K, V, @list.List[(K, V)]) // use a list of buckets to resolve collision #| Branch(@sparse_array.SparseArray[Node[K, V]]) #|} #|struct T[K, V](Node[K, V]?) derive(Eq) ), }, ) ///| let moonbitlang_core_immut_hashset_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/immut/hashset", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/array": moonbitlang_core_array_module, "moonbitlang/core/immut/internal/sparse_array": moonbitlang_core_immut_internal_sparse_array_module, "moonbitlang/core/quickcheck": moonbitlang_core_quickcheck_module, "moonbitlang/core/immut/internal/path": moonbitlang_core_immut_internal_path_module, "moonbitlang/core/list": moonbitlang_core_list_module, }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/builtin", #| "moonbitlang/core/array", #| "moonbitlang/core/immut/internal/sparse_array", #| "moonbitlang/core/quickcheck", #| "moonbitlang/core/immut/internal/path", #| "moonbitlang/core/list" #| ], #| "test-import": ["moonbitlang/core/string", "moonbitlang/core/int"] #|} ), "HAMT.mbt": ( #|pub fn[A] new() -> T[A] { #| None #|} #|pub fn[A : Eq + Hash] contains(self : T[A], key : A) -> Bool { #| self.0 is Some(node) && node.contains(key, @path.of(key)) #|} #|fn[A : Eq] Node::contains(self : Node[A], key : A, path : Path) -> Bool { #| loop (self, path) { #| (Leaf(key1, bucket), _) => key == key1 || bucket.contains(key) #| (Flat(key1, path1), path) => path == path1 && key == key1 #| (Branch(children), path) => { #| let idx = path.idx() #| if children[idx] is Some(child) { #| continue (child, path.next()) #| } #| false #| } #| } #|} #|fn[A] join_2(key1 : A, path1 : Path, key2 : A, path2 : Path) -> Node[A] { #| let idx1 = path1.idx() #| let idx2 = path2.idx() #| if idx1 == idx2 { #| let node = if path1.is_last() { #| Leaf(key2, @list.singleton(key1)) #| } else { #| join_2(key1, path1.next(), key2, path2.next()) #| } #| Branch(@sparse_array.singleton(idx1, node)) #| } else { #| let (node1, node2) = if path1.is_last() { #| (Leaf(key1, @list.empty()), Leaf(key2, @list.empty())) #| } else { #| (Flat(key1, path1.next()), Flat(key2, path2.next())) #| } #| Branch(@sparse_array.doubleton(idx1, node1, idx2, node2)) #| } #|} #|fn[A : Eq] add_with_path(self : Node[A], key : A, path : Path) -> Node[A] { #| match self { #| Leaf(key1, bucket) => #| if key == key1 || bucket.contains(key) { #| self #| } else { #| Leaf(key, bucket.add(key1)) #| } #| Flat(key1, path1) => #| if path == path1 && key == key1 { #| self #| } else { #| join_2(key1, path1, key, path) #| } #| Branch(children) => { #| let idx = path.idx() #| match children[idx] { #| Some(child) => { #| let child = child.add_with_path(key, path.next()) #| Branch(children.replace(idx, child)) #| } #| None => { #| let child = Flat(key, path.next()) #| Branch(children.add(idx, child)) #| } #| } #| } #| } #|} #|pub fn[A : Eq + Hash] add(self : T[A], key : A) -> T[A] { #| match self.0 { #| None => Some(Flat(key, @path.of(key))) #| Some(node) => Some(node.add_with_path(key, @path.of(key))) #| } #|} #|pub fn[A : Eq + Hash] remove(self : T[A], key : A) -> T[A] { #| match self.0 { #| None => None #| Some(node) => node.remove_with_path(key, @path.of(key)) #| } #|} #|fn[A : Eq] remove_with_path(self : Node[A], key : A, path : Path) -> Node[A]? { #| match self { #| Leaf(key1, bucket) => #| if key1 == key { #| match bucket { #| @list.Empty => None #| More(key2, tail=xs) => Some(Leaf(key2, xs)) #| } #| } else if bucket.find_index(key.op_equal(_)) is Some(index) { #| Some(Leaf(key1, bucket.remove_at(index))) #| } else { #| Some(self) #| } #| Flat(key1, path1) => #| if path == path1 && key == key1 { #| None #| } else { #| Some(self) #| } #| Branch(children) => { #| let idx = path.idx() #| match children[idx] { #| None => Some(self) #| Some(child) => { #| let new_child = child.remove_with_path(key, path.next()) #| let new_children = match (children.size(), new_child) { #| (1, None) => return None #| (_, None) => children.remove(idx) #| (_, Some(new_child)) => children.replace(idx, new_child) #| } #| match new_children.data { #| [Flat(key1, path1)] => #| Some(Flat(key1, path1.push(new_children.elem_info.first_idx()))) #| _ => Some(Branch(new_children)) #| } #| } #| } #| } #| } #|} #|pub fn[A] size(self : T[A]) -> Int { #| fn node_size(node) { #| match node { #| Leaf(_, bucket) => 1 + bucket.length() #| Flat(_) => 1 #| Branch(children) => #| for i = 0, total_size = 0; i < children.data.length(); { #| continue i + 1, total_size + node_size(children.data[i]) #| } else { #| total_size #| } #| } #| } #| match self.0 { #| None => 0 #| Some(node) => node_size(node) #| } #|} #|pub fn[K : Eq] T::union(self : T[K], other : T[K]) -> T[K] { #| fn go(node1, node2) { #| match (node1, node2) { #| (node, Flat(key, path)) | (Flat(key, path), node) => #| node.add_with_path(key, path) #| (Branch(children1), Branch(children2)) => #| Branch(children1.union(children2, go)) #| (Leaf(key1, bucket1), Leaf(key2, bucket2)) => { #| let keys1 = bucket1.add(key1) #| let keys2 = bucket2.add(key2) #| match keys1.filter(k => !keys2.contains(k)) { #| Empty => node2 #| More(head, tail~) => Leaf(key2, bucket2 + tail.add(head)) #| } #| } #| _ => abort("Unreachable") #| } #| } #| match (self.0, other.0) { #| (None, x) | (x, None) => x #| (Some(a), Some(b)) => Some(go(a, b)) #| } #|} #|pub fn[K : Eq] T::intersection(self : T[K], other : T[K]) -> T[K] { #| fn go(node1, node2) { #| match (node1, node2) { #| (node, Flat(key, path) as flat) | (Flat(key, path) as flat, node) => #| if node.contains(key, path) { #| Some(flat) #| } else { #| None #| } #| (Branch(children1), Branch(children2)) => #| match children1.intersection(children2, go) { #| None => None #| Some({ data: [Flat(key, path)], elem_info }) => #| Some(Flat(key, path.push(elem_info.first_idx()))) #| Some(children) => Some(Branch(children)) #| } #| (Leaf(key1, bucket1), Leaf(key2, bucket2)) => { #| let keys1 = bucket1.add(key1) #| let keys2 = bucket2.add(key2) #| match keys1.filter(keys2.contains(_)) { #| Empty => None #| More(head, tail~) => Some(Leaf(head, tail)) #| } #| } #| _ => abort("Unreachable") #| } #| } #| match (self.0, other.0) { #| (None, _) | (_, None) => None #| (Some(a), Some(b)) => go(a, b) #| } #|} #|pub fn[K : Eq] T::difference(self : T[K], other : T[K]) -> T[K] { #| fn go(node1 : Node[_], node2) { #| match (node1, node2) { #| (node, Flat(k, path)) => node.remove_with_path(k, path) #| (Flat(key, path) as flat, node) => #| if node.contains(key, path) { #| None #| } else { #| Some(flat) #| } #| (Branch(children1), Branch(children2)) => #| match children1.difference(children2, go) { #| None => None #| Some({ data: [Flat(key, path)], elem_info }) => #| Some(Flat(key, path.push(elem_info.first_idx()))) #| Some(children) => Some(Branch(children)) #| } #| (Leaf(key1, bucket1), Leaf(key2, bucket2)) => { #| let keys1 = bucket1.add(key1) #| let keys2 = bucket2.add(key2) #| match keys1.filter(k => !keys2.contains(k)) { #| Empty => None #| More(head, tail~) => Some(Leaf(head, tail)) #| } #| } #| _ => abort("Unreachable") #| } #| } #| match (self.0, other.0) { #| (None, _) => None #| (_, None) => self #| (Some(a), Some(b)) => go(a, b) #| } #|} #|pub fn[A] is_empty(self : T[A]) -> Bool { #| self.0 is None #|} #|pub fn[A] each(self : T[A], f : (A) -> Unit raise?) -> Unit raise? { #| fn go(node) raise? { #| match node { #| Leaf(k, bucket) => { #| f(k) #| bucket.each(f) #| } #| Flat(k, _) => f(k) #| Branch(children) => children.each(go) #| } #| } #| match self.0 { #| None => () #| Some(node) => go(node) #| } #|} #|pub fn[A] iter(self : T[A]) -> Iter[A] { #| fn go(node) -> Iter[A] { #| match node { #| Leaf(k, bucket) => Iter::singleton(k) + bucket.iter() #| Flat(k, _) => Iter::singleton(k) #| Branch(children) => children.data.iter().flat_map(go) #| } #| } #| match self.0 { #| None => Iter::empty() #| Some(node) => go(node) #| } #|} #|pub fn[A : Eq + Hash] from_iter(iter : Iter[A]) -> T[A] { #| iter.fold(init=new(), (s, e) => s.add(e)) #|} #|pub impl[A : Show] Show for T[A] with output(self, logger) { #| logger.write_iter(self.iter(), prefix="@immut/hashset.of([", suffix="])") #|} #|pub fn[A : Eq + Hash] from_array(arr : Array[A]) -> T[A] { #| loop (arr.length(), new()) { #| (0, set) => set #| (n, set) => { #| let k = arr[n - 1] #| continue (n - 1, set.add(k)) #| } #| } #|} #|pub fn[A : Eq + Hash] of(arr : FixedArray[A]) -> T[A] { #| loop (arr.length(), new()) { #| (0, set) => set #| (n, set) => { #| let k = arr[n - 1] #| continue (n - 1, set.add(k)) #| } #| } #|} #|pub impl[A : Hash] Hash for T[A] with hash_combine(self, hasher) { #| hasher.combine(self.iter().fold(init=0, (x, y) => x ^ y.hash())) #|} #|impl[A : Eq] Eq for Node[A] with op_equal(self, other) { #| match (self, other) { #| (Leaf(x, xs), Leaf(y, ys)) => #| xs.length() == ys.length() && #| { #| let keys1 = xs.add(x) #| let keys2 = ys.add(y) #| keys1.iter().all(keys2.contains(_)) #| } #| (Flat(x, pathx), Flat(y, pathy)) => pathx == pathy && x == y #| (Branch(xs), Branch(ys)) => xs == ys #| _ => false #| } #|} #|pub impl[K : Eq + Hash + @quickcheck.Arbitrary] @quickcheck.Arbitrary for T[K] with arbitrary( #| size, #| rs, #|) { #| @quickcheck.Arbitrary::arbitrary(size, rs) |> from_array #|} #|test "hash" { #| assert_eq(Hash::hash(of([1, 2, 3, 4])), Hash::hash(of([3, 2]).add(1).add(4))) #| assert_not_eq(Hash::hash(of([1, 2, 3])), Hash::hash(of([1, 2, 4]))) #|} #|test "eq" { #| assert_eq(of([1, 2, 3, 4]), of([3, 2]).add(1).add(4)) #| assert_not_eq(of([1, 2, 3]), of([1, 2, 4])) #|} ), "types.mbt": ( #|typealias @path.Path #|priv enum Node[A] { #| Flat(A, Path) #| Leaf(A, @list.List[A]) // use a list of buckets to resolve collision #| Branch(@sparse_array.SparseArray[Node[A]]) #|} #|struct T[A](Node[A]?) derive(Eq) ), }, ) ///| let moonbitlang_core_immut_internal_path_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/immut/internal/path", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module }, files={ "moon.pkg.json": ( #|{ #| "import": ["moonbitlang/core/builtin"] #|} ), "path.mbt": ( #|pub(all) struct Path(UInt) derive(Eq) #|const SEGMENT_LENGTH : Int = 5 #|const INDEX_MASK : UInt = (1 << SEGMENT_LENGTH) - 1 #|const SEGMENT_NUM : Int = 32 / SEGMENT_LENGTH #|const HEAD_TAG : UInt = 0xffffffffU << (SEGMENT_LENGTH * SEGMENT_NUM) #|pub fn[A : Hash] of(key : A) -> Path { #| key.hash().reinterpret_as_uint() | HEAD_TAG #|} #|const MAX_TAIL : UInt = 0xffffffffU >> (SEGMENT_LENGTH * (SEGMENT_NUM - 1)) #|pub fn Path::is_last(self : Path) -> Bool { #| let Path(self) = self #| self <= MAX_TAIL #|} #|pub fn Path::push(self : Path, idx : Int) -> Path { #| let Path(self) = self #| (self << SEGMENT_LENGTH) | idx.reinterpret_as_uint() #|} #|pub fn Path::idx(self : Path) -> Int { #| let Path(self) = self #| (self & INDEX_MASK).reinterpret_as_int() #|} #|pub fn Path::next(self : Path) -> Path { #| let Path(self) = self #| self >> SEGMENT_LENGTH #|} ), }, ) ///| let moonbitlang_core_immut_internal_sparse_array_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/immut/internal/sparse_array", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/array": moonbitlang_core_array_module, }, files={ "moon.pkg.json": ( #|{ #| "import": ["moonbitlang/core/builtin", "moonbitlang/core/array"] #|} ), "bitset.mbt": ( #|pub(all) struct Bitset(UInt) derive(Eq) #|let empty_bitset : Bitset = Bitset(0) #|pub fn Bitset::has(self : Bitset, idx : Int) -> Bool { #| (self.0 & (1U << idx)) != 0 #|} #|pub fn Bitset::index_of(self : Bitset, idx : Int) -> Int { #| (self.0 & ((1U << idx) - 1)).popcnt() #|} #|pub fn Bitset::first_idx(self : Bitset) -> Int { #| self.0.ctz() #|} #|pub fn Bitset::union(self : Bitset, other : Bitset) -> Bitset { #| Bitset(self.0 | other.0) #|} #|pub fn Bitset::intersection(self : Bitset, other : Bitset) -> Bitset { #| Bitset(self.0 & other.0) #|} #|pub fn Bitset::add(self : Bitset, idx : Int) -> Bitset { #| Bitset(self.0 | (1U << idx)) #|} #|pub fn Bitset::remove(self : Bitset, idx : Int) -> Bitset { #| Bitset(self.0 ^ (1U << idx)) #|} #|pub fn Bitset::size(self : Bitset) -> Int { #| let Bitset(self) = self #| self.popcnt() #|} #|test "Bitset::has" { #| let b = empty_bitset.add(2) #| inspect(b.has(0), content="false") #| inspect(b.has(2), content="true") #| let b = b.add(0) #| inspect(b.has(0), content="true") #| inspect(b.has(2), content="true") #|} #|test "Bitset::index_of" { #| let b = empty_bitset.add(2) #| inspect(b.index_of(2), content="0") #| let b = b.add(0) #| inspect(b.index_of(2), content="1") #| let b = b.add(5) #| inspect(b.index_of(2), content="1") #| inspect(b.index_of(3), content="2") #| inspect(b.index_of(4), content="2") #| inspect(b.index_of(5), content="2") #| inspect(b.index_of(6), content="3") #|} #|test "Bitset::union" { #| let b1 = empty_bitset.add(2).add(3) #| let b2 = empty_bitset.add(0).add(1) #| let b3 = b1.union(b2) #| inspect(b3.has(0), content="true") #| inspect(b3.has(1), content="true") #| inspect(b3.has(2), content="true") #| inspect(b3.has(3), content="true") #|} #|test "Bitset::intersection" { #| let b1 = empty_bitset.add(2).add(3) #| let b2 = empty_bitset.add(0).add(1).add(2) #| let b3 = b1.intersection(b2) #| inspect(b3.has(0), content="false") #| inspect(b3.has(1), content="false") #| inspect(b3.has(2), content="true") #| inspect(b3.has(3), content="false") #|} #|test "Bitset::remove" { #| let b = empty_bitset.add(2).add(3) #| inspect(b.has(2), content="true") #| inspect(b.has(3), content="true") #| inspect(b.index_of(2), content="0") #| inspect(b.index_of(3), content="1") #| let b = b.remove(2) #| inspect(b.has(2), content="false") #| inspect(b.has(3), content="true") #| inspect(b.index_of(3), content="0") #|} #|test "Bitset::remove" { #| let b = empty_bitset.add(2).add(3) #| inspect(b.has(2), content="true") #| inspect(b.has(3), content="true") #| inspect(b.index_of(2), content="0") #| inspect(b.index_of(3), content="1") #| let b = b.remove(2) #| inspect(b.has(2), content="false") #| inspect(b.has(3), content="true") #| inspect(b.index_of(3), content="0") #|} #|test "Bitset::size" { #| let b = empty_bitset #| inspect(b.size(), content="0") #| let b = b.add(0) #| inspect(b.size(), content="1") #| let b = b.add(1) #| inspect(b.size(), content="2") #| let b = b.add(1) #| inspect(b.size(), content="2") #|} #|test "Bitset::ctpop" { #| inspect( #| ([0, 0xf0f0f0f0, 0x3c3c0ff0] : Array[_]).map(x => x.popcnt()), #| content="[0, 16, 16]", #| ) #|} ), "sparse_array.mbt": ( #|pub(all) struct SparseArray[X] { #| elem_info : Bitset #| data : FixedArray[X] #|} derive(Eq) #|pub fn[X] empty() -> SparseArray[X] { #| { elem_info: empty_bitset, data: [] } #|} #|pub fn[X] singleton(idx : Int, value : X) -> SparseArray[X] { #| { elem_info: empty_bitset.add(idx), data: [value] } #|} #|pub fn[X] op_get(self : SparseArray[X], idx : Int) -> X? { #| if self.elem_info.has(idx) { #| Some(self.data[self.elem_info.index_of(idx)]) #| } else { #| None #| } #|} #|fn[X] unsafe_get(self : SparseArray[X], idx : Int) -> X { #| self.data[self.elem_info.index_of(idx)] #|} #|pub fn[X] doubleton( #| idx1 : Int, #| value1 : X, #| idx2 : Int, #| value2 : X, #|) -> SparseArray[X] { #| { #| elem_info: empty_bitset.add(idx1).add(idx2), #| data: if idx1 < idx2 { #| [value1, value2] #| } else { #| [value2, value1] #| }, #| } #|} #|pub fn[X] add(self : SparseArray[X], idx : Int, value : X) -> SparseArray[X] { #| let old_data = self.data #| let old_len = old_data.length() #| let new_len = old_len + 1 #| let pos_of_new_item = self.elem_info.index_of(idx) #| let new_data = FixedArray::make(new_len, value) #| old_data.blit_to(new_data, len=pos_of_new_item) #| old_data.blit_to( #| new_data, #| len=old_len - pos_of_new_item, #| src_offset=pos_of_new_item, #| dst_offset=pos_of_new_item + 1, #| ) #| { elem_info: self.elem_info.add(idx), data: new_data } #|} #|pub fn[X] remove(self : SparseArray[X], idx : Int) -> SparseArray[X] { #| let old_data = self.data #| let old_len = old_data.length() #| let pos_of_removed_item = self.elem_info.index_of(idx) #| let new_data = FixedArray::make(old_len - 1, old_data.unsafe_get(0)) #| old_data.blit_to( #| new_data, #| len=pos_of_removed_item, #| src_offset=0, #| dst_offset=0, #| ) #| old_data.blit_to( #| new_data, #| len=old_len - pos_of_removed_item - 1, #| src_offset=pos_of_removed_item + 1, #| dst_offset=pos_of_removed_item, #| ) #| { elem_info: self.elem_info.remove(idx), data: new_data } #|} #|pub fn[X] SparseArray::union( #| self : SparseArray[X], #| other : SparseArray[X], #| f : (X, X) -> X raise?, #|) -> SparseArray[X] raise? { #| let union_elem_info = self.elem_info.union(other.elem_info) #| let data = FixedArray::make(union_elem_info.size(), self.data[0]) #| for rest = union_elem_info, index = 0; rest != empty_bitset; { #| let idx = rest.first_idx() #| data[index] = match self[idx] { #| None => other.unsafe_get(idx) #| Some(value1) => #| match other[idx] { #| None => value1 #| Some(value2) => f(value1, value2) #| } #| } #| continue rest.remove(idx), index + 1 #| } #| { elem_info: union_elem_info, data } #|} #|fn[A] FixedArray::copy_prefix( #| self : FixedArray[A], #| len~ : Int, #|) -> FixedArray[A] { #| let res = FixedArray::make(len, self[0]) #| FixedArray::unsafe_blit(res, 0, self, 0, len) #| res #|} #|pub fn[X] SparseArray::intersection( #| self : SparseArray[X], #| other : SparseArray[X], #| f : (X, X) -> X? raise?, #|) -> SparseArray[X]? raise? { #| let inter_elem_info = self.elem_info.intersection(other.elem_info) #| guard inter_elem_info != 0 else { return None } #| let data = FixedArray::make(inter_elem_info.size(), self.data[0]) #| for rest = inter_elem_info, index = 0, elem_info = inter_elem_info; rest != 0; { #| let idx = rest.first_idx() #| match f(self.unsafe_get(idx), other.unsafe_get(idx)) { #| Some(value) => { #| data[index] = value #| continue rest.remove(idx), index + 1, elem_info #| } #| None => continue rest.remove(idx), index, elem_info.remove(idx) #| } #| } else { #| if elem_info == empty_bitset { #| None #| } else if elem_info == inter_elem_info { #| Some({ elem_info, data }) #| } else { #| Some({ elem_info, data: data.copy_prefix(len=index) }) #| } #| } #|} #|pub fn[X] SparseArray::difference( #| self : SparseArray[X], #| other : SparseArray[X], #| f : (X, X) -> X?, #|) -> SparseArray[X]? { #| let self_elem_info = self.elem_info #| let data = FixedArray::make(self_elem_info.size(), self.data[0]) #| for rest = self_elem_info, index = 0, elem_info = self_elem_info; rest != #| empty_bitset; { #| let idx = rest.first_idx() #| match other[idx] { #| None => { #| data[index] = self.unsafe_get(idx) #| continue rest.remove(idx), index + 1, elem_info #| } #| Some(value2) => #| match f(self.unsafe_get(idx), value2) { #| None => continue rest.remove(idx), index, elem_info.remove(idx) #| Some(v) => { #| data[index] = v #| continue rest.remove(idx), index + 1, elem_info #| } #| } #| } #| } else { #| if elem_info == empty_bitset { #| None #| } else if elem_info == self_elem_info { #| Some({ elem_info, data }) #| } else { #| Some({ elem_info, data: data.copy_prefix(len=index) }) #| } #| } #|} #|pub fn[X, Y] SparseArray::map( #| self : SparseArray[X], #| f : (X) -> Y raise?, #|) -> SparseArray[Y] raise? { #| { elem_info: self.elem_info, data: self.data.map(f) } #|} #|pub fn[X] SparseArray::filter( #| self : SparseArray[X], #| pred : (X) -> X? raise?, #|) -> SparseArray[X]? raise? { #| let self_elem_info = self.elem_info #| let data = FixedArray::make(self_elem_info.size(), self.data[0]) #| for rest = self_elem_info, index = 0, elem_info = self_elem_info; rest != #| empty_bitset; { #| let idx = rest.first_idx() #| match pred(self.unsafe_get(idx)) { #| None => continue rest.remove(idx), index, elem_info.remove(idx) #| Some(v) => { #| data[index] = v #| continue rest.remove(idx), index + 1, elem_info #| } #| } #| } else { #| if elem_info == empty_bitset { #| None #| } else if elem_info == self_elem_info { #| Some({ elem_info, data }) #| } else { #| Some({ elem_info, data: data.copy_prefix(len=index) }) #| } #| } #|} #|pub fn[X] replace( #| self : SparseArray[X], #| idx : Int, #| value : X, #|) -> SparseArray[X] { #| let new_data = self.data.copy() #| new_data[self.elem_info.index_of(idx)] = value #| { elem_info: self.elem_info, data: new_data } #|} #|pub fn[X] size(self : SparseArray[X]) -> Int { #| self.data.length() #|} #|pub fn[X] each(self : SparseArray[X], f : (X) -> Unit raise?) -> Unit raise? { #| for i in 0.. T[A] raise @json.JsonDecodeError { #| @json.from_json(json) #|} #|#deprecated #|#coverage.skip #|pub fn[A] init_(self : T[A]) -> T[A] { #| fn aux(self) { #| match self { #| Nil => Nil #| Cons(_, Nil) => Nil #| Cons(head, tail) => Cons(head, aux(tail)) #| } #| } #| aux(self) #|} #|#deprecated("use `==` instead") #|pub fn[A : Eq] equal(self : T[A], other : T[A]) -> Bool { #| loop (self, other) { #| (Nil, Nil) => true #| (Cons(h, t), Cons(h1, t1)) => if h == h1 { continue (t, t1) } else { false } #| (_, _) => false #| } #|} #|#deprecated("use `@immut/list.from_array` instead") #|#coverage.skip #|pub fn[A] T::from_array(arr : Array[A]) -> T[A] { #| from_array(arr) #|} #|#deprecated("use `@immut/list.default` instead") #|#coverage.skip #|pub fn[X] T::default() -> T[X] { #| Nil #|} #|#deprecated("use `@immut/list.from_iter` instead") #|#coverage.skip #|pub fn[A] T::from_iter(iter : Iter[A]) -> T[A] { #| from_iter(iter) #|} #|#deprecated("use `@immut/list.of` instead") #|#coverage.skip #|pub fn[A] T::of(arr : FixedArray[A]) -> T[A] { #| of(arr) #|} ), "list.mbt": ( #|#deprecated("use `@list` instead") #|pub fn[A] add(self : T[A], head : A) -> T[A] { #| Cons(head, self) #|} #|pub impl[A : Show] Show for T[A] with output(xs, logger) { #| logger.write_iter(xs.iter(), prefix="@list.of([", suffix="])") #|} #|pub impl[A : ToJson] ToJson for T[A] with to_json(self) { #| let capacity = self.length() #| guard capacity != 0 else { return [] } #| let jsons = Array::new(capacity~) #| for a in self { #| jsons.push(a.to_json()) #| } #| Json::array(jsons) #|} #|#deprecated("use `@list` instead") #|pub fn[A : ToJson] to_json(self : T[A]) -> Json { #| ToJson::to_json(self) #|} #|pub impl[A : @json.FromJson] @json.FromJson for T[A] with from_json(json, path) { #| guard json is Array(arr) else { #| raise @json.JsonDecodeError((path, "@immut/list.from_json: expected array")) #| } #| for i = arr.length() - 1, list = Nil; i >= 0; { #| continue i - 1, list.add(A::from_json(arr[i], path.add_index(i))) #| } else { #| list #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A : @json.FromJson] from_json( #| json : Json, #|) -> T[A] raise @json.JsonDecodeError { #| @json.from_json(json) #|} #|#deprecated("use `@list` instead") #|pub fn[A] from_array(arr : Array[A]) -> T[A] { #| for i = arr.length() - 1, list = Nil; i >= 0; { #| continue i - 1, Cons(arr[i], list) #| } else { #| list #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A] length(self : T[A]) -> Int { #| loop (self, 0) { #| (Nil, len) => len #| (Cons(_, rest), acc) => continue (rest, acc + 1) #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A] each(self : T[A], f : (A) -> Unit raise?) -> Unit raise? { #| loop self { #| Nil => () #| Cons(head, tail) => { #| f(head) #| continue tail #| } #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A] eachi(self : T[A], f : (Int, A) -> Unit raise?) -> Unit raise? { #| loop (self, 0) { #| (Nil, _) => () #| (Cons(x, xs), i) => { #| f(i, x) #| continue (xs, i + 1) #| } #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A, B] map(self : T[A], f : (A) -> B) -> T[B] { #| match self { #| Nil => Nil #| Cons(head, tail) => Cons(f(head), tail.map(f)) #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A, B] mapi(self : T[A], f : (Int, A) -> B raise?) -> T[B] raise? { #| fn go(xs : T[A], i : Int, f : (Int, A) -> B raise?) -> T[B] raise? { #| match xs { #| Nil => Nil #| Cons(x, xs) => Cons(f(i, x), go(xs, i + 1, f)) #| } #| } #| go(self, 0, f) #|} #|#deprecated("use `@list` instead") #|pub fn[A, B] rev_map(self : T[A], f : (A) -> B raise?) -> T[B] raise? { #| loop (Nil, self) { #| (acc, Nil) => acc #| (acc, Cons(x, xs)) => continue (Cons(f(x), acc), xs) #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A] to_array(self : T[A]) -> Array[A] { #| match self { #| Nil => [] #| Cons(x, xs) => { #| let arr = [x] #| loop xs { #| Nil => () #| Cons(x, xs) => { #| arr.push(x) #| continue xs #| } #| } #| arr #| } #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A] filter(self : T[A], f : (A) -> Bool raise?) -> T[A] raise? { #| match self { #| Nil => Nil #| Cons(head, tail) => #| if f(head) { #| Cons(head, tail.filter(f)) #| } else { #| tail.filter(f) #| } #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A] all(self : T[A], f : (A) -> Bool raise?) -> Bool raise? { #| loop self { #| Nil => true #| Cons(head, tail) => if f(head) { continue tail } else { false } #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A] any(self : T[A], f : (A) -> Bool raise?) -> Bool raise? { #| match self { #| Nil => false #| Cons(head, tail) => f(head) || tail.any(f) #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A] tail(self : T[A]) -> T[A] { #| match self { #| Nil => Nil #| Cons(_, tail) => tail #| } #|} #|#internal(unsafe, "Panic if the list is empty") #|#deprecated("use `@list` instead") #|pub fn[A] unsafe_head(self : T[A]) -> A { #| match self { #| Nil => abort("head of empty list") #| Cons(head, _) => head #| } #|} #|#coverage.skip #|#deprecated("use `@list` instead") #|pub fn[A] head_exn(self : T[A]) -> A { #| self.unsafe_head() #|} #|#deprecated("use `@list` instead") #|pub fn[A] head(self : T[A]) -> A? { #| match self { #| Nil => None #| Cons(head, _) => Some(head) #| } #|} #|#internal(unsafe, "Panic if the list is empty") #|#deprecated("use `@list` instead") #|pub fn[A] unsafe_last(self : T[A]) -> A { #| loop self { #| Nil => abort("last of empty list") #| Cons(head, Nil) => head #| Cons(_, tail) => continue tail #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A] last(self : T[A]) -> A? { #| loop self { #| Nil => None #| Cons(head, Nil) => Some(head) #| Cons(_, tail) => continue tail #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A] concat(self : T[A], other : T[A]) -> T[A] { #| match self { #| Nil => other #| Cons(head, tail) => Cons(head, tail.concat(other)) #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A] rev_concat(self : T[A], other : T[A]) -> T[A] { #| loop (self, other) { #| (Nil, other) => other #| (Cons(head, tail), other) => continue (tail, Cons(head, other)) #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A] rev(self : T[A]) -> T[A] { #| self.rev_concat(Nil) #|} #|#deprecated("use `@list` instead") #|pub fn[A, B] fold(self : T[A], init~ : B, f : (B, A) -> B raise?) -> B raise? { #| match self { #| Nil => init #| Cons(head, tail) => tail.fold(f, init=f(init, head)) #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A, B] rev_fold( #| self : T[A], #| init~ : B, #| f : (A, B) -> B raise?, #|) -> B raise? { #| let xs = self.to_array() #| let mut acc = init #| for x in xs.rev_iter() { #| acc = f(x, acc) #| } #| acc #|} #|#coverage.skip #|#deprecated("use `@list` instead") #|pub fn[A, B] fold_left( #| self : T[A], #| f : (B, A) -> B raise?, #| init~ : B, #|) -> B raise? { #| self.fold(init~, f) #|} #|#coverage.skip #|#deprecated("use `@list.rev_fold` instead") #|pub fn[A, B] fold_right( #| self : T[A], #| f : (A, B) -> B raise?, #| init~ : B, #|) -> B raise? { #| match self { #| Nil => init #| Cons(head, tail) => f(head, tail.rev_fold(f, init~)) #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A, B] foldi( #| self : T[A], #| init~ : B, #| f : (Int, B, A) -> B raise?, #|) -> B raise? { #| fn go(xs : T[A], i : Int, f : (Int, B, A) -> B raise?, acc : B) -> B raise? { #| match xs { #| Nil => acc #| Cons(x, xs) => go(xs, i + 1, f, f(i, acc, x)) #| } #| } #| go(self, 0, f, init) #|} #|#deprecated("use `@list` instead") #|pub fn[A, B] rev_foldi( #| self : T[A], #| init~ : B, #| f : (Int, A, B) -> B raise?, #|) -> B raise? { #| fn go(xs : T[A], i : Int, f : (Int, A, B) -> B raise?, acc : B) -> B raise? { #| match xs { #| Nil => acc #| Cons(x, xs) => f(i, x, go(xs, i + 1, f, acc)) #| } #| } #| go(self, 0, f, init) #|} #|#deprecated("use `@list.foldi` instead") #|pub fn[A, B] fold_lefti( #| self : T[A], #| f : (Int, B, A) -> B raise?, #| init~ : B, #|) -> B raise? { #| fn go(xs : T[A], i : Int, f : (Int, B, A) -> B raise?, acc : B) -> B raise? { #| match xs { #| Nil => acc #| Cons(x, xs) => go(xs, i + 1, f, f(i, acc, x)) #| } #| } #| go(self, 0, f, init) #|} #|#deprecated("use `@list.rev_foldi` instead") #|pub fn[A, B] fold_righti( #| self : T[A], #| f : (Int, A, B) -> B raise?, #| init~ : B, #|) -> B raise? { #| fn go(xs : T[A], i : Int, f : (Int, A, B) -> B raise?, acc : B) -> B raise? { #| match xs { #| Nil => acc #| Cons(x, xs) => f(i, x, go(xs, i + 1, f, acc)) #| } #| } #| go(self, 0, f, init) #|} #|#deprecated("use `@list` instead") #|pub fn[A, B] zip(self : T[A], other : T[B]) -> T[(A, B)]? { #| let mut acc = Nil #| let res = loop (self, other) { #| (Nil, Nil) => break Some(acc) #| (Cons(x, xs), Cons(y, ys)) => { #| acc = Cons((x, y), acc) #| continue (xs, ys) #| } #| (_, _) => break None #| } #| res.map(T::rev) #|} #|#deprecated("use `@list` instead") #|pub fn[A, B] concat_map(self : T[A], f : (A) -> T[B]) -> T[B] { #| self.flat_map(f) #|} #|#deprecated("use `@list` instead") #|pub fn[A, B] flat_map(self : T[A], f : (A) -> T[B] raise?) -> T[B] raise? { #| match self { #| Nil => Nil #| Cons(head, tail) => f(head).concat(tail.flat_map(f)) #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A, B] filter_map(self : T[A], f : (A) -> B?) -> T[B] { #| loop (Nil, self) { #| (acc, Nil) => acc.rev() #| (acc, Cons(x, xs)) => #| match f(x) { #| Some(v) => continue (acc.add(v), xs) #| None => continue (acc, xs) #| } #| } #|} #|#internal(unsafe, "Panic if the index is out of bounds") #|#deprecated("use `@list` instead") #|pub fn[A] unsafe_nth(self : T[A], n : Int) -> A { #| loop (self, n) { #| (Nil, _) => abort("nth: index out of bounds") #| (Cons(head, _), 0) => head #| (Cons(_, tail), n) => continue (tail, n - 1) #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A] nth_exn(self : T[A], n : Int) -> A { #| self.unsafe_nth(n) #|} #|#deprecated("use `@list` instead") #|pub fn[A] nth(self : T[A], n : Int) -> A? { #| loop (self, n) { #| (Nil, _) => None #| (Cons(head, _), 0) => Some(head) #| (Cons(_, tail), n) => continue (tail, n - 1) #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A] repeat(n : Int, x : A) -> T[A] { #| if n == 0 { #| Nil #| } else { #| Cons(x, repeat(n - 1, x)) #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A] intersperse(self : T[A], separator : A) -> T[A] { #| match self { #| Nil => Nil #| Cons(head, Nil) => Cons(head, Nil) #| Cons(head, tail) => Cons(head, Cons(separator, tail.intersperse(separator))) #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A] is_empty(self : T[A]) -> Bool { #| self is Nil #|} #|#deprecated("use `@list` instead") #|pub fn[A, B] unzip(self : T[(A, B)]) -> (T[A], T[B]) { #| let mut xs = Nil #| let mut ys = Nil #| loop self.rev() { #| Nil => break (xs, ys) #| Cons((x, y), tail) => { #| xs = Cons(x, xs) #| ys = Cons(y, ys) #| continue tail #| } #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A] flatten(self : T[T[A]]) -> T[A] { #| match self { #| Nil => Nil #| Cons(head, tail) => head.concat(tail.flatten()) #| } #|} #|#internal(unsafe, "Panic if the list is empty") #|#deprecated("use `@list` instead") #|pub fn[A : Compare] unsafe_maximum(self : T[A]) -> A { #| match self { #| Nil => abort("maximum: empty list") #| Cons(x, Nil) => x #| Cons(x, xs) => { #| let y = xs.unsafe_maximum() #| if x > y { #| x #| } else { #| y #| } #| } #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A : Compare] maximum(self : T[A]) -> A? { #| match self { #| Nil => None #| Cons(x, Nil) => Some(x) #| Cons(x, xs) => #| match xs.maximum() { #| None => Some(x) #| Some(y) => Some(if x > y { x } else { y }) #| } #| } #|} #|#internal(unsafe, "Panic if the list is empty") #|#deprecated("use `@list` instead") #|pub fn[A : Compare] unsafe_minimum(self : T[A]) -> A { #| match self { #| Nil => abort("minimum: empty list") #| Cons(x, Nil) => x #| Cons(x, xs) => { #| let y = xs.unsafe_minimum() #| if x < y { #| x #| } else { #| y #| } #| } #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A : Compare] minimum(self : T[A]) -> A? { #| match self { #| Nil => None #| Cons(x, Nil) => Some(x) #| Cons(x, xs) => #| match xs.minimum() { #| None => Some(x) #| Some(y) => Some(if x < y { x } else { y }) #| } #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A : Compare] sort(self : T[A]) -> T[A] { #| match self { #| Nil => Nil #| Cons(x, xs) => { #| let smaller = xs.filter(y => y < x) #| let greater = xs.filter(y => y >= x) #| smaller.sort().concat(Cons(x, greater.sort())) #| } #| } #|} #|pub impl[A] Add for T[A] with op_add(self, other) { #| self.concat(other) #|} #|#deprecated("use `@list` instead") #|pub fn[A : Eq] contains(self : T[A], value : A) -> Bool { #| loop self { #| Nil => false #| Cons(x, xs) => if x == value { true } else { continue xs } #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A, S] unfold(f : (S) -> (A, S)? raise?, init~ : S) -> T[A] raise? { #| match f(init) { #| Some((element, new_state)) => Cons(element, unfold(init=new_state, f)) #| None => Nil #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A] take(self : T[A], n : Int) -> T[A] { #| fn go(n, t) { #| match (n, t) { #| (_, Nil) => Nil #| (1, Cons(x, _)) => Cons(x, Nil) #| (n, Cons(x, xs)) => Cons(x, go(n - 1, xs)) #| } #| } #| if n <= 0 { #| Nil #| } else { #| go(n, self) #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A] drop(self : T[A], n : Int) -> T[A] { #| if n <= 0 { #| self #| } else { #| loop (n, self) { #| (_, Nil) => Nil #| (1, Cons(_, xs)) => xs #| (n, Cons(_, xs)) => continue (n - 1, xs) #| } #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A] take_while(self : T[A], p : (A) -> Bool) -> T[A] { #| match self { #| Nil => Nil #| Cons(x, xs) => if p(x) { Cons(x, xs.take_while(p)) } else { Nil } #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A] drop_while(self : T[A], p : (A) -> Bool raise?) -> T[A] raise? { #| loop self { #| Nil => Nil #| Cons(x, xs) => if p(x) { continue xs } else { Cons(x, xs) } #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A, E] scan_left( #| self : T[A], #| f : (E, A) -> E raise?, #| init~ : E, #|) -> T[E] raise? { #| Cons( #| init, #| match self { #| Nil => Nil #| Cons(x, xs) => xs.scan_left(f, init=f(init, x)) #| }, #| ) #|} #|#deprecated("use `@list` instead") #|pub fn[A, B] scan_right( #| self : T[A], #| f : (A, B) -> B raise?, #| init~ : B, #|) -> T[B] raise? { #| match self { #| Nil => Cons(init, Nil) #| Cons(x, xs) => { #| let qs = xs.scan_right(f, init~) #| Cons(f(x, qs.unsafe_head()), qs) #| } #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A : Eq, B] lookup(self : T[(A, B)], v : A) -> B? { #| loop self { #| Nil => None #| Cons((x, y), xs) => if x == v { Some(y) } else { continue xs } #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A] find(self : T[A], f : (A) -> Bool raise?) -> A? raise? { #| loop self { #| Nil => None #| Cons(element, list) => #| if f(element) { #| Some(element) #| } else { #| continue list #| } #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A] findi(self : T[A], f : (A, Int) -> Bool raise?) -> A? raise? { #| loop (self, 0) { #| (list, index) => #| match list { #| Nil => None #| Cons(element, list) => #| if f(element, index) { #| Some(element) #| } else { #| continue (list, index + 1) #| } #| } #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A] remove_at(self : T[A], index : Int) -> T[A] { #| match (index, self) { #| (0, Cons(_, tail)) => tail #| (_, Cons(head, tail)) => Cons(head, tail.remove_at(index - 1)) #| (_, Nil) => Nil #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A : Eq] remove(self : T[A], elem : A) -> T[A] { #| match self { #| Nil => Nil #| Cons(head, tail) => #| if head == elem { #| tail #| } else { #| Cons(head, tail.remove(elem)) #| } #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A : Eq] is_prefix(self : T[A], prefix : T[A]) -> Bool { #| loop (self, prefix) { #| (_, Nil) => true #| (Nil, Cons(_)) => false #| (Cons(h1, t1), Cons(h2, t2)) => #| if h1 == h2 { #| continue (t1, t2) #| } else { #| false #| } #| } #|} #|#deprecated("use `@list` instead") #|pub fn[A : Eq] is_suffix(self : T[A], suffix : T[A]) -> Bool { #| self.rev().is_prefix(suffix.rev()) #|} #|#deprecated("use `@list` instead") #|pub fn[A] intercalate(self : T[T[A]], sep : T[A]) -> T[A] { #| self.intersperse(sep).flatten() #|} #|pub impl[X] Default for T[X] with default() { #| Nil #|} #|#deprecated("use `@list` instead") #|pub fn[X] default() -> T[X] { #| Nil #|} #|#deprecated("use `@list` instead") #|pub fn[A] iter(self : T[A]) -> Iter[A] { #| Iter::new(yield_ => loop self { #| Nil => IterContinue #| Cons(head, tail) => { #| if yield_(head) == IterEnd { #| break IterEnd #| } #| continue tail #| } #| }) #|} #|#deprecated("use `@list` instead") #|pub fn[A] iter2(self : T[A]) -> Iter2[Int, A] { #| Iter2::new(yield_ => loop (self, 0) { #| (Nil, _) => IterEnd #| (Cons(head, tail), i) => { #| if yield_(i, head) == IterEnd { #| break IterEnd #| } #| continue (tail, i + 1) #| } #| }) #|} #|#deprecated("use `@list` instead") #|pub fn[A] from_iter(iter : Iter[A]) -> T[A] { #| iter.fold(init=Nil, (acc, e) => Cons(e, acc)).rev() #|} #|#deprecated("use `@list` instead") #|pub fn[A] from_iter_rev(iter : Iter[A]) -> T[A] { #| iter.fold(init=Nil, (acc, e) => Cons(e, acc)) #|} #|#deprecated("use `@list` instead") #|pub fn[A] of(arr : FixedArray[A]) -> T[A] { #| for i = arr.length() - 1, list = Nil; i >= 0; { #| continue i - 1, Cons(arr[i], list) #| } else { #| list #| } #|} #|pub impl[X : @quickcheck.Arbitrary] @quickcheck.Arbitrary for T[X] with arbitrary( #| size, #| rs, #|) { #| @quickcheck.Arbitrary::arbitrary(size, rs) |> from_array #|} #|#deprecated("use `@list` instead") #|pub fn[A] singleton(x : A) -> T[A] { #| Cons(x, Nil) #|} #|pub impl[A : Hash] Hash for T[A] with hash_combine(self, hasher) { #| for e in self { #| hasher.combine(e) #| } #|} #|pub impl[A : Compare] Compare for T[A] with compare(self, other) { #| loop (self, other) { #| (Nil, Nil) => 0 #| (Nil, Cons(_, _)) => -1 #| (Cons(_, _), Nil) => 1 #| (Cons(x, xs), Cons(y, ys)) => { #| let cmp = x.compare(y) #| if cmp != 0 { #| break cmp #| } else { #| continue (xs, ys) #| } #| } #| } #|} ), "types.mbt": ( #|#deprecated("use `@list` instead") #|pub(all) enum T[A] { #| Nil #| Cons(A, T[A]) #|} derive(Eq) ), }, ) ///| let moonbitlang_core_immut_priority_queue_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/immut/priority_queue", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/array": moonbitlang_core_array_module, "moonbitlang/core/quickcheck": moonbitlang_core_quickcheck_module, }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/builtin", #| "moonbitlang/core/array", #| "moonbitlang/core/quickcheck" #| ], #| "test-import": ["moonbitlang/core/random", "moonbitlang/core/json"], #| "targets": { #| "panic_test.mbt": ["not", "native", "llvm"] #| } #|} ), "deprecated.mbt": ( #|#deprecated("Use `unsafe_pop` instead") #|#coverage.skip #|pub fn[A : Compare] pop_exn(self : T[A]) -> T[A] { #| self.unsafe_pop() #|} ), "priority_queue.mbt": ( #|pub fn[A] new() -> T[A] { #| { node: Empty, size: 0 } #|} #|pub fn[A : Compare] from_array(array : Array[A]) -> T[A] { #| let mut pq = new() #| for i in 0.. Array[A] { #| let arr : Array[A] = [] #| fn go(x : Node[A]) { #| match x { #| Empty => return #| Leaf(a) => arr.push(a) #| Branch(a, left=l, right=r) => { #| arr.push(a) #| go(l) #| go(r) #| } #| } #| } #| go(self.node) #| arr.sort_by((x, y) => y.compare(x)) #| arr #|} #|pub fn[A : Compare] iter(self : T[A]) -> Iter[A] { #| Iter::new(yield_ => { #| let arr = self.to_array() #| for i in 0.. T[A] { #| iter.fold(init=new(), (s, e) => s.push(e)) #|} #|priv struct Path(Int) #|fn path(size : Int) -> Path { #| loop (size, 0) { #| (1, y) => Path(y) #| (x, y) => continue (x >> 1, (y << 1) | (x & 1)) #| } #|} #|fn is_left(self : Path) -> Bool { #| (self.0 & 1) == 0 #|} #|fn next(self : Path) -> Path { #| Path(self.0 >> 1) #|} #|pub fn[A : Compare] pop(self : T[A]) -> T[A]? { #| match self.node { #| Empty => None #| Leaf(_) => Some({ node: Empty, size: 0 }) #| Branch(_) => { #| let (value, temp) = self.node.remove_last_leaf(path(self.size)) #| Some({ node: temp.change_and_down(value), size: self.size - 1 }) #| } #| } #|} #|fn[A : Compare] remove_last_leaf(self : Node[A], path : Path) -> (A, Node[A]) { #| match self { #| Empty => abort("Priority queue is empty!") #| Leaf(a) => (a, Empty) #| Branch(a, left=Leaf(l_top), right=Empty) => (l_top, Leaf(a)) #| Branch(a, left=l, right=r) => #| if path.is_left() { #| let (e, ld) = l.remove_last_leaf(path.next()) #| (e, Branch(a, left=ld, right=r)) #| } else { #| let (e, rd) = r.remove_last_leaf(path.next()) #| (e, Branch(a, left=l, right=rd)) #| } #| } #|} #|fn[A : Compare] change_and_down(self : Node[A], value : A) -> Node[A] { #| match self { #| Empty => abort("unreachable") #| Leaf(_) => Leaf(value) #| Branch(_, left=l, right=r) => #| match (l, r) { #| (Leaf(l_top), Empty) => #| if value >= l_top { #| Branch(value, left=l, right=Empty) #| } else { #| Branch(l_top, left=Leaf(value), right=Empty) #| } #| (Branch(l_top, ..) | Leaf(l_top), Branch(r_top, ..) | Leaf(r_top)) => #| if value >= l_top && value >= r_top { #| Branch(value, left=l, right=r) #| } else if l_top >= r_top { #| Branch(l_top, left=l.change_and_down(value), right=r) #| } else { #| Branch(r_top, left=l, right=r.change_and_down(value)) #| } #| _ => abort("unreachable") #| } #| } #|} #|#internal(unsafe, "Panics if the queue is empty.") #|pub fn[A : Compare] unsafe_pop(self : T[A]) -> T[A] { #| match self.node { #| Empty => abort("Priority queue is empty!") #| Leaf(_) => { node: Empty, size: 0 } #| Branch(_) => { #| let (value, temp) = self.node.remove_last_leaf(path(self.size)) #| { node: temp.change_and_down(value), size: self.size - 1 } #| } #| } #|} #|pub fn[A : Compare] push(self : T[A], value : A) -> T[A] { #| match self.node { #| Empty => { node: Leaf(value), size: 1 } #| Leaf(_) | Branch(_) => { #| let size = self.size + 1 #| { node: self.node.push(value, path(size)), size } #| } #| } #|} #|fn[A : Compare] Node::push(self : Node[A], value : A, path : Path) -> Node[A] { #| match self { #| Empty => Leaf(value) #| Leaf(a) => { #| let (high, low) = if a > value { (a, value) } else { (value, a) } #| Branch(high, left=Leaf(low), right=Empty) #| } #| Branch(a, left=l, right=r) => { #| let (high, low) = if a > value { (a, value) } else { (value, a) } #| if path.is_left() { #| Branch(high, left=l.push(low, path.next()), right=r) #| } else { #| Branch(high, left=l, right=r.push(low, path.next())) #| } #| } #| } #|} #|pub fn[A] peek(self : T[A]) -> A? { #| match self.node { #| Empty => None #| Leaf(a) => Some(a) #| Branch(a, ..) => Some(a) #| } #|} #|pub fn[A] is_empty(self : T[A]) -> Bool { #| self.node is Empty #|} #|pub fn[A] length(self : T[A]) -> Int { #| self.size #|} #|pub fn[A : Compare] of(arr : FixedArray[A]) -> T[A] { #| let mut pq = new() #| for i in 0.. from_array #|} #|pub impl[A : Compare] Eq for T[A] with op_equal(self, other) { #| self.length() == other.length() && self.to_array() == other.to_array() #|} #|pub impl[A : Hash + Compare] Hash for T[A] with hash_combine(self, hasher) { #| for e in self { #| hasher.combine(e) #| } #|} #|pub impl[A : Compare] Compare for T[A] with compare(self, other) { #| let len_cmp = self.length().compare(other.length()) #| if len_cmp != 0 { #| return len_cmp #| } #| let self_arr = self.to_array() #| let other_arr = other.to_array() #| for i in 0.. T[K, V] { #| self.add(key, value) #|} #|#deprecated("use `@immut/sorted_map.new` instead") #|#coverage.skip #|pub fn[K, V] T::new() -> T[K, V] { #| Empty #|} #|#deprecated("use `@immut/sorted_map.singleton` instead") #|#coverage.skip #|pub fn[K, V] T::singleton(key : K, value : V) -> T[K, V] { #| singleton(key, value) #|} #|#deprecated("use `@immut/sorted_map.from_array` instead") #|#coverage.skip #|pub fn[K : Compare, V] T::from_array(array : Array[(K, V)]) -> T[K, V] { #| from_array(array) #|} #|#deprecated("use `@immut/sorted_map.from_iter` instead") #|#coverage.skip #|pub fn[K : Compare, V] T::from_iter(iter : Iter[(K, V)]) -> T[K, V] { #| from_iter(iter) #|} #|#deprecated("use `@immut/sorted_map.of` instead") #|#coverage.skip #|pub fn[K : Compare, V] T::of(array : FixedArray[(K, V)]) -> T[K, V] { #| of(array) #|} #|#deprecated("use `@immut/sorted_map.from_json` instead") #|#coverage.skip #|pub fn[V : @json.FromJson] T::from_json( #| json : Json, #|) -> T[String, V] raise @json.JsonDecodeError { #| @json.from_json(json) #|} ), "inorder_iterator.mbt": ( #|priv struct InorderIterator[K, V](Array[T[K, V]]) #|fn[K, V] InorderIterator::new(root : T[K, V]) -> InorderIterator[K, V] { #| let it = InorderIterator([]) #| it.move_left(root) #| it #|} #|fn[K, V] InorderIterator::move_left( #| self : InorderIterator[K, V], #| node : T[K, V], #|) -> Unit { #| loop node { #| Empty => () #| Tree(_, left, _, ..) as curr => { #| let InorderIterator(self) = self #| self.push(curr) #| continue left #| } #| } #|} #|fn[K, V] InorderIterator::next(self : InorderIterator[K, V]) -> (K, V)? { #| let InorderIterator(s) = self #| guard s.pop() is Some(curr) else { return None } #| guard curr is Tree(key, _, right, value~, ..) #| self.move_left(right) #| Some((key, value)) #|} #|test "InorderIterator" { #| let arr = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7)] #| let set = from_array(arr) #| let iter = InorderIterator::new(set) #| for i = 0; ; i = i + 1 { #| match iter.next() { #| None => break #| Some(value) => assert_eq(value, arr[i]) #| } #| } #|} ), "map.mbt": ( #|pub fn[K : Compare, V] add(self : T[K, V], key : K, value : V) -> T[K, V] { #| match self { #| Empty => singleton(key, value) #| Tree(k, value=v, l, r, ..) => { #| let c = key.compare(k) #| if c == 0 { #| make_tree(k, value, l, r) #| } else if c < 0 { #| balance(k, v, l.add(key, value), r) #| } else { #| balance(k, v, l, r.add(key, value)) #| } #| } #| } #|} #|fn[K : Compare, V] split_max(self : T[K, V]) -> (K, V, T[K, V]) { #| match self { #| Tree(k, value=v, l, Empty, ..) => (k, v, l) #| Tree(k, value=v, l, r, ..) => { #| let (k1, v1, r) = r.split_max() #| (k1, v1, balance(k, v, l, r)) #| } #| Empty => abort("Map::split_max error") #| } #|} #|fn[K : Compare, V] split_min(self : T[K, V]) -> (K, V, T[K, V]) { #| match self { #| Tree(k, value=v, Empty, r, ..) => (k, v, r) #| Tree(k, value=v, l, r, ..) => { #| let (k1, v1, l) = l.split_min() #| (k1, v1, balance(k, v, l, r)) #| } #| Empty => abort("Map::split_min error") #| } #|} #|fn[K : Compare, V] glue(l : T[K, V], r : T[K, V]) -> T[K, V] { #| match (l, r) { #| (Empty, r) => r #| (l, Empty) => l #| (l, r) => #| if l.size() > r.size() { #| let (k, v, l) = l.split_max() #| balance(k, v, l, r) #| } else { #| let (k, v, r) = r.split_min() #| balance(k, v, l, r) #| } #| } #|} #|pub fn[K : Compare, V] remove(self : T[K, V], key : K) -> T[K, V] { #| match self { #| Empty => Empty #| Tree(k, value=v, l, r, ..) => { #| let c = key.compare(k) #| if c == 0 { #| glue(l, r) #| } else if c < 0 { #| balance(k, v, l.remove(key), r) #| } else { #| balance(k, v, l, r.remove(key)) #| } #| } #| } #|} #|pub fn[K : Compare, V] filter( #| self : T[K, V], #| pred : (V) -> Bool raise?, #|) -> T[K, V] raise? { #| self.filter_with_key((_k, v) => pred(v)) #|} #|pub fn[K : Compare, V] filter_with_key( #| self : T[K, V], #| pred : (K, V) -> Bool raise?, #|) -> T[K, V] raise? { #| match self { #| Empty => Empty #| Tree(k, value=v, l, r, ..) => #| if pred(k, v) { #| balance(k, v, l.filter_with_key(pred), r.filter_with_key(pred)) #| } else { #| glue(l.filter_with_key(pred), r.filter_with_key(pred)) #| } #| } #|} #|pub fn[K, V] to_array(self : T[K, V]) -> Array[(K, V)] { #| let arr = [] #| self.each((k, v) => arr.push((k, v))) #| arr #|} #|let ratio = 5 #|fn[K, V] balance(key : K, value : V, l : T[K, V], r : T[K, V]) -> T[K, V] { #| fn single_l(k1, v1, x, r) { #| guard r is Tree(k2, value=v2, y, z, ..) #| make_tree(k2, v2, make_tree(k1, v1, x, y), z) #| } #| fn single_r(k2, v2, l, z) { #| guard l is Tree(k1, value=v1, x, y, ..) #| make_tree(k1, v1, x, make_tree(k2, v2, y, z)) #| } #| fn double_l(k1, v1, x, r) { #| guard r is Tree(k3, value=v3, Tree(k2, value=v2, y1, y2, ..), z, ..) #| make_tree(k2, v2, make_tree(k1, v1, x, y1), make_tree(k3, v3, y2, z)) #| } #| fn double_r(k3, v3, l, z) { #| guard l is Tree(k1, value=v1, x, Tree(k2, value=v2, y1, y2, ..), ..) #| make_tree(k2, v2, make_tree(k1, v1, x, y1), make_tree(k3, v3, y2, z)) #| } #| let ln = l.size() #| let rn = r.size() #| if ln + rn < 2 { #| make_tree(key, value, l, r) #| } else if rn > ratio * ln { #| guard r is Tree(_, rl, rr, ..) #| let rln = rl.size() #| let rrn = rr.size() #| if rln < rrn { #| single_l(key, value, l, r) #| } else { #| double_l(key, value, l, r) #| } #| } else if ln > ratio * rn { #| guard l is Tree(_, ll, lr, ..) #| let lln = ll.size() #| let lrn = lr.size() #| if lrn < lln { #| single_r(key, value, l, r) #| } else { #| double_r(key, value, l, r) #| } #| } else { #| make_tree(key, value, l, r) #| } #|} #|test "from_array" { #| let m = of([(3, "three"), (8, "eight"), (1, "one"), (2, "two"), (0, "zero")]) #| inspect( #| m.debug_tree(), #| content="(3,three,(1,one,(0,zero,_,_),(2,two,_,_)),(8,eight,_,_))", #| ) #|} #|test "insert" { #| let m = of([(3, "three"), (8, "eight"), (1, "one")]) #| inspect(m.debug_tree(), content="(3,three,(1,one,_,_),(8,eight,_,_))") #| let m = m.add(5, "five").add(2, "two").add(0, "zero").add(1, "one_updated") #| inspect( #| m.debug_tree(), #| content="(3,three,(1,one_updated,(0,zero,_,_),(2,two,_,_)),(8,eight,(5,five,_,_),_))", #| ) #|} #|test "remove" { #| let m1 = of([(3, "three"), (8, "eight"), (1, "one"), (2, "two"), (0, "zero")]) #| inspect( #| m1.debug_tree(), #| content="(3,three,(1,one,(0,zero,_,_),(2,two,_,_)),(8,eight,_,_))", #| ) #| let m2 = m1.remove(1).remove(3) #| inspect(m2.debug_tree(), content="(2,two,(0,zero,_,_),(8,eight,_,_))") #| let m3 = m1.remove(8) #| inspect( #| m3.debug_tree(), #| content="(2,two,(1,one,(0,zero,_,_),_),(3,three,_,_))", #| ) #| let e : T[Int, Int] = Empty #| inspect(e.remove(1).debug_tree(), content="_") #|} #|test "contains" { #| let m = of([(3, "three"), (8, "eight"), (1, "one"), (2, "two"), (0, "zero")]) #| inspect( #| m.debug_tree(), #| content="(3,three,(1,one,(0,zero,_,_),(2,two,_,_)),(8,eight,_,_))", #| ) #| inspect(m.contains(8), content="true") #| inspect(m.contains(2), content="true") #| inspect(m.contains(4), content="false") #|} #|test "map" { #| let m = of([(3, "three"), (8, "eight"), (1, "one"), (2, "two"), (0, "zero")]) #| let n = m.map(v => v + "X") #| assert_eq( #| n.debug_tree(), #| "(3,threeX,(1,oneX,(0,zeroX,_,_),(2,twoX,_,_)),(8,eightX,_,_))", #| ) #|} #|test "map_with_key" { #| let m = of([(3, "three"), (8, "eight"), (1, "one"), (2, "two"), (0, "zero")]) #| let n = m.map_with_key((k, v) => "\{k}-\{v}") #| assert_eq( #| n.debug_tree(), #| "(3,3-three,(1,1-one,(0,0-zero,_,_),(2,2-two,_,_)),(8,8-eight,_,_))", #| ) #|} #|test "filter" { #| let m = of([(3, "three"), (8, "eight"), (1, "one"), (2, "two"), (0, "zero")]) #| let fm = m.filter(v => v.length() > 3) #| inspect(fm.debug_tree(), content="(3,three,(0,zero,_,_),(8,eight,_,_))") #|} #|test "filter_with_key" { #| let m = of([(3, "three"), (8, "eight"), (1, "one"), (2, "two"), (0, "zero")]) #| let fm = m.filter_with_key((k, v) => k > 3 && v.length() > 3) #| inspect(fm.debug_tree(), content="(8,eight,_,_)") #|} #|test "singleton" { #| let m = singleton(3, "three") #| inspect(m.debug_tree(), content="(3,three,_,_)") #|} #|test "insert" { #| let m = of([(3, "three"), (8, "eight"), (1, "one")]) #| inspect(m.debug_tree(), content="(3,three,(1,one,_,_),(8,eight,_,_))") #| let m = m.add(5, "five").add(2, "two").add(0, "zero").add(1, "one_updated") #| inspect( #| m.debug_tree(), #| content="(3,three,(1,one_updated,(0,zero,_,_),(2,two,_,_)),(8,eight,(5,five,_,_),_))", #| ) #|} #|test "remove" { #| let m = of([(3, "three"), (8, "eight"), (1, "one"), (2, "two"), (0, "zero")]) #| inspect( #| m.debug_tree(), #| content="(3,three,(1,one,(0,zero,_,_),(2,two,_,_)),(8,eight,_,_))", #| ) #| let m = m.remove(1).remove(3) #| inspect(m.debug_tree(), content="(2,two,(0,zero,_,_),(8,eight,_,_))") #|} #|test "filter" { #| let m = of([(3, "three"), (8, "eight"), (1, "one"), (2, "two"), (0, "zero")]) #| let fm = m.filter(v => v.length() > 3) #| inspect(fm.debug_tree(), content="(3,three,(0,zero,_,_),(8,eight,_,_))") #|} #|test "filter_with_key" { #| let m = of([(3, "three"), (8, "eight"), (1, "one"), (2, "two"), (0, "zero")]) #| let fm = m.filter_with_key((k, v) => k > 3 && v.length() > 3) #| inspect(fm.debug_tree(), content="(8,eight,_,_)") #|} #|test "empty" { #| let m : T[Int, Int] = new() #| inspect(m.debug_tree(), content="_") #|} #|test "split_max" { #| let m = of([(3, "three"), (8, "eight"), (1, "one"), (2, "two"), (0, "zero")]) #| assert_eq( #| m.debug_tree(), #| "(3,three,(1,one,(0,zero,_,_),(2,two,_,_)),(8,eight,_,_))", #| ) #| let (k, v, r) = m.split_max() #| inspect(k, content="8") #| inspect(v, content="eight") #| inspect( #| r.debug_tree(), #| content="(2,two,(1,one,(0,zero,_,_),_),(3,three,_,_))", #| ) #|} #|test "split_min" { #| let m = of([(3, "three"), (8, "eight"), (2, "two"), (1, "one"), (0, "zero")]) #| assert_eq( #| m.debug_tree(), #| "(3,three,(1,one,(0,zero,_,_),(2,two,_,_)),(8,eight,_,_))", #| ) #| let (k, v, r) = m.split_min() #| inspect(k, content="0") #| inspect(v, content="zero") #| inspect( #| r.debug_tree(), #| content="(3,three,(1,one,_,(2,two,_,_)),(8,eight,_,_))", #| ) #|} #|test "glue" { #| let m = of([(3, "three"), (8, "eight"), (1, "one"), (2, "two"), (0, "zero")]) #| assert_eq( #| m.debug_tree(), #| "(3,three,(1,one,(0,zero,_,_),(2,two,_,_)),(8,eight,_,_))", #| ) #| let (l, r) = match m { #| Tree(_, l, r, ..) => (l, r) #| _ => abort("unreachable") #| } #| let m = glue(l, r) #| inspect( #| m.debug_tree(), #| content="(2,two,(1,one,(0,zero,_,_),_),(8,eight,_,_))", #| ) #|} #|test "split_max with non-empty tree" { #| let m = of([(3, "three"), (8, "eight"), (1, "one"), (2, "two"), (0, "zero")]) #| let (k, v, r) = m.split_max() #| inspect(k, content="8") #| inspect(v, content="eight") #| inspect( #| r.debug_tree(), #| content="(2,two,(1,one,(0,zero,_,_),_),(3,three,_,_))", #| ) #|} ), "traits_impl.mbt": ( #|pub impl[K, V] Default for T[K, V] with default() { #| new() #|} #|pub impl[K : Eq, V : Eq] Eq for T[K, V] with op_equal(self, other) -> Bool { #| let iter = InorderIterator::new(self) #| let iter1 = InorderIterator::new(other) #| loop (iter.next(), iter1.next()) { #| (None, None) => true #| (Some(a), Some(b)) => { #| guard a == b else { break false } #| continue (iter.next(), iter1.next()) #| } #| (_, _) => false #| } #|} #|pub impl[K : Compare, V : Compare] Compare for T[K, V] with compare(self, other) -> Int { #| let iter = InorderIterator::new(self) #| let iter1 = InorderIterator::new(other) #| loop (iter.next(), iter1.next()) { #| (None, None) => 0 #| (Some(a), Some(b)) => { #| let cmp = a.compare(b) #| guard cmp == 0 else { break cmp } #| continue (iter.next(), iter1.next()) #| } #| (Some(_), None) => 1 #| (None, Some(_)) => -1 #| } #|} #|pub impl[K : @quickcheck.Arbitrary + Compare, V : @quickcheck.Arbitrary] @quickcheck.Arbitrary for T[ #| K, #| V, #|] with arbitrary(size, rs) { #| @quickcheck.Arbitrary::arbitrary(size, rs) |> from_array #|} #|pub impl[K : Hash, V : Hash] Hash for T[K, V] with hash_combine(self, hasher) { #| for e in self { #| hasher..combine(e.0)..combine(e.1) #| } #|} #|pub impl[K : Show, V : Show] Show for T[K, V] with output(self, logger) { #| logger.write_iter(self.iter(), prefix="@immut/sorted_map.of([", suffix="])") #|} #|pub impl[K : Show, V : ToJson] ToJson for T[K, V] with to_json(self) { #| let capacity = self.size() #| guard capacity != 0 else { return Json::object(Map::new()) } #| let jsons = Map::new(capacity~) #| self.each((k, v) => jsons[k.to_string()] = v.to_json()) #| Json::object(jsons) #|} #|pub impl[V : @json.FromJson] @json.FromJson for T[String, V] with from_json( #| json, #| path, #|) { #| guard json is Object(obj) else { #| raise @json.JsonDecodeError( #| (path, "@immut/sorted_map.from_json: expected object"), #| ) #| } #| let mut map = new() #| for k, v in obj { #| map = map.add(k, V::from_json(v, path.add_key(k))) #| } #| map #|} ), "types.mbt": ( #|enum T[K, V] { #| Empty #| Tree(K, value~ : V, size~ : Int, T[K, V], T[K, V]) #|} ), "utils.mbt": ( #|#deprecated("Use `new()` instead") #|#coverage.skip #|pub fn[K, V] T::empty() -> T[K, V] { #| Empty #|} #|pub fn[K, V] new() -> T[K, V] { #| Empty #|} #|pub fn[K, V] singleton(key : K, value : V) -> T[K, V] { #| Tree(key, value~, size=1, Empty, Empty) #|} #|pub fn[K : Compare, V] contains(self : T[K, V], key : K) -> Bool { #| loop self { #| Empty => false #| Tree(k, l, r, ..) => { #| let c = key.compare(k) #| if c == 0 { #| true #| } else if c < 0 { #| continue l #| } else { #| continue r #| } #| } #| } #|} #|pub fn[K, V] size(self : T[K, V]) -> Int { #| match self { #| Empty => 0 #| Tree(_) as t => t.size #| } #|} #|pub fn[K, V] is_empty(self : T[K, V]) -> Bool { #| self.size() == 0 #|} #|fn[K, V] make_tree(key : K, value : V, l : T[K, V], r : T[K, V]) -> T[K, V] { #| let size = l.size() + r.size() + 1 #| Tree(key, value~, size~, l, r) #|} #|#deprecated("Use `get` instead") #|#coverage.skip #|pub fn[K : Compare, V] lookup(self : T[K, V], key : K) -> V? { #| self.get(key) #|} #|pub fn[K : Compare, V] get(self : T[K, V], key : K) -> V? { #| loop self { #| Empty => None #| Tree(k, value~, l, r, ..) => { #| let c = key.compare(k) #| if c == 0 { #| Some(value) #| } else if c < 0 { #| continue l #| } else { #| continue r #| } #| } #| } #|} #|pub fn[K : Compare, V] op_get(self : T[K, V], key : K) -> V { #| loop self { #| Empty => panic() #| Tree(k, value~, l, r, ..) => { #| let c = key.compare(k) #| if c == 0 { #| value #| } else if c < 0 { #| continue l #| } else { #| continue r #| } #| } #| } #|} #|pub fn[K, V] each(self : T[K, V], f : (K, V) -> Unit) -> Unit { #| match self { #| Empty => () #| Tree(k, value~, l, r, ..) => { #| l.each(f) #| f(k, value) #| r.each(f) #| } #| } #|} #|pub fn[K, V] eachi(self : T[K, V], f : (Int, K, V) -> Unit) -> Unit { #| fn do_eachi(m : T[K, V], f, i) { #| match m { #| Empty => () #| Tree(k, value~, l, r, ..) => { #| do_eachi(l, f, i) #| f(l.size() + i, k, value) #| do_eachi(r, f, l.size() + i + 1) #| } #| } #| } #| do_eachi(self, f, 0) #|} #|pub fn[K, X, Y] map(self : T[K, X], f : (X) -> Y) -> T[K, Y] { #| match self { #| Empty => Empty #| Tree(k, value~, size~, l, r) => #| Tree(k, value=f(value), size~, l.map(f), r.map(f)) #| } #|} #|pub fn[K, X, Y] map_with_key(self : T[K, X], f : (K, X) -> Y) -> T[K, Y] { #| match self { #| Empty => Empty #| Tree(k, value~, l, r, size~) => #| Tree(k, value=f(k, value), size~, l.map_with_key(f), r.map_with_key(f)) #| } #|} #|pub fn[K, V, A] fold(self : T[K, V], init~ : A, f : (A, V) -> A) -> A { #| self.foldl_with_key((acc, _k, v) => f(acc, v), init~) #|} #|pub fn[K, V, A] foldr_with_key( #| self : T[K, V], #| f : (A, K, V) -> A, #| init~ : A, #|) -> A { #| fn go(m : T[K, V], acc) { #| match m { #| Empty => acc #| Tree(k, value~, l, r, ..) => go(l, f(go(r, acc), k, value)) #| } #| } #| go(self, init) #|} #|pub fn[K, V, A] foldl_with_key( #| self : T[K, V], #| f : (A, K, V) -> A, #| init~ : A, #|) -> A { #| fn go(m : T[K, V], acc) { #| match m { #| Empty => acc #| Tree(k, value~, l, r, ..) => go(r, f(go(l, acc), k, value)) #| } #| } #| go(self, init) #|} #|fn[K : Show, V : Show] debug_tree(self : T[K, V]) -> String { #| match self { #| Empty => "_" #| Tree(k, value~, l, r, ..) => { #| let l = l.debug_tree() #| let r = r.debug_tree() #| "(\{k},\{value},\{l},\{r})" #| } #| } #|} #|pub fn[K : Compare, V] from_array(array : Array[(K, V)]) -> T[K, V] { #| for i = 0, mp = Empty; i < array.length(); { #| let (k, v) = array[i] #| continue i + 1, mp.add(k, v) #| } else { #| mp #| } #|} #|pub fn[K, V] iter(self : T[K, V]) -> Iter[(K, V)] { #| Iter::new(yield_ => { #| fn go(t) { #| match t { #| Empty => IterContinue #| Tree(k, value~, l, r, ..) => #| if go(l) is IterEnd { #| IterEnd #| } else if yield_((k, value)) is IterEnd { #| IterEnd #| } else { #| go(r) #| } #| } #| } #| go(self) #| }) #|} #|pub fn[K, V] iter2(self : T[K, V]) -> Iter2[K, V] { #| Iter2::new(yield_ => { #| fn go(t) { #| match t { #| Empty => IterContinue #| Tree(k, value~, l, r, ..) => #| if go(l) is IterEnd { #| IterEnd #| } else if yield_(k, value) is IterEnd { #| IterEnd #| } else { #| go(r) #| } #| } #| } #| go(self) #| }) #|} #|pub fn[K : Compare, V] from_iter(iter : Iter[(K, V)]) -> T[K, V] { #| iter.fold(init=new(), (m, e) => m.add(e.0, e.1)) #|} #|#deprecated("Use `keys_as_iter` instead. `keys` will return `Iter[K]` instead of `Array[K]` in the future.") #|#coverage.skip #|pub fn[K, V] keys(self : T[K, V]) -> Array[K] { #| self.iter().map(p => p.0).collect() #|} #|pub fn[K, V] keys_as_iter(self : T[K, V]) -> Iter[K] { #| self.iter().map(p => p.0) #|} #|pub fn[K, V] values(self : T[K, V]) -> Iter[V] { #| self.iter().map(p => p.1) #|} #|#deprecated("Use `values` instead") #|#coverage.skip #|pub fn[K, V] elems(self : T[K, V]) -> Array[V] { #| self.values().collect() #|} #|pub fn[K : Compare, V] of(array : FixedArray[(K, V)]) -> T[K, V] { #| for i = 0, mp = Empty; i < array.length(); { #| let (k, v) = array[i] #| continue i + 1, mp.add(k, v) #| } else { #| mp #| } #|} #|pub fn[K : Show, V : ToJson] to_json(self : T[K, V]) -> Json { #| ToJson::to_json(self) #|} #|pub fn[V : @json.FromJson] from_json( #| json : Json, #|) -> T[String, V] raise @json.JsonDecodeError { #| @json.from_json(json) #|} ), }, ) ///| let moonbitlang_core_immut_sorted_set_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/immut/sorted_set", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/array": moonbitlang_core_array_module, "moonbitlang/core/quickcheck": moonbitlang_core_quickcheck_module, "moonbitlang/core/json": moonbitlang_core_json_module, }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/builtin", #| "moonbitlang/core/array", #| "moonbitlang/core/quickcheck", #| "moonbitlang/core/json" #| ], #| "targets": { #| "panic_test.mbt": ["not", "native", "llvm"] #| } #|} ), "deprecated.mbt": ( #|#deprecated("use `@immut/sorted_set.new` instead") #|#coverage.skip #|pub fn[A] T::new() -> T[A] { #| Empty #|} #|#deprecated("use `immut/sorted_set.singleton` instead") #|#coverage.skip #|pub fn[A] T::singleton(value : A) -> T[A] { #| singleton(value) #|} #|#deprecated("use `@immut/sorted_set.from_array` instead") #|#coverage.skip #|pub fn[A : Compare] T::from_array(array : Array[A]) -> T[A] { #| from_array(array) #|} #|#deprecated("use `@immut/sorted_set.from_json` instead") #|#coverage.skip #|pub fn[A : @json.FromJson + Compare] T::from_json( #| json : Json, #|) -> T[A] raise @json.JsonDecodeError { #| @json.from_json(json) #|} #|#deprecated("use `@immut/sorted_set.of` instead") #|#coverage.skip #|pub fn[A : Compare] T::of(array : FixedArray[A]) -> T[A] { #| of(array) #|} ), "generic.mbt": ( #|pub fn[A] iter(self : T[A]) -> Iter[A] { #| Iter::new(yield_ => { #| fn go(t) { #| match t { #| Empty => IterContinue #| Node(left~, right~, value~, ..) => #| if go(left) is IterEnd { #| IterEnd #| } else if yield_(value) is IterEnd { #| IterEnd #| } else { #| go(right) #| } #| } #| } #| go(self) #| }) #|} #|pub fn[A : Compare] from_iter(iter : Iter[A]) -> T[A] { #| iter.fold(init=new(), (s, e) => s.add(e)) #|} #|#deprecated("use `@immut/sorted_set.from_iter` instead") #|pub fn[A : Compare] T::from_iter(iter : Iter[A]) -> T[A] { #| from_iter(iter) #|} #|test { #| @json.inspect(of([2, 7, 1, 2, 3, 4, 5]), content=[1, 2, 3, 4, 5, 7]) #|} #|pub impl[A : Eq] Eq for T[A] with op_equal(self, other) -> Bool { #| let iter = InorderIterator::new(self) #| let iter1 = InorderIterator::new(other) #| loop (iter.next(), iter1.next()) { #| (None, None) => true #| (Some(a), Some(b)) => { #| guard a == b else { break false } #| continue (iter.next(), iter1.next()) #| } #| (_, _) => false #| } #|} #|pub impl[A : Compare] Compare for T[A] with compare(self, other) -> Int { #| let iter = InorderIterator::new(self) #| let iter1 = InorderIterator::new(other) #| loop (iter.next(), iter1.next()) { #| (None, None) => 0 #| (Some(a), Some(b)) => { #| let cmp = a.compare(b) #| guard cmp == 0 else { break cmp } #| continue (iter.next(), iter1.next()) #| } #| (Some(_), None) => 1 #| (None, Some(_)) => -1 #| } #|} #|priv struct InorderIterator[A](Array[T[A]]) #|fn[A] InorderIterator::new(root : T[A]) -> InorderIterator[A] { #| let it = InorderIterator([]) #| it.move_left(root) #| it #|} #|fn[A] InorderIterator::move_left( #| self : InorderIterator[A], #| node : T[A], #|) -> Unit { #| loop node { #| Empty => () #| Node(left~, ..) as curr => { #| let InorderIterator(self) = self #| self.push(curr) #| continue left #| } #| } #|} #|fn[A] InorderIterator::next(self : InorderIterator[A]) -> A? { #| let InorderIterator(s) = self #| guard s.pop() is Some(curr) else { return None } #| guard curr is Node(right~, value~, ..) #| self.move_left(right) #| Some(value) #|} #|test "InorderIterator" { #| let arr : FixedArray[_] = [1, 2, 3, 4, 5, 6, 7] #| let set = of(arr) #| let iter = InorderIterator::new(set) #| for i = 0; ; i = i + 1 { #| match iter.next() { #| None => break #| Some(value) => assert_eq(value, arr[i]) #| } #| } #|} ), "immutable_set.mbt": ( #|pub fn[A] new() -> T[A] { #| Empty #|} #|pub impl[A] Default for T[A] with default() { #| Empty #|} #|pub fn[A] singleton(value : A) -> T[A] { #| Node(left=Empty, value~, right=Empty, size=1) #|} #|pub fn[A : Compare] from_array(array : Array[A]) -> T[A] { #| for i = array.length() - 1, set = Empty; i >= 0; { #| continue i - 1, set.add(array[i]) #| } else { #| set #| } #|} #|pub fn[A] to_array(self : T[A]) -> Array[A] { #| let arr = [] #| fn aux(set : T[A]) { #| match set { #| Empty => () #| Node(left~, value~, right~, ..) => { #| aux(left) #| arr.push(value) #| aux(right) #| } #| } #| } #| aux(self) #| arr #|} #|pub fn[A : Compare] remove_min(self : T[A]) -> T[A] { #| match self { #| Empty => abort("remove_min: empty ImmutableSet") #| Node(left~, right~, value~, ..) => #| if left is Empty { #| right #| } else { #| balance(left.remove_min(), value, right) #| } #| } #|} #|pub fn[A : Compare] add(self : T[A], value : A) -> T[A] { #| match self { #| Empty => Node(left=Empty, value~, right=Empty, size=1) #| Node(left~, right~, value=node_value, ..) => { #| let compare_result = value.compare(node_value) #| if compare_result == 0 { #| self #| } else if compare_result < 0 { #| let ll = left.add(value) #| if physical_equal(left, ll) { #| self #| } else { #| balance(ll, node_value, right) #| } #| } else { #| let rr = right.add(value) #| if physical_equal(right, rr) { #| self #| } else { #| balance(left, node_value, rr) #| } #| } #| } #| } #|} #|pub fn[A : Compare] remove(self : T[A], value : A) -> T[A] { #| match self { #| Empty => Empty #| Node(left~, right~, value=node_value, ..) => { #| let compare_result = value.compare(node_value) #| if compare_result == 0 { #| left.merge(right) #| } else if compare_result < 0 { #| let new_left = left.remove(value) #| if physical_equal(left, new_left) { #| self #| } else { #| balance(new_left, node_value, right) #| } #| } else { #| let new_right = right.remove(value) #| if physical_equal(right, new_right) { #| self #| } else { #| balance(left, node_value, new_right) #| } #| } #| } #| } #|} #|pub fn[A : Compare] min(self : T[A]) -> A { #| match self { #| Empty => abort("min: there are no values in sorted_set.") #| Node(left~, value~, ..) => if left is Empty { value } else { left.min() } #| } #|} #|pub fn[A : Compare] min_option(self : T[A]) -> A? { #| match self { #| Empty => None #| Node(left~, value~, ..) => #| if left is Empty { #| Some(value) #| } else { #| left.min_option() #| } #| } #|} #|pub fn[A : Compare] max(self : T[A]) -> A { #| match self { #| Empty => abort("max: there are no values in ImmutableSet.") #| Node(right~, value~, ..) => if right is Empty { value } else { right.max() } #| } #|} #|pub fn[A : Compare] max_option(self : T[A]) -> A? { #| match self { #| Empty => None #| Node(right~, value~, ..) => #| if right is Empty { #| Some(value) #| } else { #| right.max_option() #| } #| } #|} #|pub fn[A : Compare] split(self : T[A], divide : A) -> (T[A], Bool, T[A]) { #| match self { #| Empty => (Empty, false, Empty) #| Node(left~, right~, value~, ..) => { #| let compare_result = divide.compare(value) #| if compare_result == 0 { #| (left, true, right) #| } else if compare_result < 0 { #| let (left_left, present, right_left) = left.split(divide) #| (left_left, present, join(right_left, value, right)) #| } else { #| let (left_right, present, right_right) = right.split(divide) #| (join(left, value, left_right), present, right_right) #| } #| } #| } #|} #|pub fn[A] is_empty(self : T[A]) -> Bool { #| self is Empty #|} #|pub fn[A : Compare] contains(self : T[A], value : A) -> Bool { #| match self { #| Empty => false #| Node(left~, right~, value=node_value, ..) => { #| let compare_result = value.compare(node_value) #| compare_result == 0 || #| (if compare_result < 0 { left } else { right }).contains(value) #| } #| } #|} #|pub fn[A : Compare] union(self : T[A], other : T[A]) -> T[A] { #| match (self, other) { #| (Empty, _) => other #| (_, Empty) => self #| ( #| Node(left=l1, value=v1, right=r1, size=s1), #| Node(left=l2, value=v2, right=r2, size=s2), #| ) => #| if s1 >= s2 { #| if s2 == 1 { #| self.add(v2) #| } else { #| let (l2, _, r2) = other.split(v1) #| join(l1.union(l2), v1, r1.union(r2)) #| } #| } else if s1 == 1 { #| other.add(v1) #| } else { #| let (l1, _, r1) = self.split(v2) #| join(l1.union(l2), v2, r1.union(r2)) #| } #| } #|} #|pub impl[A : Compare] Add for T[A] with op_add(self, other) { #| return self.union(other) #|} #|#deprecated("Use `intersection` instead") #|#coverage.skip #|pub fn[A : Compare] inter(self : T[A], other : T[A]) -> T[A] { #| self.intersection(other) #|} #|pub fn[A : Compare] intersection(self : T[A], other : T[A]) -> T[A] { #| match (self, other) { #| (Empty, _) | (_, Empty) => Empty #| (Node(left=l1, value=v1, right=r1, ..), _) => #| match other.split(v1) { #| (l2, false, r2) => l1.intersection(l2).concat(r1.intersection(r2)) #| (l2, true, r2) => join(l1.intersection(l2), v1, r1.intersection(r2)) #| } #| } #|} #|#deprecated("Use `difference` instead") #|#coverage.skip #|pub fn[A : Compare] diff(self : T[A], other : T[A]) -> T[A] { #| self.difference(other) #|} #|pub fn[A : Compare] difference(self : T[A], other : T[A]) -> T[A] { #| match (self, other) { #| (Empty, _) => Empty #| (_, Empty) => self #| (Node(left=l1, value=v1, right=r1, ..), _) => #| match other.split(v1) { #| (l2, false, r2) => join(l1.difference(l2), v1, r1.difference(r2)) #| (l2, true, r2) => l1.difference(l2).concat(r1.difference(r2)) #| } #| } #|} #|pub fn[A : Compare] symmetric_difference(self : T[A], other : T[A]) -> T[A] { #| match (self, other) { #| (Empty, _) => other #| (_, Empty) => self #| (Node(left=l1, value=v1, right=r1, ..), _) => #| match other.split(v1) { #| (l2, false, r2) => #| join(l1.symmetric_difference(l2), v1, r1.symmetric_difference(r2)) #| (l2, true, r2) => #| l1.symmetric_difference(l2).concat(r1.symmetric_difference(r2)) #| } #| } #|} #|pub fn[A : Compare] subset(self : T[A], other : T[A]) -> Bool { #| match (self, other) { #| (Empty, _) => true #| (_, Empty) => false #| ( #| Node(left=l1, value=v1, right=r1, ..), #| Node(left=l2, value=v2, right=r2, ..), #| ) => { #| let compare_result = v1.compare(v2) #| if compare_result == 0 { #| l1.subset(l2) && r1.subset(r2) #| } else if compare_result < 0 { #| Node(left=l1, value=v1, right=Empty, size=1).subset(l2) && #| r1.subset(self) #| } else { #| Node(left=Empty, value=v1, right=r1, size=1).subset(r2) && #| l1.subset(self) #| } #| } #| } #|} #|pub fn[A : Compare] disjoint(self : T[A], other : T[A]) -> Bool { #| match (self, other) { #| (Empty, _) | (_, Empty) => true #| (Node(left=l1, value=v1, right=r1, ..), _) => #| if physical_equal(self, other) { #| false #| } else { #| match other.split_bis(v1) { #| NotFound(l2, r2) => l1.disjoint(l2) && r1.disjoint(r2()) #| Found => false #| } #| } #| } #|} #|pub fn[A] each(self : T[A], f : (A) -> Unit raise?) -> Unit raise? { #| match self { #| Empty => () #| Node(left~, value~, right~, ..) => { #| left.each(f) #| f(value) #| right.each(f) #| } #| } #|} #|pub fn[A : Compare, B] fold( #| self : T[A], #| init~ : B, #| f : (B, A) -> B raise?, #|) -> B raise? { #| match self { #| Empty => init #| Node(left~, value~, right~, ..) => #| right.fold(init=f(left.fold(init~, f), value), f) #| } #|} #|pub fn[A : Compare, B : Compare] map( #| self : T[A], #| f : (A) -> B raise?, #|) -> T[B] raise? { #| match self { #| Empty => Empty #| Node(left~, value~, right~, ..) => #| try_join(left.map(f), f(value), right.map(f)) #| } #|} #|pub fn[A : Compare] all(self : T[A], f : (A) -> Bool raise?) -> Bool raise? { #| match self { #| Empty => true #| Node(left~, value~, right~, ..) => f(value) && left.all(f) && right.all(f) #| } #|} #|pub fn[A : Compare] any(self : T[A], f : (A) -> Bool raise?) -> Bool raise? { #| match self { #| Empty => false #| Node(left~, value~, right~, ..) => f(value) || left.any(f) || right.any(f) #| } #|} #|pub fn[A : Compare] filter(self : T[A], f : (A) -> Bool raise?) -> T[A] raise? { #| match self { #| Empty => Empty #| Node(left~, value~, right~, ..) => { #| let l = left.filter(f) #| let v = f(value) #| let r = right.filter(f) #| if v { #| if physical_equal(l, left) && physical_equal(r, right) { #| self #| } else { #| join(l, value, r) #| } #| } else { #| l.concat(r) #| } #| } #| } #|} #|pub impl[A : Show] Show for T[A] with output(self, logger) { #| logger.write_iter(self.iter(), prefix="@immut/sorted_set.of([", suffix="])") #|} #|pub impl[A : ToJson] ToJson for T[A] with to_json(self) { #| let capacity = self.iter().count() #| guard capacity != 0 else { return Json::array([]) } #| let jsons = Array::new(capacity~) #| self.each(a => jsons.push(a.to_json())) #| Json::array(jsons) #|} #|pub fn[A : ToJson] to_json(self : T[A]) -> Json { #| ToJson::to_json(self) #|} #|pub impl[A : @json.FromJson + Compare] @json.FromJson for T[A] with from_json( #| json, #| path, #|) { #| guard json is Array(arr) else { #| raise @json.JsonDecodeError( #| (path, "@immut/sorted_set.from_json: expected array"), #| ) #| } #| let mut set = new() #| for i, x in arr { #| set = set.add(A::from_json(x, path.add_index(i))) #| } #| set #|} #|pub fn[A : @json.FromJson + Compare] from_json( #| json : Json, #|) -> T[A] raise @json.JsonDecodeError { #| @json.from_json(json) #|} #|pub impl[X : @quickcheck.Arbitrary + Compare] @quickcheck.Arbitrary for T[X] with arbitrary( #| size, #| rs, #|) { #| @quickcheck.Arbitrary::arbitrary(size, rs) |> from_array #|} #|const BALANCE_RATIO = 5 #|priv enum SplitBis[A] { #| Found #| NotFound(T[A], () -> T[A]) #|} #|impl[T] Show for SplitBis[T] with output(self, logger) { #| match self { #| Found => logger.write_string("Found") #| NotFound(_) => logger.write_string("NotFound") #| } #|} #|fn[A : Compare] split_bis(self : T[A], value : A) -> SplitBis[A] { #| match self { #| Empty => NotFound(Empty, () => Empty) #| Node(left~, value=node_value, right~, ..) => { #| let compare_result = value.compare(node_value) #| if compare_result == 0 { #| Found #| } else if compare_result < 0 { #| match left.split_bis(value) { #| Found => Found #| NotFound(ll, rl) => NotFound(ll, () => join(rl(), node_value, right)) #| } #| } else { #| match right.split_bis(value) { #| Found => Found #| NotFound(lr, rr) => NotFound(join(left, node_value, lr), rr) #| } #| } #| } #| } #|} #|pub fn[A] size(self : T[A]) -> Int { #| match self { #| Empty => 0 #| Node(size~, ..) => size #| } #|} #|fn[A] create(left : T[A], value : A, right : T[A]) -> T[A] { #| Node(left~, right~, value~, size=left.size() + right.size() + 1) #|} #|fn[A] balance(left : T[A], value : A, right : T[A]) -> T[A] { #| let left_size = left.size() #| let right_size = right.size() #| if left_size + right_size < 2 { #| create(left, value, right) #| } else if left_size > right_size * BALANCE_RATIO { #| match left { #| Empty => abort("balance: left is empty.") #| Node(left=ll, value=lv, right=lr, ..) => #| if ll.size() >= lr.size() { #| create(ll, lv, create(lr, value, right)) #| } else { #| match lr { #| Empty => abort("balance: right left.right is empty.") #| Node(left=lrl, value=lrv, right=lrr, ..) => #| create(create(ll, lv, lrl), lrv, create(lrr, value, right)) #| } #| } #| } #| } else if right_size > left_size * BALANCE_RATIO { #| match right { #| Empty => abort("balance: right is empty") #| Node(left=rl, value=rv, right=rr, ..) => #| if rr.size() >= rl.size() { #| create(create(left, value, rl), rv, rr) #| } else { #| match rl { #| Empty => abort("balance: right.left is empty") #| Node(left=rll, value=rlv, right=rlr, ..) => #| create(create(left, value, rll), rlv, create(rlr, rv, rr)) #| } #| } #| } #| } else { #| create(left, value, right) #| } #|} #|fn[A : Compare] add_min_value(self : T[A], value : A) -> T[A] { #| match self { #| Empty => singleton(value) #| Node(left~, value=node_value, right~, ..) => #| balance(left.add_min_value(value), node_value, right) #| } #|} #|fn[A : Compare] add_max_value(self : T[A], value : A) -> T[A] { #| match self { #| Empty => singleton(value) #| Node(left~, value=node_value, right~, ..) => #| balance(left, node_value, right.add_max_value(value)) #| } #|} #|fn[A : Compare] join(left : T[A], value : A, right : T[A]) -> T[A] { #| match (left, right) { #| (Empty, _) => right.add_min_value(value) #| (_, Empty) => left.add_max_value(value) #| ( #| Node(left=ll, value=lv, right=lr, size=ls), #| Node(left=rl, value=rv, right=rr, size=rs), #| ) => #| if ls > rs * BALANCE_RATIO { #| balance(ll, lv, join(lr, value, right)) #| } else if rs > ls * BALANCE_RATIO { #| balance(join(left, value, rl), rv, rr) #| } else { #| create(left, value, right) #| } #| } #|} #|fn[A : Compare] try_join(left : T[A], value : A, right : T[A]) -> T[A] { #| if (left == Empty || left.max().compare(value) < 0) && #| (right == Empty || value.compare(right.min()) < 0) { #| join(left, value, right) #| } else { #| left.union(right.add(value)) #| } #|} #|fn[A : Compare] merge(self : T[A], other : T[A]) -> T[A] { #| match (self, other) { #| (Empty, _) => other #| (_, Empty) => self #| _ => balance(self, other.min(), other.remove_min()) #| } #|} #|fn[A : Compare] concat(self : T[A], other : T[A]) -> T[A] { #| match (self, other) { #| (Empty, _) => other #| (_, Empty) => self #| _ => join(self, other.min(), other.remove_min()) #| } #|} #|pub fn[A : Compare] of(array : FixedArray[A]) -> T[A] { #| for i = array.length() - 1, set = Empty; i >= 0; { #| continue i - 1, set.add(array[i]) #| } else { #| set #| } #|} #|pub impl[A : Hash] Hash for T[A] with hash_combine(self, hasher) { #| for t in self { #| t.hash_combine(hasher) #| } #|} #|test "split_bis" { #| inspect(of([1, 2, 3]).split_bis(1), content="Found") #| inspect(of([1, 2, 3]).split_bis(3), content="Found") #| inspect(of([1, 2, 3]).split_bis(0), content="NotFound") #| inspect(of([1, 2, 3]).split_bis(4), content="NotFound") #|} #|test "balance with left height greater" { #| let left = of([1, 2, 3]) #| let value = 4 #| let right = of([5]) #| let balanced_set = balance(left, value, right) #| inspect(balanced_set, content="@immut/sorted_set.of([1, 2, 3, 4, 5])") #|} #|test "balance with right height greater" { #| let left = of([1]) #| let value = 2 #| let right = of([3, 4, 5]) #| let balanced_set = balance(left, value, right) #| inspect(balanced_set, content="@immut/sorted_set.of([1, 2, 3, 4, 5])") #|} #|test "join with different heights" { #| let left = of([1, 2, 3]) #| let value = 4 #| let right = of([5, 6, 7]) #| let joined_set = join(left, value, right) #| inspect(joined_set, content="@immut/sorted_set.of([1, 2, 3, 4, 5, 6, 7])") #|} #|test "hash" { #| assert_eq(Hash::hash(of([1, 2, 3, 4])), Hash::hash(of([3, 2]).add(1).add(4))) #| assert_not_eq(Hash::hash(of([1, 2, 3])), Hash::hash(of([1, 2, 4]))) #|} ), "types.mbt": ( #|enum T[A] { #| Empty #| Node(left~ : T[A], right~ : T[A], size~ : Int, value~ : A) #|} ), }, ) ///| let moonbitlang_core_int_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/int", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/uint": moonbitlang_core_uint_module, }, files={ "moon.pkg.json": ( #|{ #| "import": ["moonbitlang/core/builtin", "moonbitlang/core/uint"] #|} ), "int.mbt": ( #|pub let max_value = 2147483647 #|pub let min_value = -2147483648 #|pub fn Int::abs(self : Int) -> Int { #| if self < 0 { #| -self #| } else { #| self #| } #|} #|pub fnalias Int::abs #|pub fn to_be_bytes(self : Int) -> Bytes { #| self.reinterpret_as_uint().to_be_bytes() #|} #|pub fn to_le_bytes(self : Int) -> Bytes { #| self.reinterpret_as_uint().to_le_bytes() #|} ), }, ) ///| let moonbitlang_core_int16_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/int16", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/json": moonbitlang_core_json_module, }, files={ "moon.pkg.json": ( #|{ #| "import": ["moonbitlang/core/builtin", "moonbitlang/core/json"], #| "test-import": ["moonbitlang/core/uint16"] #|} ), "int16.mbt": ( #|pub let max_value : Int16 = 32767 #|pub let min_value : Int16 = -32768 #|pub impl Add for Int16 with op_add(self : Int16, that : Int16) -> Int16 { #| (self.to_int() + that.to_int()).to_int16() #|} #|pub impl Sub for Int16 with op_sub(self : Int16, that : Int16) -> Int16 { #| (self.to_int() - that.to_int()).to_int16() #|} #|pub impl Mul for Int16 with op_mul(self : Int16, that : Int16) -> Int16 { #| (self.to_int() * that.to_int()).to_int16() #|} #|pub impl Div for Int16 with op_div(self : Int16, that : Int16) -> Int16 { #| (self.to_int() / that.to_int()).to_int16() #|} #|pub impl Mod for Int16 with op_mod(self : Int16, that : Int16) -> Int16 { #| (self.to_int() % that.to_int()).to_int16() #|} #|pub impl Eq for Int16 with op_equal(self, that) { #| self.to_int() == that.to_int() #|} #|pub impl Compare for Int16 with compare(self, that) { #| self.to_int().compare(that.to_int()) #|} #|pub impl Hash for Int16 with hash(self) { #| self.to_int() #|} #|pub impl Hash for Int16 with hash_combine(self, hasher) { #| hasher.combine_int(self.to_int()) #|} #|pub impl Shl for Int16 with op_shl(self : Int16, that : Int) -> Int16 { #| (self.to_int() << that).to_int16() #|} #|pub impl Shr for Int16 with op_shr(self : Int16, that : Int) -> Int16 { #| (self.to_int() >> that).to_int16() #|} #|pub impl BitOr for Int16 with lor(self : Int16, that : Int16) -> Int16 { #| (self.to_int() | that.to_int()).to_int16() #|} #|pub impl BitAnd for Int16 with land(self : Int16, that : Int16) -> Int16 { #| (self.to_int() & that.to_int()).to_int16() #|} #|pub impl BitXOr for Int16 with lxor(self : Int16, that : Int16) -> Int16 { #| (self.to_int() ^ that.to_int()).to_int16() #|} #|pub impl Neg for Int16 with op_neg(self : Int16) -> Int16 { #| (-self.to_int()).to_int16() #|} #|pub fn Int16::abs(self : Int16) -> Int16 { #| if self < 0 { #| -self #| } else { #| self #| } #|} #|pub impl Default for Int16 with default() { #| 0 #|} #|pub impl ToJson for Int16 with to_json(self : Int16) -> Json { #| Json::number(self.to_int().to_double()) #|} #|pub fn Int16::reinterpret_as_uint16(self : Int16) -> UInt16 { #| self.to_int().to_uint16() #|} ), }, ) ///| let moonbitlang_core_int64_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/int64", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/bytes": moonbitlang_core_bytes_module, "moonbitlang/core/uint": moonbitlang_core_uint_module, "moonbitlang/core/uint64": moonbitlang_core_uint64_module, }, files={ "moon.pkg.json": ( #|{ #| "import": ["moonbitlang/core/builtin", "moonbitlang/core/bytes", "moonbitlang/core/uint", "moonbitlang/core/uint64"] #|} ), "int64.mbt": ( #|pub let max_value = 9223372036854775807L #|pub let min_value = -9223372036854775808L #|pub fn Int64::from_int(i : Int) -> Int64 { #| i.to_int64() #|} #|pub fn from_int(i : Int) -> Int64 { #| i.to_int64() #|} #|pub fn Int64::abs(self : Int64) -> Int64 { #| if self < 0L { #| -self #| } else { #| self #| } #|} #|pub fnalias Int64::abs #|pub fn to_be_bytes(self : Int64) -> Bytes { #| self.reinterpret_as_uint64().to_be_bytes() #|} #|pub fn to_le_bytes(self : Int64) -> Bytes { #| self.reinterpret_as_uint64().to_le_bytes() #|} ), "xxhash.mbt": ( #|let gPRIME2 = 0x85EBCA77U #|let gPRIME3 = 0xC2B2AE3DU #|let gPRIME4 = 0x27D4EB2FU #|let gPRIME5 = 0x165667B1U #|pub impl Hash for Int64 with hash(self) -> Int { #| let mut input = self.reinterpret_as_uint64() #| let seed = 0U #| let mut acc = seed + gPRIME5 + 8 #| let mut x = acc + input.to_uint() * gPRIME3 #| let r = 17 #| acc = ((x << r) | (x >> (32 - r))) * gPRIME4 #| input = input >> 32 #| x = acc + input.to_uint() * gPRIME3 #| acc = ((x << r) | (x >> (32 - r))) * gPRIME4 #| input = input >> 32 #| acc = acc ^ (acc >> 15) #| acc *= gPRIME2 #| acc = acc ^ (acc >> 13) #| acc *= gPRIME3 #| acc = acc ^ (acc >> 16) #| acc.reinterpret_as_int() #|} #|pub impl Hash for Int64 with hash_combine(self, hasher) { #| hasher.combine_int64(self) #|} #|fn slow_hash(self : Int64) -> Int { #| let self = self.reinterpret_as_uint64() #| let b : Bytes = [ #| (self & 0xFF).to_byte(), #| ((self >> 8) & 0xFF).to_byte(), #| ((self >> 16) & 0xFF).to_byte(), #| ((self >> 24) & 0xFF).to_byte(), #| ((self >> 32) & 0xFF).to_byte(), #| ((self >> 40) & 0xFF).to_byte(), #| ((self >> 48) & 0xFF).to_byte(), #| ((self >> 56) & 0xFF).to_byte(), #| ] #| b.hash() #|} #|test "int64 hash" { #| let i0 = 9_223_372_036_854_775_807L // INT64_MAX #| let i1 = -9_223_372_036_854_775_808L // INT64_MIN #| let i2 = gPRIME2.to_int64() #| let i3 = gPRIME3.to_int64() #| let i4 = gPRIME4.to_int64() #| let i5 = gPRIME5.to_int64() #| let i6 = 0L #| inspect(i0.hash().to_string(), content=i0.slow_hash().to_string()) #| inspect(i1.hash().to_string(), content=i1.slow_hash().to_string()) #| inspect(i2.hash().to_string(), content=i2.slow_hash().to_string()) #| inspect(i3.hash().to_string(), content=i3.slow_hash().to_string()) #| inspect(i4.hash().to_string(), content=i4.slow_hash().to_string()) #| inspect(i5.hash().to_string(), content=i5.slow_hash().to_string()) #| inspect(i6.hash().to_string(), content=i6.slow_hash().to_string()) #|} ), }, ) ///| let moonbitlang_core_json_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/json", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/char": moonbitlang_core_char_module, "moonbitlang/core/double": moonbitlang_core_double_module, "moonbitlang/core/string": moonbitlang_core_string_module, "moonbitlang/core/strconv": moonbitlang_core_strconv_module, "moonbitlang/core/option": moonbitlang_core_option_module, }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/builtin", #| "moonbitlang/core/char", #| "moonbitlang/core/double", #| "moonbitlang/core/string", #| "moonbitlang/core/strconv", #| "moonbitlang/core/option" #| ], #| "test-import": [ #| "moonbitlang/core/result", #| "moonbitlang/core/unit", #| "moonbitlang/core/array", #| "moonbitlang/core/bigint" #| ] #|} ), "deprecated.mbt": ( #|#deprecated("Definition of json is moved to builtin package, use `Json` instead") #|pub typealias Json as JsonValue ), "from_json.mbt": ( #|pub(all) suberror JsonDecodeError (JsonPath, String) derive ( #| Eq, #| Show, #| ToJson(style="flat"), #|) #|pub(open) trait FromJson { #| from_json(Json, JsonPath) -> Self raise JsonDecodeError #|} #|pub fn[T : FromJson] from_json( #| json : Json, #| path? : JsonPath = Root, #|) -> T raise JsonDecodeError { #| FromJson::from_json(json, path) #|} #|fn[T] decode_error(path : JsonPath, msg : String) -> T raise JsonDecodeError { #| raise JsonDecodeError((path, msg)) #|} #|pub impl FromJson for Bool with from_json(json, path) { #| match json { #| true => true #| false => false #| _ => decode_error(path, "Bool::from_json: expected boolean") #| } #|} #|pub impl FromJson for Int with from_json(json, path) { #| guard json is Number(n, ..) && #| n != @double.infinity && #| n != @double.neg_infinity else { #| decode_error(path, "Int::from_json: expected number") #| } #| n.to_int() #|} #|pub impl FromJson for Int64 with from_json(json, path) { #| guard json is String(str) else { #| decode_error( #| path, "Int64::from_json: expected number in string representation", #| ) #| } #| @strconv.parse_int64(str) catch { #| error => decode_error(path, "Int64::from_json: parsing failure \{error}") #| } #|} #|pub impl FromJson for UInt with from_json(json, path) { #| guard json is Number(n, ..) && #| n != @double.infinity && #| n != @double.neg_infinity else { #| decode_error(path, "UInt::from_json: expected number") #| } #| n.to_uint() #|} #|pub impl FromJson for UInt64 with from_json(json, path) { #| guard json is String(str) else { #| decode_error( #| path, "UInt64::from_json: expected number in string representation", #| ) #| } #| @strconv.parse_uint64(str) catch { #| error => decode_error(path, "UInt64::from_json: parsing failure \{error}") #| } #|} #|pub impl FromJson for Double with from_json(json, path) { #| match json { #| String("NaN") => @double.not_a_number #| String("Infinity") => @double.infinity #| String("-Infinity") => @double.neg_infinity #| Number(n, ..) if n != @double.infinity && n != @double.neg_infinity => n #| _ => decode_error(path, "Double::from_json: expected number") #| } #|} #|pub impl FromJson for String with from_json(json, path) { #| guard json is String(a) else { #| decode_error(path, "String::from_json: expected string") #| } #| a #|} #|pub impl FromJson for @string.View with from_json(json, path) { #| guard json is String(a) else { #| decode_error(path, "View::from_json: expected string") #| } #| a[:] #|} #|pub impl FromJson for Char with from_json(json, path) { #| guard json is String(a) else { #| decode_error(path, "Char::from_json: expected string") #| } #| let len = a.length() #| if len == 1 { #| a.unsafe_charcode_at(0).unsafe_to_char() #| } else if len == 2 { #| let c1 = a.unsafe_charcode_at(0) #| let c2 = a.unsafe_charcode_at(1) #| if c1 is (0xD800..=0xDBFF) && c2 is (0xDC00..=0xDFFF) { #| let c3 = (c1 << 10) + c2 - 0x35fdc00 #| c3.unsafe_to_char() #| } else { #| decode_error(path, "Char::from_json: invalid surrogate pair") #| } #| } else { #| decode_error(path, "Char::from_json: expected single character") #| } #|} #|pub impl[X : FromJson] FromJson for Array[X] with from_json(json, path) { #| guard json is Array(a) else { #| decode_error(path, "Array::from_json: expected array") #| } #| guard Index(path, index=0) is (Index(_) as new_path) #| a.mapi((i, x) => { #| new_path.index = i #| FromJson::from_json(x, new_path) #| }) #|} #|pub impl[X : FromJson] FromJson for FixedArray[X] with from_json(json, path) { #| guard json is Array(a) else { #| decode_error(path, "FixedArray::from_json: expected array") #| } #| let len = a.length() #| if len == 0 { #| return [] #| } #| guard Index(path, index=0) is (Index(_) as new_path) #| let res = FixedArray::make( #| len, #| FromJson::from_json(a.unsafe_get(0), new_path), #| ) #| for i in 1.. None #| Array([value]) => Some(FromJson::from_json(value, path.add_index(0))) #| _ => decode_error(path, "Option::from_json: expected array or null") #| } #|} #|pub impl[Ok : FromJson, Err : FromJson] FromJson for Result[Ok, Err] with from_json( #| json, #| path, #|) { #| guard json is Object(obj) else { #| decode_error(path, "Result::from_json: expected object") #| } #| if obj.size() != 1 { #| decode_error(path, "Result::from_json: expected object with one field") #| } #| match obj { #| { "Ok": ok, .. } => Ok(FromJson::from_json(ok, path.add_key("Ok"))) #| { "Err": err, .. } => Err(FromJson::from_json(err, path.add_key("Err"))) #| _ => #| decode_error( #| path, "Result::from_json: expected object with Ok or Err field", #| ) #| } #|} #|pub impl FromJson for Unit with from_json(json, path) { #| guard json is Null else { #| decode_error(path, "Unit::from_json: expected null") #| } #|} #|pub impl FromJson for Json with from_json(json, _path) { #| json #|} ), "internal_types.mbt": ( #|priv struct ParseContext { #| mut offset : Int #| input : String #| end_offset : Int #|} #|fn ParseContext::make(input : String) -> ParseContext { #| { offset: 0, input, end_offset: input.length() } #|} #|priv struct CharClass(Array[(Char, Char)]) #|fn CharClass::of(array : Array[(Char, Char)]) -> CharClass { #| CharClass(array) #|} #|fn contains(self : CharClass, c : Char) -> Bool { #| let CharClass(self) = self #| for left = 0, right = self.length(); left < right; { #| let middle = (left + right) / 2 #| let (min, max) = self[middle] #| if c < min { #| continue left, middle #| } else if c > max { #| continue middle + 1, right #| } else { #| break true #| } #| } else { #| false #| } #|} #|priv enum Token { #| Null #| True #| False #| Number(Double, String?) #| String(String) #| LBrace #| RBrace #| LBracket #| RBracket #| Comma #|} ), "json.mbt": ( #|pub fn as_null(self : Json) -> Unit? { #| guard self is Null else { return None } #| Some(()) #|} #|pub fn as_bool(self : Json) -> Bool? { #| match self { #| True => Some(true) #| False => Some(false) #| _ => None #| } #|} #|pub fn as_number(self : Json) -> Double? { #| guard self is Number(n, ..) else { return None } #| Some(n) #|} #|pub fn as_string(self : Json) -> String? { #| guard self is String(s) else { return None } #| Some(s) #|} #|pub fn as_array(self : Json) -> Array[Json]? { #| guard self is Array(arr) else { return None } #| Some(arr) #|} #|pub fn item(self : Json, index : Int) -> Json? { #| match self.as_array() { #| Some(arr) => arr.get(index) #| None => None #| } #|} #|pub fn as_object(self : Json) -> Map[String, Json]? { #| guard self is Object(obj) else { return None } #| Some(obj) #|} #|pub fn value(self : Json, key : String) -> Json? { #| match self.as_object() { #| Some(obj) => obj.get(key) #| None => None #| } #|} #|fn indent_str(level : Int, indent : Int) -> String { #| if indent == 0 { #| "" #| } else { #| "\n" + " ".repeat(indent * level) #| } #|} #|pub fn stringify( #| self : Json, #| escape_slash? : Bool = false, #| indent? : Int = 0, #|) -> String { #| let buf = StringBuilder::new(size_hint=0) #| fn stringify_inner(value : Json, level : Int) -> Unit { #| match value { #| Object(members) => { #| if members.is_empty() { #| buf.write_string("{}") #| return #| } #| buf.write_char('{') #| buf.write_string(indent_str(level + 1, indent)) #| let mut first = true #| for k, v in members { #| if first { #| first = false #| } else { #| buf.write_char(',') #| buf.write_string(indent_str(level + 1, indent)) #| } #| buf #| ..write_char('\"') #| ..write_string(escape(k, escape_slash~)) #| ..write_char('\"') #| if indent == 0 { #| buf.write_char(':') #| } else { #| buf.write_string(": ") #| } #| stringify_inner(v, level + 1) #| } #| buf.write_string(indent_str(level, indent)) #| buf.write_char('}') #| } #| Array(arr) => { #| if arr.is_empty() { #| buf.write_string("[]") #| return #| } #| buf.write_char('[') #| buf.write_string(indent_str(level + 1, indent)) #| for i, v in arr { #| if i > 0 { #| buf.write_char(',') #| buf.write_string(indent_str(level + 1, indent)) #| } #| stringify_inner(v, level + 1) #| } #| buf.write_string(indent_str(level, indent)) #| buf.write_char(']') #| } #| String(s) => #| buf #| ..write_char('\"') #| ..write_string(escape(s, escape_slash~)) #| ..write_char('\"') #| Number(n, repr~) => #| match repr { #| None => buf.write_object(n) #| Some(r) => buf.write_string(r) #| } #| True => buf.write_string("true") #| False => buf.write_string("false") #| Null => buf.write_string("null") #| } #| } #| stringify_inner(self, 0) #| buf.to_string() #|} #|fn escape(str : String, escape_slash~ : Bool) -> String { #| fn to_hex_digit(i : Int) -> Char { #| if i < 10 { #| ('0'.to_int() + i).unsafe_to_char() #| } else { #| ('a'.to_int() + (i - 10)).unsafe_to_char() #| } #| } #| let buf = StringBuilder::new(size_hint=str.length()) #| for c in str { #| match c { #| '"' => buf.write_string("\\\"") #| '\\' => buf.write_string("\\\\") #| '/' => #| if escape_slash { #| buf.write_string("\\/") #| } else { #| buf.write_char(c) #| } #| '\n' => buf.write_string("\\n") #| '\r' => buf.write_string("\\r") #| '\b' => buf.write_string("\\b") #| '\t' => buf.write_string("\\t") #| _ => { #| let code = c.to_int() #| if code == 0x0C { #| buf.write_string("\\f") #| } else if code < 0x20 { #| buf.write_string("\\u00") #| buf.write_char(to_hex_digit(code / 16)) #| buf.write_char(to_hex_digit(code % 16)) #| } else { #| buf.write_char(c) #| } #| } #| } #| } #| buf.to_string() #|} #|pub impl ToJson for Json with to_json(self) { #| self #|} #|#callsite(autofill(args_loc, loc)) #|pub fn inspect( #| obj : &ToJson, #| content? : Json, #| loc~ : SourceLoc, #| args_loc~ : ArgsLoc, #|) -> Unit raise InspectError { #| let loc = loc.to_string().escape() #| let args_loc = args_loc.to_json().escape() #| let actual = obj.to_json().stringify(escape_slash=false) #| let want = match content { #| None => "".to_json().stringify(escape_slash=false) #| Some(x) => x.stringify(escape_slash=false) #| } #| if actual != want { #| raise InspectError( #| "@EXPECT_FAILED {\"loc\": \{loc}, \"args_loc\": \{args_loc}, \"expect\": \{want.escape()}, \"actual\": \{actual.escape()}, \"mode\": \"json\"}", #| ) #| } #|} ), "json_path.mbt": ( #|enum JsonPath { #| Root #| Key(JsonPath, mut key~ : String) #| Index(JsonPath, mut index~ : Int) #|} derive(Eq) #|pub fn add_index(self : JsonPath, index : Int) -> JsonPath { #| Index(self, index~) #|} #|pub fn add_key(self : JsonPath, key : String) -> JsonPath { #| Key(self, key~) #|} #|pub impl Show for JsonPath with output(self, logger) { #| match self { #| Root => logger.write_string("$") #| Key(p, key~) => #| logger..write_object(p)..write_string(".")..write_string(key) #| Index(p, index~) => #| logger #| ..write_object(p) #| ..write_string("[") #| ..write_object(index) #| ..write_string("]") #| } #|} #|pub impl ToJson for JsonPath with to_json(self) { #| String(self.to_string()) #|} #|test "show JsonPath" { #| let path = Key(Index(Root, index=0), key="foo") #| @builtin.inspect(path, content="$[0].foo") #| @builtin.inspect(path.add_index(1), content="$[0].foo[1]") #| @builtin.inspect(path.add_key("bar"), content="$[0].foo.bar") #| @builtin.inspect( #| Root.add_key("foo").add_key("foo1").add_index(2), #| content="$.foo.foo1[2]", #| ) #| @builtin.inspect(Root.add_key("foo").add_key("foo1"), content="$.foo.foo1") #| @builtin.inspect( #| Root.add_key("foo").add_key("foo1").add_index(2).add_key("bar"), #| content="$.foo.foo1[2].bar", #| ) #| @builtin.inspect( #| Root.add_key("foo").add_key("foo1").add_index(2).add_key("bar").add_index(3), #| content="$.foo.foo1[2].bar[3]", #| ) #| @builtin.inspect( #| Root #| .add_key("foo") #| .add_key("foo1") #| .add_index(2) #| .add_key("bar") #| .add_index(3) #| .add_key("baz"), #| content="$.foo.foo1[2].bar[3].baz", #| ) #| @builtin.inspect( #| Root.add_key("foo").add_key("foo1").add_index(2).add_index(3).add_index(4), #| content="$.foo.foo1[2][3][4]", #| ) #|} ), "lex_main.mbt": ( #|let non_ascii_whitespace : CharClass = CharClass::of([ #| ('\u00A0', '\u00A0'), #| ('\u1680', '\u1680'), #| ('\u2000', '\u200A'), #| ('\u2028', '\u2029'), #| ('\u202F', '\u202F'), #| ('\u205F', '\u205F'), #| ('\u3000', '\u3000'), #| ('\uFEFF', '\uFEFF'), #|]) #|fn ParseContext::lex_value( #| ctx : ParseContext, #| allow_rbracket~ : Bool, #|) -> Token raise ParseError { #| for { #| match ctx.read_char() { #| Some('\t' | ' ' | '\n' | '\r') => continue #| Some('{') => return LBrace #| Some('[') => return LBracket #| Some(']') => #| if allow_rbracket { #| return RBracket #| } else { #| ctx.invalid_char(shift=-1) #| } #| Some('n') => { #| ctx.expect_ascii_char('u') #| ctx.expect_ascii_char('l') #| ctx.expect_ascii_char('l') #| return Null #| } #| Some('t') => { #| ctx.expect_ascii_char('r') #| ctx.expect_ascii_char('u') #| ctx.expect_ascii_char('e') #| return True #| } #| Some('f') => { #| ctx.expect_ascii_char('a') #| ctx.expect_ascii_char('l') #| ctx.expect_ascii_char('s') #| ctx.expect_ascii_char('e') #| return False #| } #| Some('-') => #| match ctx.read_char() { #| Some('0') => { #| let (n, repr) = ctx.lex_zero(start=ctx.offset - 2) #| return Number(n, repr) #| } #| Some(c2) => { #| if c2 is ('1'..='9') { #| let (n, repr) = ctx.lex_decimal_integer(start=ctx.offset - 2) #| return Number(n, repr) #| } #| ctx.invalid_char(shift=-1) #| } #| None => raise InvalidEof #| } #| Some('0') => { #| let (n, repr) = ctx.lex_zero(start=ctx.offset - 1) #| return Number(n, repr) #| } #| Some('1'..='9') => { #| let (n, repr) = ctx.lex_decimal_integer(start=ctx.offset - 1) #| return Number(n, repr) #| } #| Some('"') => { #| let s = ctx.lex_string() #| return String(s) #| } #| Some(c) => { #| if c > '\u{7f}' && non_ascii_whitespace.contains(c) { #| continue #| } #| let shift = -c.utf16_len() #| ctx.invalid_char(shift~) #| } #| None => raise InvalidEof #| } #| } #|} ), "lex_misc.mbt": ( #|fn ParseContext::read_char(ctx : ParseContext) -> Char? { #| if ctx.offset < ctx.end_offset { #| let c1 = ctx.input.unsafe_charcode_at(ctx.offset) #| ctx.offset += 1 #| if c1 >= 0xD800 && c1 <= 0xDBFF { #| if ctx.offset < ctx.end_offset { #| let c2 = ctx.input.unsafe_charcode_at(ctx.offset) #| if c2 >= 0xDC00 && c2 <= 0xDFFF { #| ctx.offset += 1 #| let c3 = (c1 << 10) + c2 - 0x35fdc00 #| return Some(c3.unsafe_to_char()) #| } #| } #| } #| Some(c1.unsafe_to_char()) #| } else { #| None #| } #|} #|const SURROGATE_LOW_CHAR = 0xD800 #|const SURROGATE_HIGH_CHAR = 0xDFFF #|fn ParseContext::expect_char( #| ctx : ParseContext, #| c : Char, #|) -> Unit raise ParseError { #| guard ctx.offset < ctx.end_offset else { raise InvalidEof } #| let c1 = ctx.input.unsafe_charcode_at(ctx.offset) #| ctx.offset += 1 #| let c0 = c.to_int() #| if c0 < 0xFFFF { #| if c0 != c1 { #| ctx.invalid_char(shift=-1) #| } #| } else { #| guard c1 is (SURROGATE_LOW_CHAR..=SURROGATE_HIGH_CHAR) && #| ctx.offset < ctx.end_offset else { #| ctx.invalid_char(shift=-1) #| } #| let c2 = ctx.input.unsafe_charcode_at(ctx.offset) #| let c3 = (c1 << 10) + c2 - 0x35fdc00 #| if c3 != c0 { #| ctx.invalid_char(shift=-1) #| } else { #| ctx.offset += 1 // consume and move forward #| } #| } #|} #|fn ParseContext::expect_ascii_char( #| ctx : ParseContext, #| c : Byte, #|) -> Unit raise ParseError { #| guard ctx.offset < ctx.end_offset else { raise InvalidEof } #| let c1 = ctx.input.unsafe_charcode_at(ctx.offset) #| ctx.offset += 1 #| if c.to_int() != c1 { #| ctx.invalid_char(shift=-1) #| } #|} #|test "expect_char" { #| let ctx = ParseContext::make("abc") #| ctx.expect_char('a') #| ctx.expect_char('b') #| ctx.expect_char('c') #| inspect(try? ctx.expect_char('d'), content={ "Err": "InvalidEof" }) #|} #|test "expect_char with surrogate pair" { #| let ctx = ParseContext::make("a\u{1F600}bc\u{1F600}c") #| ctx.expect_char('a') #| ctx.expect_char((0x1F600).unsafe_to_char()) #| ctx.expect_char('b') #| ctx.expect_char('c') #| ctx.expect_char((0x1F600).unsafe_to_char()) #| ctx.expect_char('c') #| inspect(try? ctx.expect_char('d'), content={ "Err": "InvalidEof" }) #|} #|fn ParseContext::lex_skip_whitespace(ctx : ParseContext) -> Unit { #| for { #| match ctx.read_char() { #| Some('\t' | ' ' | '\n' | '\r') => continue #| Some(c) => { #| if c > '\u{7f}' && non_ascii_whitespace.contains(c) { #| continue #| } #| ctx.offset -= 1 #| break #| } #| None => break #| } #| } #|} #|fn ParseContext::lex_after_array_value( #| ctx : ParseContext, #|) -> Token raise ParseError { #| ctx.lex_skip_whitespace() #| match ctx.read_char() { #| Some(']') => RBracket #| Some(',') => Comma #| Some(_) => ctx.invalid_char(shift=-1) #| None => raise InvalidEof #| } #|} #|fn ParseContext::lex_after_property_name( #| ctx : ParseContext, #|) -> Unit raise ParseError { #| ctx.lex_skip_whitespace() #| match ctx.read_char() { #| Some(':') => () #| Some(_) => ctx.invalid_char(shift=-1) #| None => raise InvalidEof #| } #|} #|fn ParseContext::lex_after_object_value( #| ctx : ParseContext, #|) -> Token raise ParseError { #| ctx.lex_skip_whitespace() #| match ctx.read_char() { #| Some('}') => RBrace #| Some(',') => Comma #| Some(_) => ctx.invalid_char(shift=-1) #| None => raise InvalidEof #| } #|} #|fn ParseContext::lex_property_name( #| ctx : ParseContext, #|) -> Token raise ParseError { #| ctx.lex_skip_whitespace() #| match ctx.read_char() { #| Some('}') => RBrace #| Some('"') => { #| let s = ctx.lex_string() #| String(s) #| } #| Some(_) => ctx.invalid_char(shift=-1) #| None => raise InvalidEof #| } #|} #|fn ParseContext::lex_property_name2( #| ctx : ParseContext, #|) -> Token raise ParseError { #| ctx.lex_skip_whitespace() #| match ctx.read_char() { #| Some('"') => { #| let s = ctx.lex_string() #| String(s) #| } #| Some(_) => ctx.invalid_char(shift=-1) #| None => raise InvalidEof #| } #|} ), "lex_number.mbt": ( #|fn ParseContext::lex_decimal_integer( #| ctx : ParseContext, #| start~ : Int, #|) -> (Double, String?) raise ParseError { #| for { #| match ctx.read_char() { #| Some('.') => return ctx.lex_decimal_point(start~) #| Some('e' | 'E') => return ctx.lex_decimal_exponent(start~) #| Some(c) => { #| if c >= '0' && c <= '9' { #| continue #| } #| ctx.offset -= 1 #| return ctx.lex_number_end(start, ctx.offset) #| } #| None => return ctx.lex_number_end(start, ctx.offset) #| } #| } #|} #|fn ParseContext::lex_decimal_point( #| ctx : ParseContext, #| start~ : Int, #|) -> (Double, String?) raise ParseError { #| match ctx.read_char() { #| Some(c) => #| if c >= '0' && c <= '9' { #| ctx.lex_decimal_fraction(start~) #| } else { #| ctx.invalid_char(shift=-1) #| } #| None => raise InvalidEof #| } #|} #|fn ParseContext::lex_decimal_fraction( #| ctx : ParseContext, #| start~ : Int, #|) -> (Double, String?) raise ParseError { #| for { #| match ctx.read_char() { #| Some('e' | 'E') => return ctx.lex_decimal_exponent(start~) #| Some(c) => { #| if c >= '0' && c <= '9' { #| continue #| } #| ctx.offset -= 1 #| return ctx.lex_number_end(start, ctx.offset) #| } #| None => return ctx.lex_number_end(start, ctx.offset) #| } #| } #|} #|fn ParseContext::lex_decimal_exponent( #| ctx : ParseContext, #| start~ : Int, #|) -> (Double, String?) raise ParseError { #| match ctx.read_char() { #| Some('+') | Some('-') => return ctx.lex_decimal_exponent_sign(start~) #| Some(c) => { #| if c >= '0' && c <= '9' { #| return ctx.lex_decimal_exponent_integer(start~) #| } #| ctx.offset -= 1 #| ctx.invalid_char() #| } #| None => raise InvalidEof #| } #|} #|fn ParseContext::lex_decimal_exponent_sign( #| ctx : ParseContext, #| start~ : Int, #|) -> (Double, String?) raise ParseError { #| match ctx.read_char() { #| Some(c) => { #| if c >= '0' && c <= '9' { #| return ctx.lex_decimal_exponent_integer(start~) #| } #| ctx.offset -= 1 #| ctx.invalid_char() #| } #| None => raise InvalidEof #| } #|} #|fn ParseContext::lex_decimal_exponent_integer( #| ctx : ParseContext, #| start~ : Int, #|) -> (Double, String?) { #| for { #| match ctx.read_char() { #| Some(c) => { #| if c >= '0' && c <= '9' { #| continue #| } #| ctx.offset -= 1 #| return ctx.lex_number_end(start, ctx.offset) #| } #| None => return ctx.lex_number_end(start, ctx.offset) #| } #| } #|} #|fn ParseContext::lex_zero( #| ctx : ParseContext, #| start~ : Int, #|) -> (Double, String?) raise ParseError { #| match ctx.read_char() { #| Some('.') => ctx.lex_decimal_point(start~) #| Some('e' | 'E') => ctx.lex_decimal_exponent(start~) #| Some(c) => { #| if c >= '0' && c <= '9' { #| ctx.offset -= 1 #| ctx.invalid_char() #| } #| ctx.offset -= 1 #| return ctx.lex_number_end(start, ctx.offset) #| } #| None => return ctx.lex_number_end(start, ctx.offset) #| } #|} #|fn ParseContext::lex_number_end( #| ctx : ParseContext, #| start : Int, #| end : Int, #|) -> (Double, String?) { #| let s = ctx.input.substring(start~, end~) #| if !s.contains(".") && !s.contains("e") && !s.contains("E") { #| let parsed_int = try? @strconv.parse_int64(s) #| match parsed_int { #| Ok(i) if i <= 9007199254740991 && i >= -9007199254740991 => #| return (i.to_double(), None) #| _ => #| return if s is ['-', ..] { #| (@double.neg_infinity, Some(s)) #| } else { #| (@double.infinity, Some(s)) #| } #| } #| } else { #| let parsed_double = try? @strconv.parse_double(s) #| match parsed_double { #| Ok(d) => (d, None) #| Err(_) => #| if s is ['-', ..] { #| (@double.neg_infinity, Some(s)) #| } else { #| (@double.infinity, Some(s)) #| } #| } #| } #|} ), "lex_string.mbt": ( #|fn ParseContext::lex_string(ctx : ParseContext) -> String raise ParseError { #| let buf = StringBuilder::new() #| let mut start = ctx.offset #| fn flush(end : Int) { #| if start > 0 && end > start { #| buf.write_substring(ctx.input, start, end - start) #| } #| } #| for { #| match ctx.read_char() { #| Some('"') => { #| flush(ctx.offset - 1) #| break #| } #| Some('\n' | '\r') => ctx.invalid_char(shift=-1) #| Some('\\') => { #| flush(ctx.offset - 1) #| match ctx.read_char() { #| Some('b') => buf.write_char('\b') #| Some('f') => buf.write_char('\u{0C}') #| Some('n') => buf.write_char('\n') #| Some('r') => buf.write_char('\r') #| Some('t') => buf.write_char('\t') #| Some('"') => buf.write_char('"') #| Some('\\') => buf.write_char('\\') #| Some('/') => buf.write_char('/') #| Some('u') => { #| let c = ctx.lex_hex_digits(4) #| buf.write_char(c.unsafe_to_char()) #| } #| Some(_) => ctx.invalid_char(shift=-1) #| None => raise InvalidEof #| } #| start = ctx.offset #| } #| Some(ch) => #| if ch.to_int() < 32 { #| ctx.invalid_char(shift=-1) #| } else { #| continue #| } #| None => raise InvalidEof #| } #| } #| buf.to_string() #|} #|fn ParseContext::lex_hex_digits( #| ctx : ParseContext, #| n : Int, #|) -> Int raise ParseError { #| let mut r = 0 #| for i in 0.. #| if c >= 'A' { #| let d = (c.to_int() & (32).lnot()) - 'A'.to_int() + 10 #| if d > 15 { #| ctx.invalid_char(shift=-1) #| } #| r = (r << 4) | d #| } else if c >= '0' { #| let d = c.to_int() - '0'.to_int() #| if d > 9 { #| ctx.invalid_char(shift=-1) #| } #| r = (r << 4) | d #| } else { #| ctx.invalid_char(shift=-1) #| } #| None => raise InvalidEof #| } #| } #| r #|} ), "parse.mbt": ( #|pub fn valid(input : String) -> Bool { #| try { #| parse(input) |> ignore #| true #| } catch { #| _ => return false #| } #|} #|pub fn parse(input : String) -> Json raise ParseError { #| let ctx = ParseContext::make(input) #| let val = ctx.parse_value() #| ctx.lex_skip_whitespace() #| if ctx.offset >= ctx.end_offset { #| val #| } else { #| ctx.invalid_char() #| } #|} #|fn ParseContext::parse_value(ctx : ParseContext) -> Json raise ParseError { #| let tok = ctx.lex_value(allow_rbracket=false) #| ctx.parse_value2(tok) #|} #|fn ParseContext::parse_value2( #| ctx : ParseContext, #| tok : Token, #|) -> Json raise ParseError { #| match tok { #| Null => null #| True => Json::boolean(true) #| False => Json::boolean(false) #| Number(n, repr) => Json::number(n, repr?) #| String(s) => Json::string(s) #| LBrace => ctx.parse_object() #| LBracket => ctx.parse_array() #| RBracket | RBrace | Comma => abort("unreachable") #| } #|} #|fn ParseContext::parse_object(ctx : ParseContext) -> Json raise ParseError { #| let map = Map::new() #| loop ctx.lex_property_name() { #| RBrace => Json::object(map) #| String(name) => { #| ctx.lex_after_property_name() #| map[name] = ctx.parse_value() #| match ctx.lex_after_object_value() { #| Comma => continue ctx.lex_property_name2() #| RBrace => Json::object(map) #| _ => abort("unreachable") #| } #| } #| _ => abort("unreachable") #| } #|} #|fn ParseContext::parse_array(ctx : ParseContext) -> Json raise ParseError { #| let vec = [] #| loop ctx.lex_value(allow_rbracket=true) { #| RBracket => Json::array(vec) #| tok => { #| vec.push(ctx.parse_value2(tok)) #| let tok2 = ctx.lex_after_array_value() #| match tok2 { #| Comma => continue ctx.lex_value(allow_rbracket=false) #| RBracket => Json::array(vec) #| _ => abort("unreachable") #| } #| } #| } #|} ), "tuple_fromjson.mbt": ( #|pub impl[A : FromJson, B : FromJson] FromJson for (A, B) with from_json( #| json, #| path, #|) { #| match json { #| [a, b] => { #| let a : A = FromJson::from_json(a, path.add_index(0)) #| let b : B = FromJson::from_json(b, path.add_index(1)) #| (a, b) #| } #| _ => decode_error(path, "expected tuple of size 2") #| } #|} #|pub impl[A : FromJson, B : FromJson, C : FromJson] FromJson for (A, B, C) with from_json( #| json, #| path, #|) { #| match json { #| [a, b, c] => { #| let a : A = FromJson::from_json(a, path.add_index(0)) #| let b : B = FromJson::from_json(b, path.add_index(1)) #| let c : C = FromJson::from_json(c, path.add_index(2)) #| (a, b, c) #| } #| _ => decode_error(path, "expected tuple of size 3") #| } #|} #|pub impl[A : FromJson, B : FromJson, C : FromJson, D : FromJson] FromJson for ( #| A, #| B, #| C, #| D, #|) with from_json(json, path) { #| match json { #| [a, b, c, d] => { #| let a : A = FromJson::from_json(a, path.add_index(0)) #| let b : B = FromJson::from_json(b, path.add_index(1)) #| let c : C = FromJson::from_json(c, path.add_index(2)) #| let d : D = FromJson::from_json(d, path.add_index(3)) #| (a, b, c, d) #| } #| _ => decode_error(path, "expected tuple of size 4") #| } #|} #|pub impl[A : FromJson, B : FromJson, C : FromJson, D : FromJson, E : FromJson] FromJson for ( #| A, #| B, #| C, #| D, #| E, #|) with from_json(json, path) { #| match json { #| [a, b, c, d, e] => { #| let a : A = FromJson::from_json(a, path.add_index(0)) #| let b : B = FromJson::from_json(b, path.add_index(1)) #| let c : C = FromJson::from_json(c, path.add_index(2)) #| let d : D = FromJson::from_json(d, path.add_index(3)) #| let e : E = FromJson::from_json(e, path.add_index(4)) #| (a, b, c, d, e) #| } #| _ => decode_error(path, "expected tuple of size 5") #| } #|} #|pub impl[ #| A : FromJson, #| B : FromJson, #| C : FromJson, #| D : FromJson, #| E : FromJson, #| F : FromJson, #|] FromJson for (A, B, C, D, E, F) with from_json(json, path) { #| match json { #| [a, b, c, d, e, f] => { #| let a : A = FromJson::from_json(a, path.add_index(0)) #| let b : B = FromJson::from_json(b, path.add_index(1)) #| let c : C = FromJson::from_json(c, path.add_index(2)) #| let d : D = FromJson::from_json(d, path.add_index(3)) #| let e : E = FromJson::from_json(e, path.add_index(4)) #| let f : F = FromJson::from_json(f, path.add_index(5)) #| (a, b, c, d, e, f) #| } #| _ => decode_error(path, "expected tuple of size 6") #| } #|} #|pub impl[ #| A : FromJson, #| B : FromJson, #| C : FromJson, #| D : FromJson, #| E : FromJson, #| F : FromJson, #| G : FromJson, #|] FromJson for (A, B, C, D, E, F, G) with from_json(json, path) { #| match json { #| [a, b, c, d, e, f, g] => { #| let a : A = FromJson::from_json(a, path.add_index(0)) #| let b : B = FromJson::from_json(b, path.add_index(1)) #| let c : C = FromJson::from_json(c, path.add_index(2)) #| let d : D = FromJson::from_json(d, path.add_index(3)) #| let e : E = FromJson::from_json(e, path.add_index(4)) #| let f : F = FromJson::from_json(f, path.add_index(5)) #| let g : G = FromJson::from_json(g, path.add_index(6)) #| (a, b, c, d, e, f, g) #| } #| _ => decode_error(path, "expected tuple of size 7") #| } #|} #|pub impl[ #| T0 : FromJson, #| T1 : FromJson, #| T2 : FromJson, #| T3 : FromJson, #| T4 : FromJson, #| T5 : FromJson, #| T6 : FromJson, #| T7 : FromJson, #|] FromJson for (T0, T1, T2, T3, T4, T5, T6, T7) with from_json(json, path) { #| match json { #| [x0, x1, x2, x3, x4, x5, x6, x7] => { #| let x0 : T0 = FromJson::from_json(x0, path.add_index(0)) #| let x1 : T1 = FromJson::from_json(x1, path.add_index(1)) #| let x2 : T2 = FromJson::from_json(x2, path.add_index(2)) #| let x3 : T3 = FromJson::from_json(x3, path.add_index(3)) #| let x4 : T4 = FromJson::from_json(x4, path.add_index(4)) #| let x5 : T5 = FromJson::from_json(x5, path.add_index(5)) #| let x6 : T6 = FromJson::from_json(x6, path.add_index(6)) #| let x7 : T7 = FromJson::from_json(x7, path.add_index(7)) #| (x0, x1, x2, x3, x4, x5, x6, x7) #| } #| _ => decode_error(path, "expected tuple of size 8") #| } #|} #|pub impl[ #| T0 : FromJson, #| T1 : FromJson, #| T2 : FromJson, #| T3 : FromJson, #| T4 : FromJson, #| T5 : FromJson, #| T6 : FromJson, #| T7 : FromJson, #| T8 : FromJson, #|] FromJson for (T0, T1, T2, T3, T4, T5, T6, T7, T8) with from_json(json, path) { #| match json { #| [x0, x1, x2, x3, x4, x5, x6, x7, x8] => { #| let x0 : T0 = FromJson::from_json(x0, path.add_index(0)) #| let x1 : T1 = FromJson::from_json(x1, path.add_index(1)) #| let x2 : T2 = FromJson::from_json(x2, path.add_index(2)) #| let x3 : T3 = FromJson::from_json(x3, path.add_index(3)) #| let x4 : T4 = FromJson::from_json(x4, path.add_index(4)) #| let x5 : T5 = FromJson::from_json(x5, path.add_index(5)) #| let x6 : T6 = FromJson::from_json(x6, path.add_index(6)) #| let x7 : T7 = FromJson::from_json(x7, path.add_index(7)) #| let x8 : T8 = FromJson::from_json(x8, path.add_index(8)) #| (x0, x1, x2, x3, x4, x5, x6, x7, x8) #| } #| _ => decode_error(path, "expected tuple of size 9") #| } #|} #|pub impl[ #| T0 : FromJson, #| T1 : FromJson, #| T2 : FromJson, #| T3 : FromJson, #| T4 : FromJson, #| T5 : FromJson, #| T6 : FromJson, #| T7 : FromJson, #| T8 : FromJson, #| T9 : FromJson, #|] FromJson for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) with from_json( #| json, #| path, #|) { #| match json { #| [x0, x1, x2, x3, x4, x5, x6, x7, x8, x9] => { #| let x0 : T0 = FromJson::from_json(x0, path.add_index(0)) #| let x1 : T1 = FromJson::from_json(x1, path.add_index(1)) #| let x2 : T2 = FromJson::from_json(x2, path.add_index(2)) #| let x3 : T3 = FromJson::from_json(x3, path.add_index(3)) #| let x4 : T4 = FromJson::from_json(x4, path.add_index(4)) #| let x5 : T5 = FromJson::from_json(x5, path.add_index(5)) #| let x6 : T6 = FromJson::from_json(x6, path.add_index(6)) #| let x7 : T7 = FromJson::from_json(x7, path.add_index(7)) #| let x8 : T8 = FromJson::from_json(x8, path.add_index(8)) #| let x9 : T9 = FromJson::from_json(x9, path.add_index(9)) #| (x0, x1, x2, x3, x4, x5, x6, x7, x8, x9) #| } #| _ => decode_error(path, "expected tuple of size 10") #| } #|} #|pub impl[ #| T0 : FromJson, #| T1 : FromJson, #| T2 : FromJson, #| T3 : FromJson, #| T4 : FromJson, #| T5 : FromJson, #| T6 : FromJson, #| T7 : FromJson, #| T8 : FromJson, #| T9 : FromJson, #| T10 : FromJson, #|] FromJson for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) with from_json( #| json, #| path, #|) { #| match json { #| [x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10] => { #| let x0 : T0 = FromJson::from_json(x0, path.add_index(0)) #| let x1 : T1 = FromJson::from_json(x1, path.add_index(1)) #| let x2 : T2 = FromJson::from_json(x2, path.add_index(2)) #| let x3 : T3 = FromJson::from_json(x3, path.add_index(3)) #| let x4 : T4 = FromJson::from_json(x4, path.add_index(4)) #| let x5 : T5 = FromJson::from_json(x5, path.add_index(5)) #| let x6 : T6 = FromJson::from_json(x6, path.add_index(6)) #| let x7 : T7 = FromJson::from_json(x7, path.add_index(7)) #| let x8 : T8 = FromJson::from_json(x8, path.add_index(8)) #| let x9 : T9 = FromJson::from_json(x9, path.add_index(9)) #| let x10 : T10 = FromJson::from_json(x10, path.add_index(10)) #| (x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10) #| } #| _ => decode_error(path, "expected tuple of size 11") #| } #|} #|pub impl[ #| T0 : FromJson, #| T1 : FromJson, #| T2 : FromJson, #| T3 : FromJson, #| T4 : FromJson, #| T5 : FromJson, #| T6 : FromJson, #| T7 : FromJson, #| T8 : FromJson, #| T9 : FromJson, #| T10 : FromJson, #| T11 : FromJson, #|] FromJson for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) with from_json( #| json, #| path, #|) { #| match json { #| [x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11] => { #| let x0 : T0 = FromJson::from_json(x0, path.add_index(0)) #| let x1 : T1 = FromJson::from_json(x1, path.add_index(1)) #| let x2 : T2 = FromJson::from_json(x2, path.add_index(2)) #| let x3 : T3 = FromJson::from_json(x3, path.add_index(3)) #| let x4 : T4 = FromJson::from_json(x4, path.add_index(4)) #| let x5 : T5 = FromJson::from_json(x5, path.add_index(5)) #| let x6 : T6 = FromJson::from_json(x6, path.add_index(6)) #| let x7 : T7 = FromJson::from_json(x7, path.add_index(7)) #| let x8 : T8 = FromJson::from_json(x8, path.add_index(8)) #| let x9 : T9 = FromJson::from_json(x9, path.add_index(9)) #| let x10 : T10 = FromJson::from_json(x10, path.add_index(10)) #| let x11 : T11 = FromJson::from_json(x11, path.add_index(11)) #| (x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11) #| } #| _ => decode_error(path, "expected tuple of size 12") #| } #|} #|pub impl[ #| T0 : FromJson, #| T1 : FromJson, #| T2 : FromJson, #| T3 : FromJson, #| T4 : FromJson, #| T5 : FromJson, #| T6 : FromJson, #| T7 : FromJson, #| T8 : FromJson, #| T9 : FromJson, #| T10 : FromJson, #| T11 : FromJson, #| T12 : FromJson, #|] FromJson for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) with from_json( #| json, #| path, #|) { #| match json { #| [x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12] => { #| let x0 : T0 = FromJson::from_json(x0, path.add_index(0)) #| let x1 : T1 = FromJson::from_json(x1, path.add_index(1)) #| let x2 : T2 = FromJson::from_json(x2, path.add_index(2)) #| let x3 : T3 = FromJson::from_json(x3, path.add_index(3)) #| let x4 : T4 = FromJson::from_json(x4, path.add_index(4)) #| let x5 : T5 = FromJson::from_json(x5, path.add_index(5)) #| let x6 : T6 = FromJson::from_json(x6, path.add_index(6)) #| let x7 : T7 = FromJson::from_json(x7, path.add_index(7)) #| let x8 : T8 = FromJson::from_json(x8, path.add_index(8)) #| let x9 : T9 = FromJson::from_json(x9, path.add_index(9)) #| let x10 : T10 = FromJson::from_json(x10, path.add_index(10)) #| let x11 : T11 = FromJson::from_json(x11, path.add_index(11)) #| let x12 : T12 = FromJson::from_json(x12, path.add_index(12)) #| (x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12) #| } #| _ => decode_error(path, "expected tuple of size 13") #| } #|} #|pub impl[ #| T0 : FromJson, #| T1 : FromJson, #| T2 : FromJson, #| T3 : FromJson, #| T4 : FromJson, #| T5 : FromJson, #| T6 : FromJson, #| T7 : FromJson, #| T8 : FromJson, #| T9 : FromJson, #| T10 : FromJson, #| T11 : FromJson, #| T12 : FromJson, #| T13 : FromJson, #|] FromJson for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) with from_json( #| json, #| path, #|) { #| match json { #| [x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13] => { #| let x0 : T0 = FromJson::from_json(x0, path.add_index(0)) #| let x1 : T1 = FromJson::from_json(x1, path.add_index(1)) #| let x2 : T2 = FromJson::from_json(x2, path.add_index(2)) #| let x3 : T3 = FromJson::from_json(x3, path.add_index(3)) #| let x4 : T4 = FromJson::from_json(x4, path.add_index(4)) #| let x5 : T5 = FromJson::from_json(x5, path.add_index(5)) #| let x6 : T6 = FromJson::from_json(x6, path.add_index(6)) #| let x7 : T7 = FromJson::from_json(x7, path.add_index(7)) #| let x8 : T8 = FromJson::from_json(x8, path.add_index(8)) #| let x9 : T9 = FromJson::from_json(x9, path.add_index(9)) #| let x10 : T10 = FromJson::from_json(x10, path.add_index(10)) #| let x11 : T11 = FromJson::from_json(x11, path.add_index(11)) #| let x12 : T12 = FromJson::from_json(x12, path.add_index(12)) #| let x13 : T13 = FromJson::from_json(x13, path.add_index(13)) #| (x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13) #| } #| _ => decode_error(path, "expected tuple of size 14") #| } #|} #|pub impl[ #| T0 : FromJson, #| T1 : FromJson, #| T2 : FromJson, #| T3 : FromJson, #| T4 : FromJson, #| T5 : FromJson, #| T6 : FromJson, #| T7 : FromJson, #| T8 : FromJson, #| T9 : FromJson, #| T10 : FromJson, #| T11 : FromJson, #| T12 : FromJson, #| T13 : FromJson, #| T14 : FromJson, #|] FromJson for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) with from_json( #| json, #| path, #|) { #| match json { #| [x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14] => { #| let x0 : T0 = FromJson::from_json(x0, path.add_index(0)) #| let x1 : T1 = FromJson::from_json(x1, path.add_index(1)) #| let x2 : T2 = FromJson::from_json(x2, path.add_index(2)) #| let x3 : T3 = FromJson::from_json(x3, path.add_index(3)) #| let x4 : T4 = FromJson::from_json(x4, path.add_index(4)) #| let x5 : T5 = FromJson::from_json(x5, path.add_index(5)) #| let x6 : T6 = FromJson::from_json(x6, path.add_index(6)) #| let x7 : T7 = FromJson::from_json(x7, path.add_index(7)) #| let x8 : T8 = FromJson::from_json(x8, path.add_index(8)) #| let x9 : T9 = FromJson::from_json(x9, path.add_index(9)) #| let x10 : T10 = FromJson::from_json(x10, path.add_index(10)) #| let x11 : T11 = FromJson::from_json(x11, path.add_index(11)) #| let x12 : T12 = FromJson::from_json(x12, path.add_index(12)) #| let x13 : T13 = FromJson::from_json(x13, path.add_index(13)) #| let x14 : T14 = FromJson::from_json(x14, path.add_index(14)) #| (x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14) #| } #| _ => decode_error(path, "expected tuple of size 15") #| } #|} #|pub impl[ #| T0 : FromJson, #| T1 : FromJson, #| T2 : FromJson, #| T3 : FromJson, #| T4 : FromJson, #| T5 : FromJson, #| T6 : FromJson, #| T7 : FromJson, #| T8 : FromJson, #| T9 : FromJson, #| T10 : FromJson, #| T11 : FromJson, #| T12 : FromJson, #| T13 : FromJson, #| T14 : FromJson, #| T15 : FromJson, #|] FromJson for ( #| T0, #| T1, #| T2, #| T3, #| T4, #| T5, #| T6, #| T7, #| T8, #| T9, #| T10, #| T11, #| T12, #| T13, #| T14, #| T15, #|) with from_json(json, path) { #| match json { #| [x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15] => { #| let x0 : T0 = FromJson::from_json(x0, path.add_index(0)) #| let x1 : T1 = FromJson::from_json(x1, path.add_index(1)) #| let x2 : T2 = FromJson::from_json(x2, path.add_index(2)) #| let x3 : T3 = FromJson::from_json(x3, path.add_index(3)) #| let x4 : T4 = FromJson::from_json(x4, path.add_index(4)) #| let x5 : T5 = FromJson::from_json(x5, path.add_index(5)) #| let x6 : T6 = FromJson::from_json(x6, path.add_index(6)) #| let x7 : T7 = FromJson::from_json(x7, path.add_index(7)) #| let x8 : T8 = FromJson::from_json(x8, path.add_index(8)) #| let x9 : T9 = FromJson::from_json(x9, path.add_index(9)) #| let x10 : T10 = FromJson::from_json(x10, path.add_index(10)) #| let x11 : T11 = FromJson::from_json(x11, path.add_index(11)) #| let x12 : T12 = FromJson::from_json(x12, path.add_index(12)) #| let x13 : T13 = FromJson::from_json(x13, path.add_index(13)) #| let x14 : T14 = FromJson::from_json(x14, path.add_index(14)) #| let x15 : T15 = FromJson::from_json(x15, path.add_index(15)) #| (x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15) #| } #| _ => decode_error(path, "expected tuple of size 16") #| } #|} ), "types.mbt": ( #|pub(all) struct Position { #| line : Int // 1-based #| column : Int // 0-based #|} derive(Eq, ToJson) #|pub(all) suberror ParseError { #| InvalidChar(Position, Char) #| InvalidEof #| InvalidNumber(Position, String) #| InvalidIdentEscape(Position) #|} derive(Eq, ToJson(style="flat")) #|pub impl Show for ParseError with output(self, logger) { #| match self { #| InvalidChar({ line, column }, c) => #| logger #| ..write_string("Invalid character ") #| ..write_string(repr(c)) #| ..write_string(" at line ") #| ..write_object(line) #| ..write_string(", column ") #| ..write_object(column) #| InvalidEof => logger.write_string("Unexpected end of file") #| InvalidNumber({ line, column }, s) => #| logger #| ..write_string("Invalid number ") #| ..write_string(s) #| ..write_string(" at line ") #| ..write_object(line) #| ..write_string(", column ") #| ..write_object(column) #| InvalidIdentEscape({ line, column }) => #| logger #| ..write_string("Invalid escape sequence in identifier at line ") #| ..write_object(line) #| ..write_string(", column ") #| ..write_object(column) #| } #|} #|pub impl Show for Json with output(self, logger) { #| match self { #| Null => logger.write_string("Null") #| True => logger.write_string("True") #| False => logger.write_string("False") #| Number(n, repr~) => { #| logger.write_string("Number(") #| Show::output(n, logger) #| if repr is Some(_) { #| logger.write_string(", repr=") #| Show::output(repr, logger) #| } #| logger.write_string(")") #| } #| String(s) => { #| logger.write_string("String(") #| Show::output(s, logger) #| logger.write_string(")") #| } #| Array(a) => { #| logger.write_string("Array(") #| Show::output(a, logger) #| logger.write_string(")") #| } #| Object(o) => { #| logger.write_string("Object(") #| Show::output(o, logger) #| logger.write_string(")") #| } #| } #|} ), "utils.mbt": ( #|fn offset_to_position(input : String, offset : Int) -> Position { #| let mut line = 1 #| let mut column = 0 #| for i in 0.. T raise ParseError { #| let offset = ctx.offset + shift #| let replacement_char : Char = '\u{fffd}' #| raise InvalidChar( #| offset_to_position(ctx.input, offset), #| ctx.input.get_char(offset).unwrap_or(replacement_char), #| ) #|} ), }, ) ///| let moonbitlang_core_list_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/list", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/array": moonbitlang_core_array_module, "moonbitlang/core/quickcheck": moonbitlang_core_quickcheck_module, "moonbitlang/core/json": moonbitlang_core_json_module, }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/builtin", #| "moonbitlang/core/array", #| "moonbitlang/core/quickcheck", #| "moonbitlang/core/json" #| ], #| "test-import": [], #| "targets": { #| "panic_test.mbt": [ #| "not", #| "native" #| ] #| } #|} ), "deprecated.mbt": ( #|#deprecated("use `_.to_array().rev_fold(...)` instead") #|pub fn[A, B] rev_fold(self : List[A], init~ : B, f : (B, A) -> B) -> B { #| let xs = self.to_array() #| let mut acc = init #| for x in xs.rev_iter() { #| acc = f(acc, x) #| } #| acc #|} #|#deprecated("use `_.rev().foldi(...)` instead") #|pub fn[A, B] rev_foldi(self : List[A], init~ : B, f : (Int, B, A) -> B) -> B { #| self.rev().foldi(init~, (i, b, a) => f(i, b, a)) #|} #|#deprecated("use `unsafe_tail` instead") #|pub fn[A] tail(self : List[A]) -> List[A] { #| match self { #| Empty => Empty #| More(_, tail~) => tail #| } #|} ), "list.mbt": ( #|pub fn[A] new() -> List[A] { #| Empty #|} #|pub fn[A] empty() -> List[A] { #| Empty #|} #|pub fn[A] construct(head : A, tail : List[A]) -> List[A] { #| More(head, tail~) #|} #|pub fn[A] prepend(self : List[A], head : A) -> List[A] { #| More(head, tail=self) #|} #|pub fn[A] add(self : List[A], head : A) -> List[A] { #| More(head, tail=self) #|} #|pub impl[A : Show] Show for List[A] with output(xs, logger) { #| logger.write_iter(xs.iter(), prefix="@list.of([", suffix="])") #|} #|pub impl[A : ToJson] ToJson for List[A] with to_json(self) { #| let capacity = self.length() #| guard capacity != 0 else { return [] } #| let jsons = Array::new(capacity~) #| for a in self { #| jsons.push(a.to_json()) #| } #| Json::array(jsons) #|} #|pub fn[A : ToJson] to_json(self : List[A]) -> Json { #| ToJson::to_json(self) #|} #|pub impl[A : @json.FromJson] @json.FromJson for List[A] with from_json( #| json, #| path, #|) { #| guard json is Array(arr) else { #| raise @json.JsonDecodeError((path, "@list.from_json: expected array")) #| } #| for i = arr.length() - 1, list = Empty; i >= 0; { #| continue i - 1, list.prepend(A::from_json(arr[i], path.add_index(i))) #| } else { #| list #| } #|} #|pub fn[A : @json.FromJson] from_json( #| json : Json, #|) -> List[A] raise @json.JsonDecodeError { #| @json.from_json(json) #|} #|pub fn[A] from_array(arr : Array[A]) -> List[A] { #| for i = arr.length() - 1, list = Empty; i >= 0; { #| continue i - 1, More(arr[i], tail=list) #| } else { #| list #| } #|} #|pub fn[A] length(self : List[A]) -> Int { #| loop (self, 0) { #| (Empty, len) => len #| (More(_, tail=rest), acc) => continue (rest, acc + 1) #| } #|} #|#locals(f) #|pub fn[A] each(self : List[A], f : (A) -> Unit raise?) -> Unit raise? { #| loop self { #| Empty => () #| More(head, tail~) => { #| f(head) #| continue tail #| } #| } #|} #|pub fn[A] eachi(self : List[A], f : (Int, A) -> Unit raise?) -> Unit raise? { #| loop (self, 0) { #| (Empty, _) => () #| (More(x, tail=xs), i) => { #| f(i, x) #| continue (xs, i + 1) #| } #| } #|} #|pub fn[A, B] map(self : List[A], f : (A) -> B raise?) -> List[B] raise? { #| match self { #| Empty => Empty #| More(hd, tail~) => { #| let dest = More(f(hd), tail=Empty) #| loop (dest, tail) { #| (_, Empty) => () #| (More(_) as dest, More(hd, tail~)) => { #| dest.tail = More(f(hd), tail=Empty) #| continue (dest.tail, tail) #| } #| (Empty, _) => panic() #| } #| dest #| } #| } #|} #|pub fn[A, B] mapi(self : List[A], f : (Int, A) -> B raise?) -> List[B] raise? { #| match self { #| Empty => Empty #| More(hd, tail~) => { #| let dest = More(f(0, hd), tail=Empty) #| loop (1, dest, tail) { #| (_, _, Empty) => () #| (i, More(_) as dest, More(hd, tail~)) => { #| dest.tail = More(f(i, hd), tail=Empty) #| continue (i + 1, dest.tail, tail) #| } #| (_, Empty, _) => panic() #| } #| dest #| } #| } #|} #|pub fn[A, B] rev_map(self : List[A], f : (A) -> B raise?) -> List[B] raise? { #| loop (Empty, self) { #| (acc, Empty) => acc #| (acc, More(x, tail=xs)) => continue (More(f(x), tail=acc), xs) #| } #|} #|pub fn[A] to_array(self : List[A]) -> Array[A] { #| match self { #| Empty => [] #| More(x, tail=xs) => { #| let arr = [x] #| loop xs { #| Empty => () #| More(x, tail=xs) => { #| arr.push(x) #| continue xs #| } #| } #| arr #| } #| } #|} #|pub fn[A] filter(self : List[A], f : (A) -> Bool raise?) -> List[A] raise? { #| loop self { #| Empty => Empty #| More(head, tail~) => #| if !f(head) { #| continue tail #| } else { #| let dest = More(head, tail=Empty) #| loop (dest, tail) { #| (_, Empty) => () #| (More(_) as dest, More(hd, tail~)) => #| if f(hd) { #| dest.tail = More(hd, tail=Empty) #| continue (dest.tail, tail) #| } else { #| continue (dest, tail) #| } #| (Empty, _) => #| panic() #| } #| dest #| } #| } #|} #|pub fn[A] all(self : List[A], f : (A) -> Bool raise?) -> Bool raise? { #| loop self { #| Empty => true #| More(head, tail~) => if f(head) { continue tail } else { false } #| } #|} #|pub fn[A] any(self : List[A], f : (A) -> Bool raise?) -> Bool raise? { #| loop self { #| Empty => false #| More(head, tail~) => if f(head) { true } else { continue tail } #| } #|} #|#internal(unsafe, "Panic if the list is empty") #|pub fn[A] unsafe_head(self : List[A]) -> A { #| match self { #| Empty => abort("head of empty list") #| More(head, tail=_) => head #| } #|} #|pub fn[A] unsafe_tail(self : List[A]) -> List[A] { #| match self { #| Empty => abort("tail of empty list") #| More(_, tail~) => tail #| } #|} #|pub fn[A] head(self : List[A]) -> A? { #| match self { #| Empty => None #| More(head, tail=_) => Some(head) #| } #|} #|#internal(unsafe, "Panic if the list is empty") #|pub fn[A] unsafe_last(self : List[A]) -> A { #| loop self { #| Empty => abort("last of empty list") #| More(head, tail=Empty) => head #| More(_, tail~) => continue tail #| } #|} #|pub fn[A] last(self : List[A]) -> A? { #| loop self { #| Empty => None #| More(head, tail=Empty) => Some(head) #| More(_, tail~) => continue tail #| } #|} #|pub fn[A] concat(self : List[A], other : List[A]) -> List[A] { #| match self { #| Empty => other #| More(hd, tail=Empty) => More(hd, tail=other) #| More(hd, tail~) => { #| let dest = More(hd, tail=Empty) #| loop (dest, tail) { #| (More(_) as dest, Empty) => dest.tail = other #| (More(_) as dest, More(head, tail~)) => { #| dest.tail = More(head, tail=Empty) #| continue (dest.tail, tail) #| } #| (Empty, _) => panic() #| } #| dest #| } #| } #|} #|pub fn[A] rev_concat(self : List[A], other : List[A]) -> List[A] { #| loop (self, other) { #| (Empty, other) => other #| (More(head, tail~), other) => continue (tail, More(head, tail=other)) #| } #|} #|pub fn[A] rev(self : List[A]) -> List[A] { #| self.rev_concat(Empty) #|} #|pub fn[A, B] fold( #| self : List[A], #| init~ : B, #| f : (B, A) -> B raise?, #|) -> B raise? { #| loop (self, init) { #| (Empty, acc) => acc #| (More(head, tail~), acc) => continue (tail, f(acc, head)) #| } #|} #|pub fn[A, B] foldi( #| self : List[A], #| init~ : B, #| f : (Int, B, A) -> B raise?, #|) -> B raise? { #| fn go( #| xs : List[A], #| i : Int, #| f : (Int, B, A) -> B raise?, #| acc : B, #| ) -> B raise? { #| match xs { #| Empty => acc #| More(x, tail=xs) => go(xs, i + 1, f, f(i, acc, x)) #| } #| } #| go(self, 0, f, init) #|} #|pub fn[A, B] List::zip(self : List[A], other : List[B]) -> List[(A, B)] { #| let res = loop (self, other, Empty) { #| (Empty, _, acc) => break acc #| (_, Empty, acc) => break acc #| (More(x, tail=xs), More(y, tail=ys), acc) => #| continue (xs, ys, More((x, y), tail=acc)) #| } #| res.reverse_inplace() #|} #|pub fn[A, B] flat_map( #| self : List[A], #| f : (A) -> List[B] raise?, #|) -> List[B] raise? { #| loop self { #| Empty => Empty #| More(head, tail~) => #| match f(head) { #| Empty => continue tail #| More(hd, tail=tl) => { #| let dest = More(hd, tail=Empty) #| let dest1 = loop (dest, tl) { #| (dest, Empty) => dest #| (More(_) as dest, More(hd, tail~)) => { #| dest.tail = More(hd, tail=Empty) #| continue (dest.tail, tail) #| } #| (Empty, _) => panic() #| } #| loop_over_tail~: loop (dest1, tail) { #| (_, Empty) => () #| (More(_) as dest, More(t_hd, tail=Empty)) => dest.tail = f(t_hd) #| (dest, More(t_hd, tail=t_tl)) => #| loop (dest, f(t_hd)) { #| (dest, Empty) => continue loop_over_tail~ (dest, t_tl) #| (More(_) as dest, More(hd, tail~)) => { #| dest.tail = More(hd, tail=Empty) #| continue (dest.tail, tail) #| } #| (Empty, _) => panic() #| } #| } #| dest #| } #| } #| } #|} #|pub fn[A, B] filter_map(self : List[A], f : (A) -> B? raise?) -> List[B] raise? { #| loop self { #| Empty => Empty #| More(hd, tail~) => #| match f(hd) { #| None => continue tail #| Some(head) => { #| let dest = More(head, tail=Empty) #| loop (dest, tail) { #| (_, Empty) => () #| (More(_) as dest, More(hd, tail~)) => #| match f(hd) { #| None => continue (dest, tail) #| Some(head) => { #| dest.tail = More(head, tail=Empty) #| continue (dest.tail, tail) #| } #| } #| (Empty, _) => panic() #| } #| dest #| } #| } #| } #|} #|#internal(unsafe, "Panic if the index is out of bounds") #|pub fn[A] unsafe_nth(self : List[A], n : Int) -> A { #| loop (self, n) { #| (Empty, _) => abort("nth: index out of bounds") #| (More(head, tail=_), 0) => head #| (More(_, tail~), n) => continue (tail, n - 1) #| } #|} #|pub fn[A] nth(self : List[A], n : Int) -> A? { #| loop (self, n) { #| (Empty, _) => None #| (More(head, tail=_), 0) => Some(head) #| (More(_, tail~), n) => continue (tail, n - 1) #| } #|} #|pub fn[A] repeat(n : Int, x : A) -> List[A] { #| loop (Empty, n) { #| (acc, n) => if n <= 0 { acc } else { continue (More(x, tail=acc), n - 1) } #| } #|} #|pub fn[A] intersperse(self : List[A], separator : A) -> List[A] { #| match self { #| Empty => Empty #| More(head, tail=Empty) => More(head, tail=Empty) #| More(head, tail~) => { #| let dest = More(head, tail=Empty) #| loop (dest, tail) { #| (_, Empty) => () #| (More(_) as dest, More(hd, tail=tl)) => { #| let new_tail = More(hd, tail=Empty) #| dest.tail = More(separator, tail=new_tail) #| continue (new_tail, tl) #| } #| (Empty, _) => panic() #| } #| dest #| } #| } #|} #|pub fn[A] is_empty(self : List[A]) -> Bool { #| self is Empty #|} #|pub fn[A, B] unzip(self : List[(A, B)]) -> (List[A], List[B]) { #| match self { #| Empty => (Empty, Empty) #| More((x, y), tail~) => { #| let xs = More(x, tail=Empty) #| let ys = More(y, tail=Empty) #| loop (tail, xs, ys) { #| (Empty, _, _) => () #| (More((x, y), tail~), More(_) as xptr, More(_) as yptr) => { #| xptr.tail = More(x, tail=Empty) #| yptr.tail = More(y, tail=Empty) #| continue (tail, xptr.tail, yptr.tail) #| } #| (_, _, _) => abort("unreachable") #| } #| (xs, ys) #| } #| } #|} #|pub fn[A] flatten(self : List[List[A]]) -> List[A] { #| loop self { #| Empty => Empty #| More(head, tail~) => #| match head { #| Empty => continue tail #| More(hd, tail=tl) => { #| let dest = More(hd, tail=Empty) #| let dest1 = loop (dest, tl) { #| (dest, Empty) => dest #| (More(_) as dest, More(hd, tail~)) => { #| dest.tail = More(hd, tail=Empty) #| continue (dest.tail, tail) #| } #| (Empty, _) => panic() #| } #| loop_over_tail~: loop (dest1, tail) { #| (_, Empty) => () #| (More(_) as dest, More(t_hd, tail=Empty)) => dest.tail = t_hd #| (dest, More(t_hd, tail=t_tl)) => #| loop (dest, t_hd) { #| (dest, Empty) => continue loop_over_tail~ (dest, t_tl) #| (More(_) as dest, More(hd, tail~)) => { #| dest.tail = More(hd, tail=Empty) #| continue (dest.tail, tail) #| } #| (Empty, _) => panic() #| } #| } #| dest #| } #| } #| } #|} #|#internal(unsafe, "Panic if the list is empty") #|pub fn[A : Compare] unsafe_maximum(self : List[A]) -> A { #| match self { #| Empty => abort("maximum: empty list") #| More(head, tail~) => #| loop (tail, head) { #| (Empty, curr_max) => curr_max #| (More(item, tail~), curr_max) => #| continue (tail, if item > curr_max { item } else { curr_max }) #| } #| } #|} #|pub fn[A : Compare] maximum(self : List[A]) -> A? { #| match self { #| Empty => None #| More(head, tail~) => #| loop (tail, head) { #| (Empty, curr_max) => Some(curr_max) #| (More(item, tail~), curr_max) => #| continue (tail, if item > curr_max { item } else { curr_max }) #| } #| } #|} #|#internal(unsafe, "Panic if the list is empty") #|pub fn[A : Compare] unsafe_minimum(self : List[A]) -> A { #| match self { #| Empty => abort("minimum: empty list") #| More(head, tail~) => #| loop (tail, head) { #| (Empty, curr_min) => curr_min #| (More(item, tail~), curr_min) => #| continue (tail, if item < curr_min { item } else { curr_min }) #| } #| } #|} #|pub fn[A : Compare] minimum(self : List[A]) -> A? { #| match self { #| Empty => None #| More(head, tail~) => #| loop (tail, head) { #| (Empty, curr_min) => Some(curr_min) #| (More(item, tail~), curr_min) => #| continue (tail, if item < curr_min { item } else { curr_min }) #| } #| } #|} #|pub fn[A : Compare] sort(self : List[A]) -> List[A] { #| let arr = self.to_array() #| arr.sort() #| from_array(arr) #|} #|pub impl[A] Add for List[A] with op_add(self, other) { #| self.concat(other) #|} #|pub fn[A : Eq] contains(self : List[A], value : A) -> Bool { #| loop self { #| Empty => false #| More(x, tail=xs) => if x == value { true } else { continue xs } #| } #|} #|pub fn[A, S] unfold(f : (S) -> (A, S)? raise?, init~ : S) -> List[A] raise? { #| match f(init) { #| None => Empty #| Some((element, new_state)) => { #| let dest = More(element, tail=Empty) #| loop (dest, f(new_state)) { #| (_, None) => () #| (More(_) as dest, Some((element, new_state))) => { #| dest.tail = More(element, tail=Empty) #| continue (dest.tail, f(new_state)) #| } #| (Empty, _) => panic() #| } #| dest #| } #| } #|} #|pub fn[A, S] rev_unfold(f : (S) -> (A, S)? raise?, init~ : S) -> List[A] raise? { #| loop (f(init), Empty) { #| (None, acc) => acc #| (Some((x, s)), acc) => continue (f(s), More(x, tail=acc)) #| } #|} #|pub fn[A] take(self : List[A], n : Int) -> List[A] { #| if n <= 0 { #| Empty #| } else { #| match self { #| Empty => Empty #| More(head, tail~) => { #| let dest = More(head, tail=Empty) #| loop (dest, tail, n - 1) { #| (_, Empty, _) => () #| (_, _, 0) => () #| (More(_) as dest, More(x, tail=xs), n) => { #| dest.tail = More(x, tail=Empty) #| continue (dest.tail, xs, n - 1) #| } #| (Empty, _, _) => panic() #| } #| dest #| } #| } #| } #|} #|pub fn[A] drop(self : List[A], n : Int) -> List[A] { #| if n <= 0 { #| self #| } else { #| loop (n, self) { #| (_, Empty) => Empty #| (1, More(_, tail=xs)) => xs #| (n, More(_, tail=xs)) => continue (n - 1, xs) #| } #| } #|} #|pub fn[A] take_while(self : List[A], p : (A) -> Bool raise?) -> List[A] raise? { #| match self { #| Empty => Empty #| More(head, tail~) => #| if p(head) { #| let dest = More(head, tail=Empty) #| loop (dest, tail) { #| (_, Empty) => () #| (More(_) as dest, More(x, tail=xs)) if p(x) => { #| dest.tail = More(x, tail=Empty) #| continue (dest.tail, xs) #| } #| (More(_), _) => () #| (Empty, _) => panic() #| } #| dest #| } else { #| Empty #| } #| } #|} #|pub fn[A] drop_while(self : List[A], p : (A) -> Bool raise?) -> List[A] raise? { #| loop self { #| Empty => Empty #| More(x, tail=xs) => if p(x) { continue xs } else { More(x, tail=xs) } #| } #|} #|pub fn[A, E] scan_left( #| self : List[A], #| f : (E, A) -> E raise?, #| init~ : E, #|) -> List[E] raise? { #| let dest = More(init, tail=Empty) #| loop (dest, self, init) { #| (_, Empty, _) => () #| (Empty, _, _) => panic() #| (More(_) as dest, More(x, tail=xs), acc) => { #| dest.tail = More(f(acc, x), tail=Empty) #| continue (dest.tail, xs, f(acc, x)) #| } #| } #| dest #|} #|pub fn[A, B] scan_right( #| self : List[A], #| f : (B, A) -> B raise?, #| init~ : B, #|) -> List[B] raise? { #| self.rev().scan_left(f, init~).reverse_inplace() #|} #|pub fn[A : Eq, B] lookup(self : List[(A, B)], v : A) -> B? { #| loop self { #| Empty => None #| More((x, y), tail=xs) => if x == v { Some(y) } else { continue xs } #| } #|} #|pub fn[A] find(self : List[A], f : (A) -> Bool raise?) -> A? raise? { #| loop self { #| Empty => None #| More(element, tail=list) => #| if f(element) { #| Some(element) #| } else { #| continue list #| } #| } #|} #|pub fn[A] List::find_index( #| self : Self[A], #| f : (A) -> Bool raise?, #|) -> Int? raise? { #| loop (self, 0) { #| (Empty, _) => None #| (More(element, tail=list), idx) => #| if f(element) { #| Some(idx) #| } else { #| continue (list, idx + 1) #| } #| } #|} #|pub fn[A] findi(self : List[A], f : (A, Int) -> Bool raise?) -> A? raise? { #| loop (self, 0) { #| (list, index) => #| match list { #| Empty => None #| More(element, tail=list) => #| if f(element, index) { #| Some(element) #| } else { #| continue (list, index + 1) #| } #| } #| } #|} #|pub fn[A] remove_at(self : List[A], index : Int) -> List[A] { #| match (index, self) { #| (_, Empty) => Empty #| (_..<0, _) => self #| (0, More(_, tail~)) => tail #| (n, More(head, tail~)) => { #| let dest = More(head, tail=Empty) #| loop (dest, tail, n - 1) { #| (_, Empty, _) => () #| (More(_) as dest, More(_, tail~), 0) => dest.tail = tail #| (More(_) as dest, More(x, tail=xs), n) => { #| dest.tail = More(x, tail=Empty) #| continue (dest.tail, xs, n - 1) #| } #| (Empty, _, _) => panic() #| } #| dest #| } #| } #|} #|pub fn[A : Eq] remove(self : List[A], elem : A) -> List[A] { #| match self { #| Empty => Empty #| More(head, tail~) if head == elem => tail #| More(head, tail~) => { #| let dest = More(head, tail~) #| loop (dest, tail) { #| (_, Empty) => () #| (More(_) as dest, More(x, tail=xs)) => #| if x == elem { #| dest.tail = xs #| } else { #| dest.tail = More(x, tail=Empty) #| continue (dest.tail, xs) #| } #| (Empty, _) => panic() #| } #| dest #| } #| } #|} #|pub fn[A : Eq] is_prefix(self : List[A], prefix : List[A]) -> Bool { #| loop (self, prefix) { #| (_, Empty) => true #| (Empty, More(_)) => false #| (More(h1, tail=t1), More(h2, tail=t2)) => #| if h1 == h2 { #| continue (t1, t2) #| } else { #| false #| } #| } #|} #|pub fn[A : Eq] is_suffix(self : List[A], suffix : List[A]) -> Bool { #| self.rev().is_prefix(suffix.rev()) #|} #|pub fn[A] intercalate(self : List[List[A]], sep : List[A]) -> List[A] { #| self.intersperse(sep).flatten() #|} #|pub impl[X] Default for List[X] with default() { #| Empty #|} #|pub fn[X] default() -> List[X] { #| Empty #|} #|pub fn[A] iter(self : List[A]) -> Iter[A] { #| Iter::new(yield_ => loop self { #| Empty => IterContinue #| More(head, tail~) => { #| if yield_(head) == IterEnd { #| break IterEnd #| } #| continue tail #| } #| }) #|} #|pub fn[A] iter2(self : List[A]) -> Iter2[Int, A] { #| Iter2::new(yield_ => loop (self, 0) { #| (Empty, _) => IterEnd #| (More(head, tail~), i) => { #| if yield_(i, head) == IterEnd { #| break IterEnd #| } #| continue (tail, i + 1) #| } #| }) #|} #|pub fn[A] from_iter(iter : Iter[A]) -> List[A] { #| let mut res = Empty #| let mut ptr = Empty #| for x in iter { #| match (res, ptr) { #| (Empty, _) => { #| res = More(x, tail=Empty) #| ptr = res #| } #| (More(_), More(_) as ptr_) => { #| ptr_.tail = More(x, tail=Empty) #| ptr = ptr_.tail #| } #| (_, _) => panic() #| } #| } #| res #|} #|pub fn[A] from_iter_rev(iter : Iter[A]) -> List[A] { #| iter.fold(init=Empty, (acc, e) => More(e, tail=acc)) #|} #|pub fn[A] of(arr : FixedArray[A]) -> List[A] { #| for i = arr.length() - 1, list = Empty; i >= 0; { #| continue i - 1, More(arr[i], tail=list) #| } else { #| list #| } #|} #|pub impl[X : @quickcheck.Arbitrary] @quickcheck.Arbitrary for List[X] with arbitrary( #| size, #| rs, #|) { #| @quickcheck.Arbitrary::arbitrary(size, rs) |> from_array #|} #|pub fn[A] singleton(x : A) -> List[A] { #| More(x, tail=Empty) #|} #|pub impl[A : Hash] Hash for List[A] with hash_combine(self, hasher) { #| for e in self { #| hasher.combine(e) #| } #|} #|fn[A] reverse_inplace(self : List[A]) -> List[A] { #| match self { #| Empty | More(_, tail=Empty) => self #| More(head, tail~) => #| loop (More(head, tail=Empty), tail) { #| (result, Empty) => result #| (result, More(_, tail=xs) as new_result) => { #| new_result.tail = result #| continue (new_result, xs) #| } #| } #| } #|} #|pub fnalias List::zip ), "types.mbt": ( #|pub enum List[A] { #| Empty #| More(A, mut tail~ : List[A]) #|} derive(Eq) #|#deprecated("Use List instead of T") #|pub typealias List as T ), }, ) ///| let moonbitlang_core_math_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/math", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/double": moonbitlang_core_double_module, "moonbitlang/core/float": moonbitlang_core_float_module, "moonbitlang/core/int": moonbitlang_core_int_module, "moonbitlang/core/bigint": moonbitlang_core_bigint_module, "moonbitlang/core/random": moonbitlang_core_random_module, }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/builtin", #| "moonbitlang/core/double", #| "moonbitlang/core/float", #| "moonbitlang/core/int", #| "moonbitlang/core/bigint", #| "moonbitlang/core/random" #| ], #| "targets" : { #| "algebraic_double_js.mbt": ["js"], #| "algebraic_double_nonjs.mbt": ["not", "js"], #| "exp_double_js.mbt": ["js"], #| "exp_double_nonjs.mbt": ["not", "js"], #| "log_double_js.mbt": ["js"], #| "log_double_nonjs.mbt": ["not", "js"], #| "pow_double_js.mbt": ["js"], #| "pow_double_nonjs.mbt": ["not", "js"], #| "trig_double_js.mbt": ["js"], #| "trig_double_nonjs.mbt": ["not", "js"], #| "hyperbolic_double_js.mbt": ["js"], #| "hyperbolic_double_nonjs.mbt": ["not", "js"], #| "utils.mbt": ["not", "js"] #| } #|} ), "algebraic.mbt": ( #|#deprecated("Use @cmp.maximum instead") #|pub fn[T : Compare] maximum(x : T, y : T) -> T { #| if x > y { #| x #| } else { #| y #| } #|} #|#deprecated("Use @cmp.minimum instead") #|pub fn[T : Compare] minimum(x : T, y : T) -> T { #| if x > y { #| y #| } else { #| x #| } #|} #|pub fn cbrtf(x : Float) -> Float { #| let b1 : UInt = 709958130 // B1 = (127-127.0/3-0.03306235651)*2**23 */ #| let b2 : UInt = 642849266 // B2 = (127-127.0/3-24/3-0.03306235651)*2**23 */ #| let mut ui : UInt = x.reinterpret_as_uint() #| let mut hx : UInt = ui & 0x7fffffff #| if hx >= 0x7f800000 { #| return x + x #| } #| if hx < 0x00800000 { #| if hx == 0 { #| return x #| } // cbrt(+-0) is itx #| ui = (x * (0x1.0p24 : Float)).reinterpret_as_uint() #| hx = ui & 0x7fffffff #| hx = hx / 3 + b2 #| } else { #| hx = hx / 3 + b1 #| } #| ui = ui & 0x80000000 #| ui = ui | hx #| let dx = x.to_double() #| let t = ui.reinterpret_as_float().to_double() #| let r = t * t * t #| let t = t * (dx + dx + r) / (dx + r + r) #| let r = t * t * t #| let t = t * (dx + dx + r) / (dx + r + r) #| t.to_float() #|} #|pub fn hypotf(x : Float, y : Float) -> Float { #| let epsilon : Float = 1.1920928955078125e-7 #| let x = x.abs() #| let y = y.abs() #| if x.is_inf() || y.is_inf() { #| return @float.infinity #| } #| let (x, y) = if y > x { (y, x) } else { (x, y) } #| if x * epsilon >= y { #| return x #| } #| let rat = y / x #| x * (rat * rat + 1.0).sqrt() #|} ), "algebraic_double_js.mbt": ( #|pub fn cbrt(x : Double) -> Double = "Math" "cbrt" #|pub fn hypot(x : Double, y : Double) -> Double = "Math" "hypot" ), "algebraic_double_nonjs.mbt": ( #|pub fn cbrt(x : Double) -> Double { #| if x.is_inf() || x.is_nan() || x == 0.0 { #| return x #| } #| let b1 : UInt = 715094163 // B1 = (682-0.03306235651)*2**20 #| let b2 : UInt = 696219795 // B2 = (664-0.03306235651)*2**20 #| let c = 5.42857142857142815906e-01 // 19/35 = 0x3FE15F15, 0xF15F15F1 #| let d = -7.05306122448979611050e-01 // -864/1225 = 0xBFE691DE, 0x2532C834 #| let e = 1.41428571428571436819e+00 // 99/70 = 0x3FF6A0EA, 0x0EA0EA0F #| let f = 1.60714285714285720630e+00 // 45/28 = 0x3FF9B6DB, 0x6DB6DB6E #| let g = 3.57142857142857150787e-01 // 5/14 = 0x3FD6DB6D, 0xB6DB6DB7 #| let hx = get_high_word(x).reinterpret_as_int() #| let sign = if x < 0.0 { true } else { false } #| let x = abs(x) #| let t = if hx < 0x00100000 { #| let t : UInt64 = 0x43500000_00000000 #| let t : Double = t.reinterpret_as_double() #| let t = t * x #| set_high_word(0, get_high_word(t) / 3 + b2) #| } else { #| set_high_word(0, hx.reinterpret_as_uint() / 3 + b1) #| } #| let r = t * t / x #| let s = c + r * t #| let t = t * (g + f / (s + e + d / s)) #| let t = set_high_word(0, get_high_word(t) + 0x00000001) #| let s = t * t #| let r = x / s #| let w = t + t #| let r = (r - t) / (w + r) #| let t = t + t * r #| if sign { #| -t #| } else { #| t #| } #|} #|pub fn hypot(x : Double, y : Double) -> Double { #| if x.is_nan() || y.is_nan() { #| return @double.not_a_number #| } #| if x.is_inf() || y.is_inf() { #| return @double.infinity #| } #| let x = x.abs() #| let y = y.abs() #| let double_epsilon : Double = 0x0.0000000000001P-1022 #| let (x, y) = if y > x { (y, x) } else { (x, y) } #| if x * double_epsilon >= y { #| return x #| } #| let r = y / x #| x * (1.0 + r * r).sqrt() #|} ), "deprecated.mbt": ( #|#deprecated("Use `PI` instead") #|pub let pi = 0x3.243F6A8885A308CA8A54 ), "exp.mbt": ( #|fn top12(x : Float) -> UInt { #| x.reinterpret_as_uint() >> 20 #|} #|fn __math_xflowf(sign : UInt, y : Float) -> Float { #| return (if sign != 0 { -y } else { y }) * y #|} #|fn __math_oflowf(sign : UInt) -> Float { #| return __math_xflowf(sign, 0x1.0p97) #|} #|fn __math_uflowf(sign : UInt) -> Float { #| return __math_xflowf(sign, 0x1.0p-95) #|} #|let exp2f_table_bits = 5 #|priv struct Exp2fData { #| tab : FixedArray[UInt64] #| shift : Double #| invln2_scaled : Double #| poly_scaled : FixedArray[Double] #|} #|let expf_n : UInt64 = (1 << exp2f_table_bits).to_uint64() #|let exp2f_data_n : Double = (1 << exp2f_table_bits).to_double() #|let exp2f_data : Exp2fData = { #| tab: [ #| 0x3ff0000000000000, 0x3fefd9b0d3158574, 0x3fefb5586cf9890f, 0x3fef9301d0125b51, #| 0x3fef72b83c7d517b, 0x3fef54873168b9aa, 0x3fef387a6e756238, 0x3fef1e9df51fdee1, #| 0x3fef06fe0a31b715, 0x3feef1a7373aa9cb, 0x3feedea64c123422, 0x3feece086061892d, #| 0x3feebfdad5362a27, 0x3feeb42b569d4f82, 0x3feeab07dd485429, 0x3feea47eb03a5585, #| 0x3feea09e667f3bcd, 0x3fee9f75e8ec5f74, 0x3feea11473eb0187, 0x3feea589994cce13, #| 0x3feeace5422aa0db, 0x3feeb737b0cdc5e5, 0x3feec49182a3f090, 0x3feed503b23e255d, #| 0x3feee89f995ad3ad, 0x3feeff76f2fb5e47, 0x3fef199bdd85529c, 0x3fef3720dcef9069, #| 0x3fef5818dcfba487, 0x3fef7c97337b9b5f, 0x3fefa4afa2a490da, 0x3fefd0765b6e4540, #| ], #| shift: 0x1.8p+52, #| invln2_scaled: 0x1.71547652b82fep+0 * exp2f_data_n, #| poly_scaled: [ #| 0x1.c6af84b912394p-5 / exp2f_data_n / exp2f_data_n / exp2f_data_n, #| 0x1.ebfce50fac4f3p-3 / exp2f_data_n / exp2f_data_n, #| 0x1.62e42ff0c52d6p-1 / exp2f_data_n, #| ], #|} #|pub fn expf(x : Float) -> Float { #| let xd = x.to_double() #| let abstop = top12(x) & 0x7ff #| if abstop >= top12(88.0) { #| if x.reinterpret_as_uint() == @float.neg_infinity.reinterpret_as_uint() { #| return 0.0 #| } #| if abstop >= top12(@float.infinity) { #| return x + x #| } #| if x > 0x1.62e42ep6 { #| return __math_oflowf(0) #| } #| if x < -0x1.9fe368p6 { #| return __math_uflowf(0) #| } #| } #| let z = exp2f_data.invln2_scaled * xd #| let kd = z + exp2f_data.shift #| let ki = kd.reinterpret_as_uint64() #| let kd = kd - exp2f_data.shift #| let r = z - kd #| let t = exp2f_data.tab[(ki % expf_n).to_int()] #| let t = t + (ki << (52 - exp2f_table_bits)) #| let s = t.reinterpret_as_double() #| let z = exp2f_data.poly_scaled[0] * r + exp2f_data.poly_scaled[1] #| let r2 = r * r #| let y = exp2f_data.poly_scaled[2] * r + 1 #| let y = z * r2 + y #| let y = y * s #| y.to_float() #|} #|pub fn expm1f(x : Float) -> Float { #| let float_ln2_hi : Float = 6.9314575195e-01 // 0x3f317200 #| let float_ln2_lo : Float = 1.4286067653e-06 // 0x35bfbe8e #| let inv_ln2 : Float = 1.4426950216e+00 // 0x3fb8aa3b #| let mut x = x #| let q1 : Float = -3.3333212137e-2 // -0x888868.0p-28 #| let q2 : Float = 1.5807170421e-3 // 0xcf3010.0p-33 #| let mut hx = x.reinterpret_as_uint() #| let sign = hx >> 31 != 0 #| hx = hx & 0x7fffffff #| if hx >= 0x4195b844 { #| if hx > 0x7f800000 { #| return x #| } #| if sign { #| return -1.0 #| } #| if hx > 0x42b17217 { #| x *= (0x1.0p127 : Float) #| return x #| } #| } #| let mut k : Int = 0 #| let mut hi : Float = 0 #| let mut lo : Float = 0 #| let mut c : Float = 0 #| if hx > 0x3eb17218 { #| if hx < 0x3F851592 { #| if !sign { #| hi = x - float_ln2_hi #| lo = float_ln2_lo #| k = 1 #| } else { #| hi = x + float_ln2_hi #| lo = -float_ln2_lo #| k = -1 #| } #| } else { #| k = (inv_ln2 * x + (if sign { -0.5 } else { 0.5 })).to_int() #| let t = k.to_float() #| hi = x - t * float_ln2_hi // t*ln2_hi is exact here #| lo = t * float_ln2_lo #| } #| x = hi - lo #| c = hi - x - lo #| } else if hx < 0x33000000 { #| return x #| } else { #| k = 0 #| } #| let hfx = (0.5 : Float) * x #| let hxs = x * hfx #| let r1 = (1.0 : Float) + hxs * (q1 + hxs * q2) #| let t = (3.0 : Float) - r1 * hfx #| let mut e = hxs * ((r1 - t) / ((6.0 : Float) - x * t)) #| if k == 0 { #| return x - (x * e - hxs) #| } #| e = x * (e - c) - c #| e -= hxs #| if k == -1 { #| return (0.5 : Float) * (x - e) - 0.5 #| } #| if k == 1 { #| if x < -0.25 { #| return -(2.0 : Float) * (e - (x + 0.5)) #| } #| return (1.0 : Float) + (2.0 : Float) * (x - e) #| } #| let twopk = ((0x7f + k) << 23).reinterpret_as_float() // 2^k #| if !(k is (0..=56)) { #| let mut y = x - e + 1.0 #| if k == 128 { #| y = y * 2.0 * (0x1.0p127 : Float) #| } else { #| y = y * twopk #| } #| return y - 1.0 #| } #| let uf = ((0x7f - k) << 23).reinterpret_as_float() // 2^-k #| if k < 23 { #| (x - e + ((1.0 : Float) - uf)) * twopk #| } else { #| (x - (e + uf) + 1.0) * twopk #| } #|} ), "exp_double_js.mbt": ( #|pub fn exp(x : Double) -> Double = "Math" "exp" #|pub fn expm1(x : Double) -> Double = "Math" "expm1" ), "exp_double_nonjs.mbt": ( #|pub fn exp(x : Double) -> Double { #| fn get_high_word(x : Double) -> UInt { #| (x.reinterpret_as_uint64() >> 32).to_uint() #| } #| fn get_low_word(x : Double) -> UInt { #| x.reinterpret_as_uint64().to_uint() #| } #| fn insert_words(ix0 : UInt64, ix1 : UInt64) -> Double { #| let mut bits : UInt64 = 0 #| bits = bits | (ix0 << 32) #| bits = bits | ix1 #| bits.reinterpret_as_double() #| } #| let ori_x = x #| let mut x = x #| let one = 1.0 #| let halF = [0.5, -0.5] #| let o_threshold = 7.09782712893383973096e+02 #| let u_threshold = -7.45133219101941108420e+02 #| let ln2HI = [6.93147180369123816490e-01, -6.93147180369123816490e-01] #| let ln2LO = [1.90821492927058770002e-10, -1.90821492927058770002e-10] #| let invln2 = 1.44269504088896338700e+00 #| let p1 = 1.66666666666666019037e-01 #| let p2 = -2.77777777770155933842e-03 #| let p3 = 6.61375632143793436117e-05 #| let p4 = -1.65339022054652515390e-06 #| let p5 = 4.13813679705723846039e-08 #| let e = 2.718281828459045 #| let mut hi = 0.0 #| let mut lo = 0.0 #| let huge = 1.0e+300 #| let twom1000 = 9.33263618503218878990e-302 #| let two1023 = 8.988465674311579539e307 #| let mut k : Int = 0 #| let mut hx : UInt = get_high_word(ori_x) #| let xsb : Int = ((hx >> 31) & 1).reinterpret_as_int() #| hx = hx & 0x7FFFFFFF #| if hx >= 0x40862E42 { #| if hx >= 0x7FF00000 { #| let lx : UInt = get_low_word(ori_x) #| if ((hx & 0xFFFFF) | lx) != 0 { #| return ori_x + ori_x #| } else if xsb == 0 { #| return ori_x #| } else { #| return 0.0 #| } #| } #| if ori_x > o_threshold { #| return huge * huge #| } #| if ori_x < u_threshold { #| return twom1000 * twom1000 #| } #| } #| if hx > 0x3FD62E42 { #| if hx < 0x3FF0A2B2 { #| if ori_x == 1.0 { #| return e #| } #| hi = ori_x - ln2HI[xsb] #| lo = ln2LO[xsb] #| k = 1 - xsb - xsb #| } else { #| k = (invln2 * ori_x + halF[xsb]).to_int() #| let t = k.to_double() #| hi = ori_x - t * ln2HI[0] #| lo = t * ln2LO[0] #| } #| x = hi - lo #| } else if hx < 0x3E300000 { #| if huge + x > one { #| return one + x #| } #| } else { #| k = 0 #| } #| let t = x * x #| let twopk = if k >= -1021 { #| insert_words( #| (0x3FF00000 + (k.reinterpret_as_uint() << 20).reinterpret_as_int()) #| .to_int64() #| .reinterpret_as_uint64(), #| 0, #| ) #| } else { #| insert_words( #| 0x3FF00000UL + ((k + 1000).reinterpret_as_uint() << 20).to_uint64(), #| 0, #| ) #| } #| let c = x - t * (p1 + t * (p2 + t * (p3 + t * (p4 + t * p5)))) #| if k == 0 { #| return one - (x * c / (c - 2.0) - x) #| } #| let y = one - (lo - x * c / (2.0 - c) - hi) #| if k >= -1021 { #| if k == 1024 { #| return y * 2.0 * two1023 #| } else { #| return y * twopk #| } #| } else { #| return y * twopk * twom1000 #| } #|} #|pub fn expm1(x : Double) -> Double { #| if x.is_nan() { #| return @double.not_a_number #| } #| let o_threshold = 7.09782712893383973096e+02 #| if x > o_threshold { #| return @double.infinity #| } #| if x.is_inf() { #| return -1.0 #| } #| let huge = 1.0e+300 #| let tiny = 1.0e-300 #| let ln2_hi = 6.93147180369123816490e-01 #| let ln2_lo = 1.90821492927058770002e-10 #| let invln2 = 1.44269504088896338700e+00 #| let q1 = -3.33333333333331316428e-02 #| let q2 = 1.58730158725481460165e-03 #| let q3 = -7.93650757867487942473e-05 #| let q4 = 4.00821782732936239552e-06 #| let q5 = -2.01099218183624371326e-07 #| let mut x = x #| let mut hx = get_high_word(x) #| let xsb : Int = (hx & 0x80000000).reinterpret_as_int() #| let mut y : Double = if xsb == 0 { x } else { -x } #| hx = hx & 0x7fffffff #| if hx >= 0x4043687A { #| if xsb != 0 { #| if x + tiny < 0.0 { #| return tiny - 1.0 #| } #| } #| } #| let mut hi = 0.0 #| let mut lo = 0.0 #| let mut k = 0 #| let mut c = 0.0 #| let mut t = 0.0 #| if hx > 0x3fd62e42 { #| if hx < 0x3FF0A2B2 { #| hi = if xsb == 0 { x - ln2_hi } else { x + ln2_hi } #| lo = if xsb == 0 { ln2_lo } else { -ln2_lo } #| k = if xsb == 0 { 1 } else { -1 } #| } else { #| k = (invln2 * x + (if xsb == 0 { 0.5 } else { -0.5 })).to_int() #| t = k.to_double() #| hi = x - t * ln2_hi #| lo = t * ln2_lo #| } #| x = hi - lo #| c = hi - x - lo #| } else if hx < 0x3c900000 { #| t = huge + x #| return x - (t - (huge + x)) #| } else { #| k = 0 #| } #| let hfx : Double = 0.5 * x #| let hxs : Double = x * hfx #| let r1 : Double = 1.0 + #| hxs * (q1 + hxs * (q2 + hxs * (q3 + hxs * (q4 + hxs * q5)))) #| let t : Double = 3.0 - r1 * hfx #| let e : Double = hxs * ((r1 - t) / (6.0 - x * t)) #| if k == 0 { #| return x - (x * e - hxs) #| } else { #| let e : Double = x * (e - c) - c #| let e : Double = e - hxs #| if k == -1 { #| return 0.5 * (x - e) - 0.5 #| } #| if k == 1 { #| return if x < -0.25 { #| -2.0 * (e - (x + 0.5)) #| } else { #| 1.0 + 2.0 * (x - e) #| } #| } #| if k <= -2 || k > 56 { #| y = 1.0 - (e - x) #| y = set_high_word(y, get_high_word(y) + (k << 20).reinterpret_as_uint()) #| return y - 1.0 #| } #| let mut t : Double = 1.0 #| if k < 20 { #| t = set_high_word(0, (0x3ff00000 - (0x200000 >> k)).reinterpret_as_uint()) #| y = t - (e - x) #| y = set_high_word(y, get_high_word(y) + (k << 20).reinterpret_as_uint()) #| } else { #| t = set_high_word(0, ((0x3ff - k) << 20).reinterpret_as_uint()) #| y = x - (e + t) + 1.0 #| y = set_high_word(y, get_high_word(y) + (k << 20).reinterpret_as_uint()) #| } #| } #| y #|} ), "hyperbolic.mbt": ( #|fn k_expo2f(x : Float) -> Float { #| let k = 235 #| let k_ln2 = (0x4322e3bc).reinterpret_as_float() #| let scale = ((0x7f + k / 2) << 23).reinterpret_as_float() #| expf(x - k_ln2) * scale * scale #|} #|pub fn sinhf(x : Float) -> Float { #| let mut h : Float = 0.5 #| let mut ix = x.reinterpret_as_uint() #| if ix >> 31 != 0 { #| h = -h #| } #| ix = ix & 0x7fffffff #| let absx = ix.reinterpret_as_float() #| let w = ix #| if w < 0x42b17217 { #| let t = expm1f(absx) #| if w < 0x3f800000 { #| if w < 0x3f800000U - (12U << 23) { #| return x #| } #| return h * ((2.0 : Float) * t - t * t / (t + 1.0)) #| } #| return h * (t + t / (t + 1.0)) #| } #| h * k_expo2f(absx) * 2.0 #|} #|pub fn coshf(x : Float) -> Float { #| let mut x = x #| let mut ix = x.reinterpret_as_uint() #| ix = ix & 0x7fffffff #| x = ix.reinterpret_as_float() #| let w = ix #| if w < 0x3f317217 { #| if w < 0x3f800000U - (12U << 23) { #| return 1.0 #| } #| let t = expm1f(x) #| return (1.0 : Float) + t * t / ((2.0 : Float) * (t + 1.0)) #| } #| if w < 0x42b17217 { #| let t = expf(x) #| return (t + (1.0 : Float) / t) * 0.5 #| } #| k_expo2f(x) #|} #|pub fn tanhf(x : Float) -> Float { #| let mut ix = x.reinterpret_as_uint() #| let sign = ix >> 31 != 0 #| ix = ix & 0x7fffffff #| let x = ix.reinterpret_as_float() #| let w = ix #| let tt = if w > 0x3f0c9f54 { #| if w > 0x41200000 { #| (1.0 : Float) + (0.0 : Float) / x #| } else { #| let t = expm1f(x * 2.0) #| (1.0 : Float) - (2.0 : Float) / (t + 2.0) #| } #| } else if w > 0x3e82c578 { #| let t = expm1f(x * 2.0) #| t / (t + 2.0) #| } else if w >= 0x00800000 { #| let t = expm1f(x * -2.0) #| -t / (t + 2.0) #| } else { #| x #| } #| if sign { #| -tt #| } else { #| tt #| } #|} #|pub fn asinhf(x : Float) -> Float { #| let u = x.reinterpret_as_uint() #| let i = u & 0x7fffffff #| let sign = u >> 31 != 0 #| let ln2 : Float = 0.693147180559945309417232121458176568 #| let x = i.reinterpret_as_float() #| let x = if i >= 0x3f800000U + (12U << 23) { #| lnf(x) + ln2 #| } else if i >= 0x3f800000U + (1U << 23) { #| lnf(x * 2.0 + (1.0 : Float) / ((x * x + 1.0).sqrt() + x)) #| } else if i >= 0x3f800000U - (12U << 23) { #| ln_1pf(x + x * x / ((x * x + 1.0).sqrt() + 1.0)) #| } else { #| x #| } #| if sign { #| -x #| } else { #| x #| } #|} #|pub fn acoshf(x : Float) -> Float { #| let ln2 : Float = 693147180559945309417232121458176568 #| let u = x.reinterpret_as_uint() #| let a = u & 0x7fffffffU #| if a < 0x3f800000U + (1U << 23) { #| return ln_1pf( #| x - 1.0 + ((x - 1.0) * (x - 1.0) + (2.0 : Float) * (x - 1.0)).sqrt(), #| ) #| } #| if a < 0x3f800000U + (12U << 23) { #| return lnf(x * 2.0 - (1.0 : Float) / (x + (x * x - 1.0).sqrt())) #| } #| return lnf(x) + ln2 #|} #|pub fn atanhf(x : Float) -> Float { #| let u = x.reinterpret_as_uint() #| let sign = u >> 31 != 0 #| let u = u & 0x7fffffff #| let x = u.reinterpret_as_float() #| let x = if u < 0x3f800000U - (1U << 23) { #| if u < 0x3f800000U - (32U << 23) { #| x #| } else { #| ln_1pf(x * 2.0 + x * 2.0 * x / ((1.0 : Float) - x)) * 0.5 #| } #| } else { #| ln_1pf(x / ((1.0 : Float) - x) * 2.0) * 0.5 #| } #| if sign { #| -x #| } else { #| x #| } #|} ), "hyperbolic_double_js.mbt": ( #|pub fn sinh(x : Double) -> Double = "Math" "sinh" #|pub fn cosh(x : Double) -> Double = "Math" "cosh" #|pub fn tanh(x : Double) -> Double = "Math" "tanh" #|pub fn asinh(x : Double) -> Double = "Math" "asinh" #|pub fn acosh(x : Double) -> Double = "Math" "acosh" #|pub fn atanh(x : Double) -> Double = "Math" "atanh" ), "hyperbolic_double_nonjs.mbt": ( #|pub fn sinh(x : Double) -> Double { #| if x.is_nan() || x.is_inf() { #| return x #| } #| let ix = get_high_word(x).reinterpret_as_int() & 0x7fffffff #| let abs_x = x.abs() #| let shuge = 1.0e307 #| let h = if x < 0.0 { -0.5 } else { 0.5 } #| if ix < 0x40360000 { #| if ix < 0x3e300000 { #| if shuge + x > 1.0 { #| return x #| } #| } #| let t = expm1(abs_x) #| if ix < 0x3ff00000 { #| return h * (2.0 * t - t * t / (t + 1.0)) #| } #| return h * (t + t / (t + 1.0)) #| } #| if ix < 0x40862E42 { #| return h * exp(abs_x) #| } #| if abs_x.reinterpret_as_uint64() < 0x408633ce8fb9f87d { #| let w = exp(0.5 * abs_x) #| let t = h * w #| return t * w #| } #| x * shuge #|} #|pub fn cosh(x : Double) -> Double { #| if x.is_nan() { #| return x #| } #| if x.is_inf() { #| return @double.infinity #| } #| let ix = get_high_word(x).reinterpret_as_int() & 0x7fffffff #| if ix < 0x3fd62e43 { #| let t = expm1(x.abs()) #| let w = 1.0 + t #| if ix < 0x3c800000 { #| return w #| } #| return 1.0 + t * t / (w + w) #| } #| if ix < 0x40360000 { #| let t = exp(x.abs()) #| return 0.5 * t + 0.5 / t #| } #| if ix < 0x40862E42 { #| return (0.5 * x.abs()) |> exp #| } #| let lx = get_low_word(x).reinterpret_as_int() #| if ix < 0x408633ce || (ix == 0x408633ce && lx <= 0x8fb9f87d) { #| let w = exp(0.5 * x.abs()) #| let t = 0.5 * w #| return t * w #| } #| @double.infinity #|} #|pub fn tanh(x : Double) -> Double { #| if x.is_nan() { #| return x #| } #| if x.is_pos_inf() { #| return 1.0 #| } #| if x.is_neg_inf() { #| return -1.0 #| } #| let ix = get_high_word(x).reinterpret_as_int() & 0x7fffffff #| let tiny = 1.0e-300 #| let z = if ix < 0x40360000 { #| if ix < 0x3c800000 { #| x * (1.0 + x) #| } else if ix >= 0x3ff00000 { #| let t = (2.0 * x.abs()) |> expm1 #| 1.0 - 2.0 / (t + 2.0) #| } else { #| let t = (-2.0 * x.abs()) |> expm1 #| -t / (t + 2.0) #| } #| } else { #| 1.0 - tiny #| } #| if x >= 0.0 { #| z #| } else { #| -z #| } #|} #|pub fn asinh(x : Double) -> Double { #| if x.is_nan() || x.is_inf() { #| return x #| } #| let one : Double = 1.0 #| let ln2 : Double = 6.93147180559945286227e-01 #| let huge : Double = 1.0e300 #| let hx = get_high_word(x).reinterpret_as_int() #| let ix = hx & 0x7fffffff #| if ix < 0x3e300000 { #| if huge + x > one { #| return x #| } #| } #| let w : Double = if ix > 0x41b00000 { #| ln(x.abs()) + ln2 #| } else if ix > 0x40000000 { #| let t = x.abs() #| (2.0 * t + one / ((x * x + one).sqrt() + t)) |> ln #| } else { #| let t = x * x #| (x.abs() + t / (one + (one + t).sqrt())) |> ln_1p #| } #| if hx > 0 { #| w #| } else { #| -w #| } #|} #|pub fn acosh(x : Double) -> Double { #| let one = 1.0 #| let hx = get_high_word(x).reinterpret_as_int() #| if x < 1.0 || x.is_nan() { #| return @double.not_a_number #| } else if x == 1.0 { #| return 0.0 #| } else if x.is_pos_inf() { #| return @double.infinity #| } else if hx >= 0x41b00000 { #| return ln(x) + LN2 #| } else if hx > 0x40000000 { #| let t = x * x #| return (2.0 * x - one / (x + (t - one).sqrt())) |> ln #| } else { #| let t = x - one #| return (t + (2.0 * t + t * t).sqrt()) |> ln_1p #| } #|} #|pub fn atanh(x : Double) -> Double { #| let hx : Int = get_high_word(x).reinterpret_as_int() #| let ix = hx & 0x7fffffff #| if x.abs() > 1.0 { #| return @double.not_a_number #| } #| if x == 1.0 { #| return @double.infinity #| } #| if x == -1.0 { #| return @double.neg_infinity #| } #| if ix < 0x3e300000 && 1.0e300 + x > 0.0 { #| return x #| } #| let x = x.abs() #| let t = if x <= 0.5 { #| let t = x + x #| 0.5 * ln_1p(t + t * x / (1.0 - x)) #| } else { #| 0.5 * ln_1p((x + x) / (1.0 - x)) #| } #| if hx >= 0 { #| t #| } else { #| -t #| } #|} ), "log.mbt": ( #|let logf_off = 0x3f330000U #|let logf_table_bits = 4 #|let logf_n : UInt = 1U << logf_table_bits #|priv struct LogfData { #| invc : FixedArray[Double] #| logc : FixedArray[Double] #| ln2 : Double #| poly : FixedArray[Double] #|} #|let logf_data : LogfData = { #| invc: [ #| 0x1.661ec79f8f3bep+0, 0x1.571ed4aaf883dp+0, 0x1.49539f0f010bp+0, 0x1.3c995b0b80385p+0, #| 0x1.30d190c8864a5p+0, 0x1.25e227b0b8eap+0, 0x1.1bb4a4a1a343fp+0, 0x1.12358f08ae5bap+0, #| 0x1.0953f419900a7p+0, 0x1.0p+0, 0x1.e608cfd9a47acp-1, 0x1.ca4b31f026aap-1, 0x1.b2036576afce6p-1, #| 0x1.9c2d163a1aa2dp-1, 0x1.886e6037841edp-1, 0x1.767dcf5534862p-1, #| ], #| logc: [ #| -0x1.57bf7808caadep-2, -0x1.2bef0a7c06ddbp-2, -0x1.01eae7f513a67p-2, -0x1.b31d8a68224e9p-3, #| -0x1.6574f0ac07758p-3, -0x1.1aa2bc79c81p-3, -0x1.a4e76ce8c0e5ep-4, -0x1.1973c5a611cccp-4, #| -0x1.252f438e10c1ep-5, 0x0.0p+0, 0x1.aa5aa5df25984p-5, 0x1.c5e53aa362eb4p-4, #| 0x1.526e57720db08p-3, 0x1.bc2860d22477p-3, 0x1.1058bc8a07ee1p-2, 0x1.4043057b6ee09p-2, #| ], #| ln2: 0x1.62e42fefa39efp-1, #| poly: [-0x1.00ea348b88334p-2, 0x1.5575b0be00b6ap-2, -0x1.ffffef20a4123p-2], #|} #|pub fn lnf(x : Float) -> Float { #| let mut ix : UInt = x.reinterpret_as_uint() #| if ix == 0x3f800000U { #| return 0.0 #| } #| if ix - 0x00800000U >= 0x7f800000U - 0x00800000U { #| if ix * 2 == 0 { #| return @float.neg_infinity #| } #| if ix == 0x7f800000U { #| return x #| } #| if (ix & 0x80000000U) != 0 || ix * 2 >= 0xff000000U { #| return @float.not_a_number #| } #| ix = (x * 0x1.0p23).reinterpret_as_uint() #| ix -= (23 << 23).reinterpret_as_uint() #| } #| let tmp = ix - logf_off #| let i = ((tmp >> (23 - logf_table_bits)) % logf_n).reinterpret_as_int() #| let k = tmp.reinterpret_as_int() >> 23 #| let iz = ix - (tmp & 0xff800000U) #| let invc = logf_data.invc[i] #| let logc = logf_data.logc[i] #| let z = iz.reinterpret_as_float().to_double() #| let r = z * invc - 1 #| let y0 = logc + k.to_double() * logf_data.ln2 #| let r2 = r * r #| let y = logf_data.poly[1] * r + logf_data.poly[2] #| let y = logf_data.poly[0] * r2 + y #| let y = y * r2 + (y0 + r) #| y.to_float() #|} #|pub fn ln_1pf(x : Float) -> Float { #| let lg1_f : Float = 0.66666662693 #| let lg2_f : Float = 0.40000972152 #| let lg3_f : Float = 0.28498786688 #| let lg4_f : Float = 0.24279078841 #| let float_ln2_hi : Float = 6.9314575195e-01 // 0x3f317200 #| let float_ln2_lo : Float = 1.4286067653e-06 // 0x35bfbe8e #| let mut ui : UInt = x.reinterpret_as_uint() #| let mut f : Float = 0 #| let mut c : Float = 0 #| let mut iu : UInt = 0 #| let one : Float = 1.0 #| let mut k = 1 #| if ui < 0x3ed413d0 || ui >> 31 > 0 { #| if ui >= 0xbf800000 { #| if x == -1.0 { #| return x / 0.0 #| } #| return (x - x) / 0.0 #| } #| if ui << 1 < 0x33800000U << 1 { #| return x #| } #| if ui <= 0xbe95f619 { #| k = 0 #| c = 0.0 #| f = x #| } #| } else if ui >= 0x7f800000 { #| return x #| } #| if k > 0 { #| ui = (one + x).reinterpret_as_uint() #| iu = ui #| iu += 0x3f800000U - 0x3f3504f3U #| k = (iu >> 23).reinterpret_as_int() - 0x7f #| if k < 25 { #| let fui = ui.reinterpret_as_float() #| c = if k >= 2 { one - (fui - x) } else { x - (fui - 1.0) } #| c /= ui.reinterpret_as_float() #| } else { #| c = 0.0 #| } #| iu = (iu & 0x007fffff) + 0x3f3504f3 #| ui = iu #| f = ui.reinterpret_as_float() - 1.0 #| } #| let s = f / (f + 2.0) #| let z = s * s #| let w = z * z #| let t1 = w * (lg2_f + w * lg4_f) #| let t2 = z * (lg1_f + w * lg3_f) #| let r = t2 + t1 #| let hfsq = f * f * 0.5 #| let dk = k.to_float() #| s * (hfsq + r) + (dk * float_ln2_lo + c) - hfsq + f + dk * float_ln2_hi #|} ), "log_double_js.mbt": ( #|pub fn ln(x : Double) -> Double = "Math" "log" #|pub fn log2(x : Double) -> Double = "Math" "log2" #|pub fn log10(x : Double) -> Double = "Math" "log10" #|pub fn ln_1p(x : Double) -> Double = "Math" "log1p" ), "log_double_nonjs.mbt": ( #|pub fn ln(x : Double) -> Double { #| let l1 = 6.666666666666735130e-01 // 3FE55555 55555593 #| let l2 = 3.999999999940941908e-01 // 3FD99999 9997FA04 #| let l3 = 2.857142874366239149e-01 // 3FD24924 94229359 #| let l4 = 2.222219843214978396e-01 // 3FCC71C5 1D8E78AF #| let l5 = 1.818357216161805012e-01 // 3FC74664 96CB03DE #| let l6 = 1.531383769920937332e-01 // 3FC39A09 D078C69F #| let l7 = 1.479819860511658591e-01 // 3FC2F112 DF3E5244 #| if x < 0.0 { #| return @double.not_a_number #| } else if x.is_nan() || x.is_inf() { #| return x #| } else if x == 0.0 { #| return @double.neg_infinity #| } #| let (f1, ki) = frexp(x) #| let (f, k) = if f1 < SQRT2 / 2.0 { #| (f1 * 2.0 - 1.0, (ki - 1).to_double()) #| } else { #| (f1 - 1.0, ki.to_double()) #| } #| let s = f / (2.0 + f) #| let s2 = s * s #| let s4 = s2 * s2 #| let t1 = s2 * (l1 + s4 * (l3 + s4 * (l5 + s4 * l7))) #| let t2 = s4 * (l2 + s4 * (l4 + s4 * l6)) #| let r = t1 + t2 #| let hfsq = 0.5 * f * f #| k * LN2_HI - (hfsq - (s * (hfsq + r) + k * LN2_LO) - f) #|} #|pub fn log2(x : Double) -> Double { #| let (f, e) = frexp(x) #| if f == 0.5 { #| return e.to_double() - 1.0 #| } #| ln(f) / LN2 + e.to_double() #|} #|pub fn log10(x : Double) -> Double { #| if x < 0.0 { #| return @double.not_a_number #| } else if x.is_nan() || x.is_inf() { #| return x #| } else if x == 0.0 { #| return @double.neg_infinity #| } #| let ivln10 = 4.34294481903251816668e-01 #| let log10_2hi = 3.01029995663611771306e-01 #| let log10_2lo = 3.69423907715893078616e-13 #| let (f, e) = frexp(x) #| let (f, e) = if e >= 1 { #| (f * 2.0, (e - 1).to_double()) #| } else { #| (f, e.to_double()) #| } #| let z = e * log10_2lo + ivln10 * ln(f) #| z + e * log10_2hi #|} #|pub fn ln_1p(x : Double) -> Double { #| if x < -1.0 || x.is_nan() { #| return @double.not_a_number #| } #| if x == -1.0 { #| return @double.neg_infinity #| } #| if x.is_inf() { #| return @double.infinity #| } #| let ln2_hi = 6.93147180369123816490e-01 #| let ln2_lo = 1.90821492927058770002e-10 #| let two54 = 1.80143985094819840000e+16 #| let lp1 = 6.666666666666735130e-01 #| let lp2 = 3.999999999940941908e-01 #| let lp3 = 2.857142874366239149e-01 #| let lp4 = 2.222219843214978396e-01 #| let lp5 = 1.818357216161805012e-01 #| let lp6 = 1.531383769920937332e-01 #| let zero = 0.0 #| let lp7 = 1.479819860511658591e-01 #| let hx = get_high_word(x).reinterpret_as_int() #| let ax = hx & 0x7fffffff #| let mut f = 0.0 #| let mut c = 0.0 #| let mut s = 0.0 #| let mut z = 0.0 #| let mut r = 0.0 #| let mut u = 0.0 #| let mut hu = 0 #| let mut k = 1 #| if hx < 0x3FDA827A { #| if ax < 0x3e200000 { #| if two54 + x > zero && ax < 0x3c900000 { #| return x #| } else { #| return x - x * x * 0.5 #| } #| } #| if hx > 0 || hx <= 0xbfd2bec3 { #| k = 0 #| f = x #| hu = 1 #| } #| } #| if k != 0 { #| if hx < 0x43400000 { #| u = 1.0 + x #| hu = get_high_word(u).reinterpret_as_int() #| k = (hu >> 20) - 1023 #| c = if k > 0 { 1.0 - (u - x) } else { x - (u - 1.0) } #| c /= u #| } else { #| u = x #| hu = get_high_word(u).reinterpret_as_int() #| k = (hu >> 20) - 1023 #| c = 0.0 #| } #| hu = hu & 0x000fffff #| if hu < 0x6a09e { #| u = set_high_word(u, hu.reinterpret_as_uint() | 0x3ff00000) #| } else { #| k += 1 #| u = set_high_word(u, hu.reinterpret_as_uint() | 0x3fe00000) #| hu = (0x00100000 - hu) >> 2 #| } #| f = u - 1.0 #| } #| let hfsq = 0.5 * f * f #| if hu == 0 { #| if f == zero { #| if k == 0 { #| return zero #| } else { #| c += k.to_double() * ln2_lo #| return k.to_double() * ln2_hi + c #| } #| } #| r = hfsq * (1.0 - 0.66666666666666666 * f) #| if k == 0 { #| return f - r #| } else { #| return k.to_double() * ln2_hi - (r - (k.to_double() * ln2_lo + c) - f) #| } #| } #| s = f / (2.0 + f) #| z = s * s #| r = z * #| (lp1 + z * (lp2 + z * (lp3 + z * (lp4 + z * (lp5 + z * (lp6 + z * lp7)))))) #| if k == 0 { #| return f - (hfsq - s * (hfsq + r)) #| } else { #| return k.to_double() * ln2_hi - #| (hfsq - (s * (hfsq + r) + (k.to_double() * ln2_lo + c)) - f) #| } #|} ), "pow.mbt": ( #|pub fn powf(base : Float, exponent : Float) -> Float { #| let huge : Float = 1.0e30 #| let tiny : Float = 1.0e-30 #| let cp : Float = 9.6179670095e-01 // 0x3f76384f =2/(3ln2) */ #| let cp_h : Float = 9.6191406250e-01 // 0x3f764000 =12b cp */ #| let cp_l : Float = -1.1736857402e-04 // 0xb8f623c6 =tail of cp_h */ #| let lg2 : Float = 6.9314718246e-01 // 0x3f317218 */ #| let lg2_h : Float = 6.93145752e-01 // 0x3f317200 */ #| let lg2_l : Float = 1.4286067653e-06 // 0x35bfbe8c */ #| let ovt : Float = 8.0085662595e-08 // -(2**-28)/(log(2)**2) */ #| let ivln2 : Float = 1.4426950216e+00 // 0x3f317218 */ #| let ivln2_h : Float = 1.4426879883e+00 // 0x3f317218 */ #| let ivln2_l : Float = 7.0526075433e-06 // 0x35bfbe8c */ #| let l1 : Float = 6.0000002384e-01 // 0x3f19999a */ #| let l2 : Float = 4.2857143283e-01 // 0x3edb6db7 */ #| let l3 : Float = 3.3333334327e-01 // 0x3eaaaaab */ #| let l4 : Float = 2.7272811532e-01 // 0x3e8ba305 */ #| let l5 : Float = 2.3066075146e-01 // 0x3e6c3255 */ #| let l6 : Float = 2.0697501302e-01 // 0x3e53f142 */ #| let p1 : Float = 1.6666667163e-01 // 0x3e2aaaab */ #| let p2 : Float = -2.7777778450e-03 // 0xbb360b61 */ #| let p3 : Float = 6.6137559770e-05 // 0x388ab355 */ #| let p4 : Float = -1.6533901999e-06 // 0xb5ddea0e */ #| let p5 : Float = 4.1381369442e-08 // 0x3331bb4c */ #| let mut z : Float = 0 #| let mut ax : Float = 0 #| let mut z_h : Float = 0 #| let mut z_l : Float = 0 #| let mut p_h : Float = 0 #| let mut p_l : Float = 0 #| let mut y1 : Float = 0 #| let mut t1 : Float = 0 #| let mut t2 : Float = 0 #| let mut r : Float = 0 #| let mut s : Float = 0 #| let mut sn : Float = 0 #| let mut t : Float = 0 #| let mut u : Float = 0 #| let mut v : Float = 0 #| let mut w : Float = 0 #| let mut i : Int = 0 #| let mut j : Int = 0 #| let mut k : Int = 0 #| let mut yisint : Int = 0 #| let mut n : Int = 0 #| let mut hx : Int = 0 #| let mut hy : Int = 0 #| let mut ix : Int = 0 #| let mut iy : Int = 0 #| let mut i_s : Int = 0 #| let (x, y) = (base, exponent) #| let bp : Array[Float] = [1.0, 1.5] #| let dp_h : Array[Float] = [0.0, 5.84960938e-01] // 0x3f15c000 */ #| let dp_l : Array[Float] = [0.0, 1.56322085e-06] // 0x35d1cfdc */ #| let two24 : Float = 16777216.0 #| hx = x.reinterpret_as_int() #| hy = y.reinterpret_as_int() #| ix = hx & 0x7fffffff #| iy = hy & 0x7fffffff #| if iy == 0 { #| return 1.0 #| } #| if hx == 0x3f800000 { #| return 1.0 #| } #| if ix > 0x7f800000 || iy > 0x7f800000 { #| return x + y #| } #| yisint = 0 #| if hx < 0 { #| if iy >= 0x4b800000 { #| yisint = 2 // even integer y #| } else if iy >= 0x3f800000 { #| k = (iy >> 23) - 0x7f // exponent #| j = iy >> (23 - k) #| if j << (23 - k) == iy { #| yisint = 2 - (j & 1) #| } #| } #| } #| if iy == 0x7f800000 { #| if ix == 0x3f800000 { #| return 1.0 #| } else if ix > 0x3f800000 { #| return if hy >= 0 { y } else { 0.0 } #| } else { #| return if hy >= 0 { 0.0 } else { -y } #| } #| } #| if iy == 0x3f800000 { #| return if hy >= 0 { x } else { (1.0 : Float) / x } #| } #| if hy == 0x40000000 { #| return x * x #| } #| if hy == 0x3f000000 && hx >= 0 { #| return x.sqrt() #| } #| ax = x.abs() #| if ix == 0x7f800000 || ix == 0 || ix == 0x3f800000 { #| z = ax #| if hy < 0 { #| z = (1.0 : Float) / z #| } #| if hx < 0 { #| if ((ix - 0x3f800000) | yisint) == 0 { #| z = (z - z) / (z - z) // (-1)**non-int is NaN #| } else if yisint == 1 { #| z = -z #| } #| } // (x<0)**odd = -(|x|**odd) #| return z #| } #| sn = 1.0 // sign of result #| if hx < 0 { #| if yisint == 0 { #| return @float.not_a_number #| } #| if yisint == 1 { #| sn = -1.0 #| } #| } #| if iy > 0x4d000000 { #| if ix < 0x3f7ffff8 { #| return if hy < 0 { sn * huge * huge } else { sn * tiny * tiny } #| } #| if ix > 0x3f800007 { #| return if hy > 0 { sn * huge * huge } else { sn * tiny * tiny } #| } #| t = ax - 1.0 // t has 20 trailing zeros #| w = t * t * ((0.5 : Float) - t * ((0.333333333333 : Float) - t * 0.25)) #| u = ivln2_h * t // IVLN2_H has 16 sig. bits #| v = t * ivln2_l - w * ivln2 #| t1 = u + v #| i_s = t1.reinterpret_as_int() #| t1 = (i_s & 0xfffff000).reinterpret_as_float() #| t2 = v - (t1 - u) #| } else { #| let mut s2 : Float = 0 #| let mut s_h : Float = 0 #| let mut s_l : Float = 0 #| let mut t_h : Float = 0 #| let mut t_l : Float = 0 #| n = 0 #| if ix < 0x00800000 { #| ax *= two24 #| n -= 24 #| ix = ax.reinterpret_as_int() #| } #| n += (ix >> 23) - 0x7f #| j = ix & 0x007fffff #| ix = j | 0x3f800000 // normalize ix #| if j <= 0x1cc471 { #| k = 0 #| } else if j < 0x5db3d7 { #| k = 1 #| } else { #| k = 0 #| n += 1 #| ix -= 0x00800000 #| } #| ax = ix.reinterpret_as_float() #| u = ax - bp[k] #| v = (1.0 : Float) / (ax + bp[k]) #| s = u * v #| s_h = s #| i_s = s_h.reinterpret_as_int() #| s_h = (i_s & 0xfffff000).reinterpret_as_float() #| i_s = (((ix.reinterpret_as_uint() >> 1) & 0xfffff000) | 0x20000000).reinterpret_as_int() #| t_h = (i_s.reinterpret_as_uint() + #| 0x00400000 + #| (k.reinterpret_as_uint() << 21)).reinterpret_as_float() #| t_l = ax - (t_h - bp[k]) #| s_l = v * (u - s_h * t_h - s_h * t_l) #| s2 = s * s #| r = s2 * s2 * (l1 + s2 * (l2 + s2 * (l3 + s2 * (l4 + s2 * (l5 + s2 * l6))))) #| r += s_l * (s_h + s) #| s2 = s_h * s_h #| t_h = (3.0 : Float) + s2 + r #| i_s = t_h.reinterpret_as_int() #| t_h = (i_s & 0xfffff000).reinterpret_as_float() #| t_l = r - (t_h - 3.0 - s2) #| u = s_h * t_h #| v = s_l * t_h + t_l * s #| p_h = u + v #| i_s = p_h.reinterpret_as_int() #| p_h = (i_s & 0xfffff000).reinterpret_as_float() #| p_l = v - (p_h - u) #| z_h = cp_h * p_h // cp_h+cp_l = 2/(3*log2) #| z_l = cp_l * p_h + p_l * cp + dp_l[k] #| t = n.to_float() #| t1 = z_h + z_l + dp_h[k] + t #| i_s = t1.reinterpret_as_int() #| t1 = (i_s & 0xfffff000).reinterpret_as_float() #| t2 = z_l - (t1 - t - dp_h[k] - z_h) #| } #| i_s = y.reinterpret_as_int() #| y1 = (i_s & 0xfffff000).reinterpret_as_float() #| p_l = (y - y1) * t1 + y * t2 #| p_h = y1 * t1 #| z = p_l + p_h #| j = z.reinterpret_as_int() #| if j > 0x43000000 { #| return sn * huge * huge // overflow #| } else if j == 0x43000000 { #| if p_l + ovt > z - p_h { #| return sn * huge * huge #| } #| } else if ( // overflow #| j & 0x7fffffff #| ) > #| 0x43160000 { #| return sn * tiny * tiny // underflow #| } else if j.reinterpret_as_uint() == 0xc3160000 && p_l <= z - p_h { #| return sn * tiny * tiny #| } // underflow #| i = j & 0x7fffffff #| k = (i >> 23) - 0x7f #| n = 0 #| if i > 0x3f000000 { #| n = j + (0x00800000 >> (k + 1)) #| k = ((n & 0x7fffffff) >> 23) - 0x7f // new k for n #| t = (n & (0x007fffff >> k).lnot()).reinterpret_as_float() #| n = ((n & 0x007fffff) | 0x00800000) >> (23 - k) #| if j < 0 { #| n = -n #| } #| p_h -= t #| } #| t = p_l + p_h #| i_s = t.reinterpret_as_int() #| t = (i_s & 0xffff8000).reinterpret_as_float() #| u = t * lg2_h #| v = (p_l - (t - p_h)) * lg2 + t * lg2_l #| z = u + v #| w = v - (z - u) #| t = z * z #| t1 = z - t * (p1 + t * (p2 + t * (p3 + t * (p4 + t * p5)))) #| r = z * t1 / (t1 - 2.0) - (w + z * w) #| z = (1.0 : Float) - (r - z) #| j = z.reinterpret_as_int() #| j += n << 23 #| if j >> 23 <= 0 { #| z = scalbnf(z, n) #| } else { #| z = j.reinterpret_as_float() #| } #| sn * z #|} ), "pow_double_js.mbt": ( #|pub fn pow(base : Double, exponent : Double) -> Double = "Math" "pow" ), "pow_double_nonjs.mbt": ( #|let pow_bp : FixedArray[Double] = [1.0, 1.5] #|let pow_dp_h : FixedArray[Double] = [0.0, 5.84962487220764160156e-01] #|let pow_dp_l : FixedArray[Double] = [0.0, 1.35003920212974897128e-08] #|const ZERO = 0.0 #|const ONE = 1.0 #|const TWO = 2.0 #|const POW_two53 = 9007199254740992.0 #|const POW_huge = 1.0e300 #|const POW_tiny = 1.0e-300 #|const POW_L1 = 5.99999999999994648725e-01 #|const POW_L2 = 4.28571428578550184252e-01 #|const POW_L3 = 3.33333329818377432918e-01 #|const POW_L4 = 2.72728123808534006489e-01 #|const POW_L5 = 2.30660745775561754067e-01 #|const POW_L6 = 2.06975017800338417784e-01 #|const POW_P1 = 1.66666666666666019037e-01 #|const POW_P2 = -2.77777777770155933842e-03 #|const POW_P3 = 6.61375632143793436117e-05 #|const POW_P4 = -1.65339022054652515390e-06 #|const POW_P5 = 4.13813679705723846039e-08 #|const POW_lg2 = 6.93147180559945286227e-01 #|const POW_lg2_h = 6.93147182464599609375e-01 #|const POW_lg2_l = -1.90465429995776804525e-09 #|const POW_ovt = 8.0085662595372944372e-0017 #|const POW_cp = 9.61796693925975554329e-01 #|const POW_cp_h = 9.61796700954437255859e-01 #|const POW_cp_l = -7.02846165095275826516e-09 #|const POW_ivln2 = 1.44269504088896338700e+00 #|const POW_ivln2_h = 1.44269502162933349609e+00 #|const POW_ivln2_l = 1.92596299112661746887e-08 #|pub fn pow(x : Double, y : Double) -> Double { #| fn set_low_word(d : Double, v : UInt) -> Double { #| let bits : UInt64 = d.reinterpret_as_uint64() #| let bits = bits & 0xFFFF_FFFF_0000_0000 #| let bits = bits | v.to_uint64() #| bits.reinterpret_as_double() #| } #| fn set_high_word(d : Double, v : UInt) -> Double { #| let bits : UInt64 = d.reinterpret_as_uint64() #| let bits = bits & 0x0000_0000_FFFF_FFFF #| let bits = bits | (v.to_uint64() << 32) #| bits.reinterpret_as_double() #| } #| fn get_high_word(x : Double) -> UInt { #| (x.reinterpret_as_uint64() >> 32).to_uint() #| } #| fn get_low_word(x : Double) -> UInt { #| x.reinterpret_as_uint64().to_uint() #| } #| let mut z : Double = 0.0 #| let mut ax : Double = 0.0 #| let mut z_h : Double = 0.0 #| let mut z_l : Double = 0.0 #| let mut p_h : Double = 0.0 #| let mut p_l : Double = 0.0 #| let mut y1 : Double = 0.0 #| let mut t1 : Double = 0.0 #| let mut t2 : Double = 0.0 #| let mut r : Double = 0.0 #| let mut s : Double = 0.0 #| let mut t : Double = 0.0 #| let mut u : Double = 0.0 #| let mut v : Double = 0.0 #| let mut w : Double = 0.0 #| let mut i : Int = 0 #| let mut j : Int = 0 #| let mut k : Int = 0 #| let mut yisint : Int = 0 #| let mut n : Int = 0 #| let hx : Int = (x.reinterpret_as_uint64() >> 32).to_int() #| let lx : UInt = (x.reinterpret_as_uint64() & 0xFFFFFFFF).to_uint() #| let hy : Int = (y.reinterpret_as_uint64() >> 32).to_int() #| let ly : UInt = (y.reinterpret_as_uint64() & 0xFFFFFFFF).to_uint() #| let mut ix : Int = hx & 0x7FFFFFFF #| let iy : Int = hy & 0x7FFFFFFF #| if (iy.reinterpret_as_uint() | ly) == 0 { #| return ONE #| } #| if ix > 0x7FF00000 || #| (ix == 0x7FF00000 && lx != 0) || #| iy > 0x7FF00000 || #| (iy == 0x7FF00000 && ly != 0) { #| return x + y #| } #| if hx < 0 { #| if iy >= 0x43400000 { #| yisint = 2 // even integer y #| } else if iy >= 0x3ff00000 { #| k = (iy >> 20) - 0x3ff // exponent #| if k > 20 { #| j = (ly >> (52 - k)).reinterpret_as_int() #| if j << (52 - k) == ly.reinterpret_as_int() { #| yisint = 2 - (j & 1) #| } #| } else if ly == 0 { #| j = iy >> (20 - k) #| if j << (20 - k) == iy { #| yisint = 2 - (j & 1) #| } #| } #| } #| } #| if ly == 0 { #| if iy == 0x7ff00000 { // y is +-inf #| if ((ix.reinterpret_as_uint() - 0x3ff00000) | lx) == 0 { #| return y - y // inf**+-1 is NaN #| } else if ix >= 0x3ff00000 { // (|x|>1)**+-inf = inf,0 #| return if hy >= 0 { y } else { ZERO } #| } else { // (|x|<1)**-,+inf = inf,0 #| return if hy < 0 { -y } else { ZERO } #| } #| } #| if iy == 0x3ff00000 { // y is +-1 #| if hy < 0 { #| return ONE / x #| } else { #| return x #| } #| } #| if hy == 0x40000000 { // y is 2 #| return x * x #| } #| if hy == 0x3fe00000 { // y is 0.5 #| if hx >= 0 { // x >= +0 #| return x.sqrt() #| } #| } #| } #| ax = x.abs() #| if lx == 0 { #| if ix == 0x7ff00000 || ix == 0 || ix == 0x3ff00000 { #| z = ax // x is +-0,+-inf,+-1 */ #| if hy < 0 { #| z = ONE / z // z = (1/|x|) #| } #| if hx < 0 { #| if ((ix - 0x3ff00000) | yisint) == 0 { #| z = @double.not_a_number #| } else if yisint == 1 { #| z = -z // (x<0)**odd = -(|x|**odd) #| } #| } #| return z #| } #| } #| n = (hx >> 31) + 1 #| if (n | yisint) == 0 { #| return @double.not_a_number #| } #| s = ONE // s (sign of result -ve**odd) = -1 else = 1 #| if (n | (yisint - 1)) == 0 { #| s = -ONE // (-ve)**(odd int) #| } #| if iy > 0x41e00000 { // if |y| > 2**31 */ #| if iy > 0x43f00000 { // if |y| > 2**64, must o/uflow */ #| if ix <= 0x3fefffff { #| return if hy < 0 { POW_huge * POW_huge } else { POW_tiny * POW_tiny } #| } #| if ix >= 0x3ff00000 { #| return if hy > 0 { POW_huge * POW_huge } else { POW_tiny * POW_tiny } #| } #| } #| if ix < 0x3fefffff { #| return if hy < 0 { #| s * POW_huge * POW_huge #| } else { #| s * POW_tiny * POW_tiny #| } #| } #| if ix > 0x3ff00000 { #| return if hy > 0 { #| s * POW_huge * POW_huge #| } else { #| s * POW_tiny * POW_tiny #| } #| } #| t = ax - ONE // t has 20 trailing zeros */ #| w = t * t * (0.5 - t * (0.3333333333333333333333 - t * 0.25)) #| u = POW_ivln2_h * t // POW_ivln2_h has 21 sig. bits */ #| v = t * POW_ivln2_l - w * POW_ivln2 #| t1 = u + v #| t1 = set_low_word(t1, 0) #| t2 = v - (t1 - u) #| } else { #| n = 0 #| if ix < 0x00100000 { #| ax *= POW_two53 #| n -= 53 #| ix = get_high_word(ax).reinterpret_as_int() #| } #| n += (ix >> 20) - 0x3ff #| j = ix & 0x000fffff #| ix = j | 0x3ff00000 // normalize ix #| if j <= 0x3988E { #| k = 0 // |x|> 1) | 0x20000000) + #| 0x00080000 + #| (k.reinterpret_as_uint() << 18), #| ) #| let mut t_l : Double = ax - (t_h - pow_bp[k]) #| let s_l : Double = v * (u - s_h * t_h - s_h * t_l) #| let mut s2 : Double = ss * ss #| r = s2 * #| s2 * #| ( #| POW_L1 + #| s2 * #| (POW_L2 + s2 * (POW_L3 + s2 * (POW_L4 + s2 * (POW_L5 + s2 * POW_L6)))) #| ) #| r += s_l * (s_h + ss) #| s2 = s_h * s_h #| t_h = 3.0 + s2 + r #| t_h = set_low_word(t_h, 0) #| t_l = r - (t_h - 3.0 - s2) #| u = s_h * t_h #| v = s_l * t_h + t_l * ss #| p_h = u + v #| p_h = set_low_word(p_h, 0) #| p_l = v - (p_h - u) #| z_h = POW_cp_h * p_h // cp_h+cp_l = 2/(3*log2) #| z_l = POW_cp_l * p_h + p_l * POW_cp + pow_dp_l[k] #| t = n.to_double() #| t1 = z_h + z_l + pow_dp_h[k] + t #| t1 = set_low_word(t1, 0) #| t2 = z_l - (t1 - t - pow_dp_h[k] - z_h) #| } #| y1 = y #| y1 = set_low_word(y1, 0) #| p_l = (y - y1) * t1 + y * t2 #| p_h = y1 * t1 #| z = p_l + p_h #| j = get_high_word(z).reinterpret_as_int() #| i = get_low_word(z).reinterpret_as_int() #| if j >= 0x40900000 { // z >= 1024 #| if ((j - 0x40900000) | i) != 0 { // if z > 1024 #| return s * POW_huge * POW_huge // overflow #| } else if p_l + POW_ovt > z - p_h { #| return s * POW_huge * POW_huge // overflow #| } #| } else if (j & 0x7fffffff) >= 0x4090cc00 { // z <= -1075 #| if ((j - 0xc090cc00) | i) != 0 { // z < -1075 #| return s * POW_tiny * POW_tiny // underflow #| } else if p_l <= z - p_h { #| return s * POW_tiny * POW_tiny // underflow #| } #| } #| i = j & 0x7fffffff #| k = (i >> 20) - 0x3ff #| n = 0 #| if i > 0x3fe00000 { // if |z| > 0.5, set n = [z+0.5] #| n = j + (0x00100000 >> (k + 1)) #| k = ((n & 0x7fffffff) >> 20) - 0x3ff // new k for n #| t = ZERO #| t = set_high_word(t, (n & (0x000fffff >> k).lnot()).reinterpret_as_uint()) #| n = ((n & 0x000fffff) | 0x00100000) >> (20 - k) #| if j < 0 { #| n = -n #| } #| p_h -= t #| } #| t = p_l + p_h #| t = set_low_word(t, 0) #| u = t * POW_lg2_h #| v = (p_l - (t - p_h)) * POW_lg2 + t * POW_lg2_l #| z = u + v #| w = v - (z - u) #| t = z * z #| t1 = z - #| t * (POW_P1 + t * (POW_P2 + t * (POW_P3 + t * (POW_P4 + t * POW_P5)))) #| r = z * t1 / (t1 - TWO - (w + z * w)) #| z = ONE - (r - z) #| j = get_high_word(z).reinterpret_as_int() #| j += (n.reinterpret_as_uint() << 20).reinterpret_as_int() #| if j >> 20 <= 0 { #| z = scalbn(z, n) #| } else { // subnormal output */ #| let tmp = get_high_word(z).reinterpret_as_int() #| z = set_high_word( #| z, #| (tmp + (n.reinterpret_as_uint() << 20).reinterpret_as_int()).reinterpret_as_uint(), #| ) #| } #| return s * z #|} ), "prime.mbt": ( #|const DEFAULT_PRIME_TEST_ITERS = 64 #|let small_primes : Array[@bigint.BigInt] = [ #| 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, #| 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, #| 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, #| 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, #| 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, #| 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, #| 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, #| 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, #| 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, #| 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, #| 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, #| 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, #| 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, #| 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, #| 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, #| 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, #| 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, #| 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, #| 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, #| 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, #| 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, #| 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, #| 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, #| 2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, #| 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, #| 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, #| 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, #| 2789, 2791, 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, #| 2897, 2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, #| 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, #| 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, #| 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, #| 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, #| 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, #| 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, #| 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, #| 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, #| 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, #| 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, #| 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, #| 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, #| 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, #| 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, #| 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, #| 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, #| 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, #| 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, #| 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, #| 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, #| 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, #| 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, #| 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, #| 5741, 5743, 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, #| 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, #| 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, #| 6113, 6121, 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, #| 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, #| 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, #| 6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, #| 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, #| 6719, 6733, 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, #| 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, #| 6967, 6971, 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, #| 7079, 7103, 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, #| 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, #| 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, #| 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, #| 7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, #| 7717, 7723, 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, #| 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, #| 7993, 8009, 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, #| 8117, 8123, 8147, 8161, 8167, 8171, 8179, 8191, 8209, 8219, 8221, 8231, 8233, 8237, #| 8243, 8263, 8269, 8273, 8287, 8291, 8293, 8297, 8311, 8317, 8329, 8353, 8363, 8369, #| 8377, 8387, 8389, 8419, 8423, 8429, 8431, 8443, 8447, 8461, 8467, 8501, 8513, 8521, #| 8527, 8537, 8539, 8543, 8563, 8573, 8581, 8597, 8599, 8609, 8623, 8627, 8629, 8641, #| 8647, 8663, 8669, 8677, 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741, #| 8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831, 8837, 8839, 8849, 8861, #| 8863, 8867, 8887, 8893, 8923, 8929, 8933, 8941, 8951, 8963, 8969, 8971, 8999, 9001, #| 9007, 9011, 9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109, 9127, 9133, #| 9137, 9151, 9157, 9161, 9173, 9181, 9187, 9199, 9203, 9209, 9221, 9227, 9239, 9241, #| 9257, 9277, 9281, 9283, 9293, 9311, 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377, #| 9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439, 9461, 9463, 9467, 9473, #| 9479, 9491, 9497, 9511, 9521, 9533, 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623, #| 9629, 9631, 9643, 9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733, 9739, 9743, #| 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811, 9817, 9829, 9833, 9839, 9851, 9857, #| 9859, 9871, 9883, 9887, 9901, 9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973, 10007, #| 10009, 10037, 10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099, 10103, 10111, #| 10133, 10139, 10141, 10151, 10159, 10163, 10169, 10177, 10181, 10193, 10211, 10223, #| 10243, 10247, 10253, 10259, 10267, 10271, 10273, 10289, 10301, 10303, 10313, 10321, #| 10331, 10333, 10337, 10343, 10357, 10369, 10391, 10399, 10427, 10429, 10433, 10453, #| 10457, 10459, 10463, 10477, 10487, 10499, 10501, 10513, 10529, 10531, 10559, 10567, #| 10589, 10597, 10601, 10607, 10613, 10627, 10631, 10639, 10651, 10657, 10663, 10667, #| 10687, 10691, 10709, 10711, 10723, 10729, 10733, 10739, 10753, 10771, 10781, 10789, #| 10799, 10831, 10837, 10847, 10853, 10859, 10861, 10867, 10883, 10889, 10891, 10903, #| 10909, 10937, 10939, 10949, 10957, 10973, 10979, 10987, 10993, 11003, 11027, 11047, #| 11057, 11059, 11069, 11071, 11083, 11087, 11093, 11113, 11117, 11119, 11131, 11149, #| 11159, 11161, 11171, 11173, 11177, 11197, 11213, 11239, 11243, 11251, 11257, 11261, #| 11273, 11279, 11287, 11299, 11311, 11317, 11321, 11329, 11351, 11353, 11369, 11383, #| 11393, 11399, 11411, 11423, 11437, 11443, 11447, 11467, 11471, 11483, 11489, 11491, #| 11497, 11503, 11519, 11527, 11549, 11551, 11579, 11587, 11593, 11597, 11617, 11621, #| 11633, 11657, 11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731, 11743, 11777, #| 11779, 11783, 11789, 11801, 11807, 11813, 11821, 11827, 11831, 11833, 11839, 11863, #| 11867, 11887, 11897, 11903, 11909, 11923, 11927, 11933, 11939, 11941, 11953, 11959, #| 11969, 11971, 11981, 11987, 12007, 12011, 12037, 12041, 12043, 12049, 12071, 12073, #| 12097, 12101, 12107, 12109, 12113, 12119, 12143, 12149, 12157, 12161, 12163, 12197, #| 12203, 12211, 12227, 12239, 12241, 12251, 12253, 12263, 12269, 12277, 12281, 12289, #| 12301, 12323, 12329, 12343, 12347, 12373, 12377, 12379, 12391, 12401, 12409, 12413, #| 12421, 12433, 12437, 12451, 12457, 12473, 12479, 12487, 12491, 12497, 12503, 12511, #| 12517, 12527, 12539, 12541, 12547, 12553, 12569, 12577, 12583, 12589, 12601, 12611, #| 12613, 12619, 12637, 12641, 12647, 12653, 12659, 12671, 12689, 12697, 12703, 12713, #| 12721, 12739, 12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821, 12823, 12829, #| 12841, 12853, 12889, 12893, 12899, 12907, 12911, 12917, 12919, 12923, 12941, 12953, #| 12959, 12967, 12973, 12979, 12983, 13001, 13003, 13007, 13009, 13033, 13037, 13043, #| 13049, 13063, 13093, 13099, 13103, 13109, 13121, 13127, 13147, 13151, 13159, 13163, #| 13171, 13177, 13183, 13187, 13217, 13219, 13229, 13241, 13249, 13259, 13267, 13291, #| 13297, 13309, 13313, 13327, 13331, 13337, 13339, 13367, 13381, 13397, 13399, 13411, #| 13417, 13421, 13441, 13451, 13457, 13463, 13469, 13477, 13487, 13499, 13513, 13523, #| 13537, 13553, 13567, 13577, 13591, 13597, 13613, 13619, 13627, 13633, 13649, 13669, #| 13679, 13681, 13687, 13691, 13693, 13697, 13709, 13711, 13721, 13723, 13729, 13751, #| 13757, 13759, 13763, 13781, 13789, 13799, 13807, 13829, 13831, 13841, 13859, 13873, #| 13877, 13879, 13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933, 13963, 13967, #| 13997, 13999, 14009, 14011, 14029, 14033, 14051, 14057, 14071, 14081, 14083, 14087, #| 14107, 14143, 14149, 14153, 14159, 14173, 14177, 14197, 14207, 14221, 14243, 14249, #| 14251, 14281, 14293, 14303, 14321, 14323, 14327, 14341, 14347, 14369, 14387, 14389, #| 14401, 14407, 14411, 14419, 14423, 14431, 14437, 14447, 14449, 14461, 14479, 14489, #| 14503, 14519, 14533, 14537, 14543, 14549, 14551, 14557, 14561, 14563, 14591, 14593, #| 14621, 14627, 14629, 14633, 14639, 14653, 14657, 14669, 14683, 14699, 14713, 14717, #| 14723, 14731, 14737, 14741, 14747, 14753, 14759, 14767, 14771, 14779, 14783, 14797, #| 14813, 14821, 14827, 14831, 14843, 14851, 14867, 14869, 14879, 14887, 14891, 14897, #| 14923, 14929, 14939, 14947, 14951, 14957, 14969, 14983, 15013, 15017, 15031, 15053, #| 15061, 15073, 15077, 15083, 15091, 15101, 15107, 15121, 15131, 15137, 15139, 15149, #| 15161, 15173, 15187, 15193, 15199, 15217, 15227, 15233, 15241, 15259, 15263, 15269, #| 15271, 15277, 15287, 15289, 15299, 15307, 15313, 15319, 15329, 15331, 15349, 15359, #| 15361, 15373, 15377, 15383, 15391, 15401, 15413, 15427, 15439, 15443, 15451, 15461, #| 15467, 15473, 15493, 15497, 15511, 15527, 15541, 15551, 15559, 15569, 15581, 15583, #| 15601, 15607, 15619, 15629, 15641, 15643, 15647, 15649, 15661, 15667, 15671, 15679, #| 15683, 15727, 15731, 15733, 15737, 15739, 15749, 15761, 15767, 15773, 15787, 15791, #| 15797, 15803, 15809, 15817, 15823, 15859, 15877, 15881, 15887, 15889, 15901, 15907, #| 15913, 15919, 15923, 15937, 15959, 15971, 15973, 15991, 16001, 16007, 16033, 16057, #| 16061, 16063, 16067, 16069, 16073, 16087, 16091, 16097, 16103, 16111, 16127, 16139, #| 16141, 16183, 16187, 16189, 16193, 16217, 16223, 16229, 16231, 16249, 16253, 16267, #| 16273, 16301, 16319, 16333, 16339, 16349, 16361, 16363, 16369, 16381, 16411, 16417, #| 16421, 16427, 16433, 16447, 16451, 16453, 16477, 16481, 16487, 16493, 16519, 16529, #| 16547, 16553, 16561, 16567, 16573, 16603, 16607, 16619, 16631, 16633, 16649, 16651, #| 16657, 16661, 16673, 16691, 16693, 16699, 16703, 16729, 16741, 16747, 16759, 16763, #| 16787, 16811, 16823, 16829, 16831, 16843, 16871, 16879, 16883, 16889, 16901, 16903, #| 16921, 16927, 16931, 16937, 16943, 16963, 16979, 16981, 16987, 16993, 17011, 17021, #| 17027, 17029, 17033, 17041, 17047, 17053, 17077, 17093, 17099, 17107, 17117, 17123, #| 17137, 17159, 17167, 17183, 17189, 17191, 17203, 17207, 17209, 17231, 17239, 17257, #| 17291, 17293, 17299, 17317, 17321, 17327, 17333, 17341, 17351, 17359, 17377, 17383, #| 17387, 17389, 17393, 17401, 17417, 17419, 17431, 17443, 17449, 17467, 17471, 17477, #| 17483, 17489, 17491, 17497, 17509, 17519, 17539, 17551, 17569, 17573, 17579, 17581, #| 17597, 17599, 17609, 17623, 17627, 17657, 17659, 17669, 17681, 17683, 17707, 17713, #| 17729, 17737, 17747, 17749, 17761, 17783, 17789, 17791, 17807, 17827, 17837, 17839, #| 17851, 17863, #|] #|pub fn is_probable_prime( #| number : @bigint.BigInt, #| rand : @random.Rand, #| iters? : Int = DEFAULT_PRIME_TEST_ITERS, #|) -> Bool { #| if iters <= 0 { #| abort("non-positive iters for probably prime") #| } #| if number <= 1N { #| return false #| } #| if number <= 3N { #| return true #| } #| if number % 2N == 0 { #| return false #| } #| trial_divisions(number) && miller_rabin_test(number, iters, rand) #|} #|pub fn probable_prime(bits : Int, rand : @random.Rand) -> @bigint.BigInt { #| for { #| let b = rand.bigint(bits) #| if is_probable_prime(b, rand) { #| break b #| } #| } #|} #|fn trial_divisions(n : @bigint.BigInt) -> Bool { #| let td = match n.bit_length() { #| _..=512 => 64 #| 512..=1024 => 128 #| 1024..=2048 => 384 #| 2048..=4096 => 1024 #| _ => 2048 #| } #| for i in 1.. Bool { #| if w <= 3N { #| abort("candidate of miller rabin test must larger than 3") #| } #| let w1 = w - 1N #| let w3 = w - 3N #| let a = w1.ctz() #| let m = w1 >> a #| let w3_len = w3.bit_length() #| next~: for i in 0.. Double { #| let mut n = exp #| let mut y : Double = x #| if n > 1023 { #| y *= 0x1.0p1023 #| n -= 1023 #| if n > 1023 { #| y *= 0x1.0p1023 #| n -= 1023 #| if n > 1023 { #| n = 1023 #| } #| } #| } else if n < -1022 { #| y *= 0x1.0p-1022 * 0x1.0p53 #| n += 1022 - 53 #| if n < -1022 { #| y *= 0x1.0p-1022 * 0x1.0p53 #| n += 1022 - 53 #| if n < -1022 { #| n = -1022 #| } #| } #| } #| let ui = (0x3ff + n).to_uint64() << 52 #| return y * ui.reinterpret_as_double() #|} #|pub fn scalbnf(y : Float, exp : Int) -> Float { #| let mut y = y #| let mut n = exp #| if n > 127 { #| y *= (0x1.0p127 : Float) #| n -= 127 #| if n > 127 { #| y *= (0x1.0p127 : Float) #| n -= 127 #| if n > 127 { #| n = 127 #| } #| } #| } else if n < -126 { #| y *= (0x1.0p-126 : Float) * 0x1.0p24 #| n += 126 - 24 #| if n < -126 { #| y *= (0x1.0p-126 : Float) * 0x1.0p24 #| n += 126 - 24 #| if n < -126 { #| n = -126 #| } #| } #| } #| let u = (0x7f + n) << 23 #| return y * u.reinterpret_as_float() #|} #|test "scalbn" { #| inspect(scalbn(1.5, 2), content="6") #| inspect(scalbn(2.0, -1), content="1") #| inspect(scalbn(3.0, 0), content="3") #| inspect(scalbn(1.0, 1024), content="Infinity") #| inspect(scalbn(1.0, -1023), content="1.1125369292536007e-308") #| inspect(scalbn(1.0, 2047), content="Infinity") #| inspect(scalbn(1.0, -1992), content="0") #| inspect(scalbn(1.0, 3070), content="Infinity") #| inspect(scalbn(1.0, -2961), content="0") #| inspect(scalbn(@double.infinity, 10), content="Infinity") #| inspect(scalbn(@double.not_a_number, 10), content="NaN") #| inspect(scalbn(0.0, 10), content="0") #|} ), "trig.mbt": ( #|pub const PI = 0x3.243F6A8885A308CA8A54 #|const SIN_SWITCHOVER : Float = 201.15625 #|const COS_SWITCHOVER : Float = 142.90625 #|fn mulh(a : UInt, b : UInt) -> UInt { #| let a = a.to_uint64() #| let b = b.to_uint64() #| let res = a * b #| (res >> 32).to_uint() #|} #|fn mul(a : UInt, b : UInt) -> (UInt, UInt) { #| let a = a.to_uint64() #| let b = b.to_uint64() #| let res = a * b #| ((res >> 32).to_uint(), res.to_uint()) #|} #|fn trig_reduce(x : Float, switch_over : Float) -> (Float, Int) { #| if x.abs() <= switch_over { #| let mut j : Float = 0.0 #| let mut r : Float = 0.0 #| j = x * (0x3f22f983).reinterpret_as_float() + #| (0x4b40_0000).reinterpret_as_float() #| j = (j.reinterpret_as_int() - 0x4b40_0000).to_float() #| r = x - j * (0x3fc90f80).reinterpret_as_float() #| r = r - j * (0x37354440).reinterpret_as_float() #| r = r - j * (0x2c34611a).reinterpret_as_float() #| return (r, j.to_int()) #| } #| let xispos = x > 0.0 #| let mut exp : Int = ((x.reinterpret_as_int() >> 23) & 0xff) - 126 #| let ix = ((x.reinterpret_as_uint() & 0x007fffff) << 8) | 0x80000000 #| let ind = exp >> 5 #| exp = exp & 0x1f #| let two_over_pi : Array[UInt] = [ #| 0x00000000, 0x28be60db, 0x9391054a, 0x7f09d5f4, 0x7d4d3770, 0x36d8a566, 0x4f10e410, #| 0000000000, #| ] #| let mut hi = two_over_pi[ind] #| let mut mi = two_over_pi[ind + 1] #| let mut lo = two_over_pi[ind + 2] #| let tp = two_over_pi[ind + 3] #| if exp > 0 { #| hi = (hi << exp) | (mi >> (32 - exp)) #| mi = (mi << exp) | (lo >> (32 - exp)) #| lo = (lo << exp) | (tp >> (32 - exp)) #| } #| let phi = 0U #| let (h, l) = mul(ix, lo) #| let plo = phi + l #| let phi = h + (if plo < l { 1 } else { 0 }) #| let (h, l) = mul(ix, mi) #| let mut plo = phi + l #| let phi = h + (if plo < l { 1 } else { 0 }) #| let l = ix * hi #| let mut phi = phi + l #| let mut q : Int = (phi >> 30).reinterpret_as_int() #| phi = phi & 0x3fffffff #| if (phi & 0x2000_0000) != 0 { #| phi = phi - 0x4000_0000 #| q = q + 1 #| } #| let s : UInt = phi & 0x8000_0000 #| if phi >= 0x8000_0000 { #| phi = phi.lnot() #| plo = 0U - plo #| phi += if plo == 0 { 1 } else { 0 } #| } #| exp = 0 #| while phi < 0x8000_0000 { #| phi = (phi << 1) | (plo >> 31) #| plo = plo << 1 #| exp = exp - 1 #| } #| phi = mulh(phi, 0xc90f_daa2) #| if phi < 0x8000_0000 { #| phi = phi << 1 #| exp = exp - 1 #| } #| let mut r = s + #| ((exp + 128) << 23).reinterpret_as_uint() + #| (phi >> 8) + #| (if (phi & 0xff) > 0x7e { 1 } else { 0 }) #| if !xispos { #| r = r ^ 0x8000_0000 #| q = -q #| } #| let r = r.reinterpret_as_float() #| return (r, q) #|} #|fn sinf_poly(x : Float) -> Float { #| let s = x * x #| let mut r = (0x3640_5000).reinterpret_as_float() #| r = r * s - (0x3950_3486).reinterpret_as_float() #| r = r * s + (0x3c08_88c1).reinterpret_as_float() #| r = r * s - (0x3e2a_aaab).reinterpret_as_float() #| let t = x * s #| r = r * t + x #| r #|} #|fn cosf_poly(x : Float) -> Float { #| let s = x * x #| let mut r = (0x37cd_4000).reinterpret_as_float() #| r = r * s - (0x3ab6_077d).reinterpret_as_float() #| r = r * s + (0x3d2a_aaa8).reinterpret_as_float() #| r = r * s - (0x3f00_0000).reinterpret_as_float() #| r = r * s + (0x3f80_0000).reinterpret_as_float() #| r #|} #|fn sin_cos_core(x : Float, q : Int) -> Float { #| let mut r = if (q & 1) != 0 { cosf_poly(x) } else { sinf_poly(x) } #| if (q & 2) != 0 { #| r = -r #| } #| r #|} #|fn tanf_poly(x : Float, odd : Bool) -> Float { #| let x = x.to_double() #| let coef : FixedArray[Double] = [ #| 0.333331395030791399758, // 0x15554d3418c99f.0p-54 */ #| 0.133392002712976742718, // 0x1112fd38999f72.0p-55 */ #| 0.0533812378445670393523, // 0x1b54c91d865afe.0p-57 */ #| 0.0245283181166547278873, // 0x191df3908c33ce.0p-58 */ #| 0.00297435743359967304927, // 0x185dadfcecf44e.0p-61 */ #| 0.00946564784943673166728, // 0x1362b9bf971bcd.0p-59 */ #| ] #| let z = x * x #| let mut r = coef[4] + z * coef[5] #| let t = coef[2] + z * coef[3] #| let w = z * z #| let s = z * x #| let u = coef[0] + z * coef[1] #| r = x + s * u + s * w * (t + w * r) #| (if odd { -1.0 / r } else { r }).to_float() #|} #|pub fn sinf(x : Float) -> Float { #| if x.is_nan() || x.is_inf() { #| return @float.not_a_number #| } #| if x == 0.0 { #| return x #| } #| let (x, q) = trig_reduce(x, SIN_SWITCHOVER) #| sin_cos_core(x, q) #|} #|pub fn cosf(x : Float) -> Float { #| if x.is_nan() || x.is_inf() { #| return @float.not_a_number #| } #| if x == 0.0 { #| return 1.0 #| } #| let (x, q) = trig_reduce(x, COS_SWITCHOVER) #| sin_cos_core(x, q + 1) #|} #|pub fn tanf(x : Float) -> Float { #| if x.is_nan() || x.is_inf() { #| return @float.not_a_number #| } #| if x == 0.0 { #| return x #| } #| let (x, q) = trig_reduce(x, COS_SWITCHOVER) #| tanf_poly(x, (q & 1) != 0) #|} #|pub fn asinf(x : Float) -> Float { #| let x1p120 = 0x3870000000000000UL.reinterpret_as_double() #| let pio2 : Double = 1.570796326794896558e+00 #| let ps0 : Float = 1.6666586697e-01 #| let ps1 : Float = -4.2743422091e-02 #| let ps2 : Float = -8.6563630030e-03 #| let qs2 : Float = -7.0662963390e-01 #| fn r(z : Float) -> Float { #| let p = z * (ps0 + z * (ps1 + z * ps2)) #| let q = z * qs2 + 1.0 #| p / q #| } #| let hx = x.reinterpret_as_uint() #| let ix = hx & 0x7fffffff #| if ix >= 0x3f800000 { #| if ix == 0x3f800000 { #| return (x.to_double() * pio2 + x1p120).to_float() #| } #| return @float.not_a_number // asin(|x|>1) is NaN #| } #| if ix < 0x3f000000 { #| if ix is (0x00800000..=0x39800000) { #| return x #| } #| return x + x * r(x * x) #| } #| let z = ((1.0 : Float) - x.abs()) * 0.5 #| let s = z.to_double().sqrt() #| let x = (pio2 - 2.0 * (s + s * r(z).to_double())).to_float() #| if hx >> 31 != 0 { #| -x #| } else { #| x #| } #|} #|pub fn acosf(x : Float) -> Float { #| let pio2_hi : Float = 1.5707962513 #| let pio2_lo : Float = 7.5497894159e-08 #| let ps0 : Float = 1.6666586697e-01 #| let ps1 : Float = -4.2743422091e-02 #| let ps2 : Float = -8.6563630030e-03 #| let qs1 : Float = -7.0662963390e-01 #| let one : Float = 1.0 #| let two : Float = 2.0 #| fn r(z : Float) -> Float { #| let p = z * (ps0 + z * (ps1 + z * ps2)) #| let q = z * qs1 + 1.0 #| p / q #| } #| let hx = x.reinterpret_as_int() #| let ix = hx & 0x7fffffff #| if ix >= 0x3f800000 { #| if ix == 0x3f800000 { #| if hx >> 31 != 0 { #| return two * pio2_hi + 0x1.0p-120 #| } #| return 0.0 #| } #| return @float.not_a_number #| } #| if ix < 0x3f000000 { #| if ix <= 0x32800000 { #| return pio2_hi + 0x1.0p-120 #| } #| return pio2_hi - (x - (pio2_lo - x * r(x * x))) #| } #| if hx >> 31 != 0 { #| let z = (x + 1.0) * 0.5 #| let s = z.sqrt() #| let w = r(z) * s - pio2_lo #| return two * (pio2_hi - (s + w)) #| } #| let z = (one - x) * 0.5 #| let s = z.sqrt() #| let df = s #| let c = (z - df * df) / (s + df) #| let w = r(z) * s + c #| two * (df + w) #|} #|pub fn atanf(x : Float) -> Float { #| let atanhi : Array[Float] = [ #| 4.6364760399e-01, 7.8539812565e-01, 9.8279368877e-01, 1.5707962513e+00, #| ] #| let atanlo : Array[Float] = [ #| 5.0121582440e-09, 3.7748947079e-08, 3.4473217170e-08, 7.5497894159e-08, #| ] #| let a_t : Array[Float] = [ #| 3.3333328366e-01, -1.9999158382e-01, 1.4253635705e-01, -1.0648017377e-01, 6.1687607318e-02, #| ] #| let ix = x.reinterpret_as_int() #| let sign = ix >> 31 #| let ix = ix & 0x7fffffff #| let mut id = 0 #| let mut x = x #| let one : Float = 1.0 #| let two : Float = 2.0 #| if ix >= 0x4c800000 { #| if x.is_nan() { #| return x #| } #| let z = atanhi[3] + 0x1.0p-120 #| let z = if sign != 0 { -z } else { z } #| return z #| } #| if ix < 0x3ee00000 { #| if ix < 0x39800000 { #| return x #| } #| id = -1 #| } else { #| x = x.abs() #| if ix < 0x3f980000 { #| if ix < 0x3f300000 { #| id = 0 #| x = (two * x - one) / (two + x) #| } else { #| id = 1 #| x = (x - one) / (x + one) #| } #| } else if ix < 0x401c0000 { #| id = 2 #| x = (x - 1.5) / (one + x * 1.5) #| } else { #| id = 3 #| x = -one / x #| } #| } #| let z = x * x #| let w = z * z #| let s1 = z * (a_t[0] + w * (a_t[2] + w * a_t[4])) #| let s2 = w * (a_t[1] + w * a_t[3]) #| if id < 0 { #| return x - x * (s1 + s2) #| } #| let z = atanhi[id] - (x * (s1 + s2) - atanlo[id] - x) #| if sign != 0 { #| -z #| } else { #| z #| } #|} #|pub fn atan2f(y : Float, x : Float) -> Float { #| if x.is_nan() || y.is_nan() { #| return @float.not_a_number #| } #| let pi : Float = 3.1415927410e+00 #| let pi_lo : Float = -8.7422776573e-08 #| let zero : Float = 0.0 #| let ix = x.reinterpret_as_uint() #| let iy = y.reinterpret_as_uint() #| if ix == 0x3f800000 { #| return atanf(y) #| } #| let m = ((iy >> 31) & 1) | ((ix >> 30) & 2) #| let ix = ix & 0x7fffffff #| let iy = iy & 0x7fffffff #| if iy == 0 { #| match m { #| 0 | 1 => return y #| 2 => return pi #| _ => return -pi #| } #| } #| if ix == 0 { #| let res = if (m & 1) != 0 { -pi / 2 } else { pi / 2 } #| return res #| } #| if ix == 0x7f800000 { #| if iy == 0x7f800000 { #| match m { #| 0 => return pi / 4 #| 1 => return -pi / 4 #| 2 => return pi * 3.0 / 4 #| _ => return -pi * 3.0 / 4 #| } #| } else { #| match m { #| 0 => return 0.0 #| 1 => return -0.0 #| 2 => return pi #| _ => return -pi #| } #| } #| } #| if ix + (26U << 23) < iy || iy == 0x7f800000 { #| let res = if (m & 1) != 0 { -pi / 2 } else { pi / 2 } #| return res #| } #| let z = if (m & 2) != 0 && iy + (26U << 23) < ix { #| zero #| } else { #| atanf(y / x) #| } #| match m { #| 0 => z #| 1 => -z #| 2 => pi - (z - pi_lo) #| _ => z - pi_lo - pi #| } #|} ), "trig_double_js.mbt": ( #|pub fn sin(x : Double) -> Double = "Math" "sin" #|pub fn cos(x : Double) -> Double = "Math" "cos" #|pub fn tan(x : Double) -> Double = "Math" "tan" #|pub fn asin(x : Double) -> Double = "Math" "asin" #|pub fn acos(x : Double) -> Double = "Math" "acos" #|pub fn atan(x : Double) -> Double = "Math" "atan" #|pub fn atan2(y : Double, x : Double) -> Double = "Math" "atan2" ), "trig_double_nonjs.mbt": ( #|pub fn sin(x : Double) -> Double { #| if x.is_inf() || x.is_nan() { #| return @double.not_a_number #| } #| let y = [0.0, 0.0] #| let z = 0.0 #| if x.abs() <= PI_OVER_4 { #| return __kernel_sin(x, z, 0) #| } else { #| let n = rem_pio2(x, y) #| match n & 3 { #| 0 => __kernel_sin(y[0], y[1], 1) #| 1 => __kernel_cos(y[0], y[1]) #| 2 => -__kernel_sin(y[0], y[1], 1) #| _ => -__kernel_cos(y[0], y[1]) #| } #| } #|} #|pub fn cos(x : Double) -> Double { #| if x.is_inf() || x.is_nan() { #| return @double.not_a_number #| } #| let y = [0.0, 0.0] #| let z = 0.0 #| if x.abs() <= PI_OVER_4 { #| return __kernel_cos(x, z) #| } else { #| let n = rem_pio2(x, y) #| match n & 3 { #| 0 => __kernel_cos(y[0], y[1]) #| 1 => -__kernel_sin(y[0], y[1], 1) #| 2 => -__kernel_cos(y[0], y[1]) #| _ => __kernel_sin(y[0], y[1], 1) #| } #| } #|} #|pub fn tan(x : Double) -> Double { #| if x.is_inf() || x.is_nan() { #| return @double.not_a_number #| } #| let y = Array::make(2, 0.0) #| let z = 0.0 #| if x.abs() <= PI_OVER_4 { #| __kernal_tan(x, z, 1) #| } else { #| let n = rem_pio2(x, y) #| __kernal_tan(y[0], y[1], 1 - ((n & 1) << 1)) #| } #|} #|pub fn asin(x : Double) -> Double { #| let huge = 1.0e+300 #| let pio4_hi = 7.85398163397448278999e-01 #| let pio2_hi = 1.57079632679489655800 #| let pio2_lo = 6.12323399573676603587e-17 #| let ps0 = 1.66666666666666657415e-01 #| let ps1 = -3.25565818622400915405e-01 #| let ps2 = 2.01212532134862925881e-01 #| let ps3 = -4.00555345006794114027e-02 #| let ps4 = 7.91534994289814532176e-04 #| let ps5 = 3.47933107596021167570e-05 #| let qs1 = -2.40339491173441421878e+00 #| let qs2 = 2.02094576023350569471e+00 #| let qs3 = -6.88283971605453293030e-01 #| let qs4 = 7.70381505559019352791e-02 #| let ix = get_high_word(x).reinterpret_as_int() & 0x7fffffff #| let absx = x.abs() #| if absx >= 1.0 { #| if absx == 1.0 { #| return x * pio2_hi + x * pio2_lo #| } else { #| return @double.not_a_number #| } #| } else if absx < 0.5 { #| if ix < 0x3e400000 { #| if huge + x > 1.0 { #| return x #| } #| } else { #| let t = x * x #| let p = t * #| (ps0 + t * (ps1 + t * (ps2 + t * (ps3 + t * (ps4 + t * ps5))))) #| let q = 1.0 + t * (qs1 + t * (qs2 + t * (qs3 + t * qs4))) #| let w = p / q #| return x + x * w #| } #| } #| let w = 1.0 - absx #| let t = w * 0.5 #| let p = t * (ps0 + t * (ps1 + t * (ps2 + t * (ps3 + t * (ps4 + t * ps5))))) #| let q = 1.0 + t * (qs1 + t * (qs2 + t * (qs3 + t * qs4))) #| let s = t.sqrt() #| if ix >= 0x3FEF3333 { #| let w = p / q #| let t = pio2_hi - (2.0 * (s + s * w) - pio2_lo) #| return if x > 0.0 { t } else { -t } #| } else { #| let mut w = s #| w = set_low_word(w, 0) #| let c = (t - w * w) / (s + w) #| let r = p / q #| let p = 2.0 * s * r - (pio2_lo - 2.0 * c) #| let q = pio4_hi - 2.0 * w #| let t = pio4_hi - (p - q) #| return if x > 0.0 { t } else { -t } #| } #|} #|pub fn acos(x : Double) -> Double { #| let one : Double = 1.0 #| let pi : Double = 3.14159265358979311600 #| let pio2_hi : Double = 1.57079632679489655800 #| let pio2_lo : Double = 6.12323399573676603587e-17 #| let ps0 : Double = 1.66666666666666657415e-01 #| let ps1 : Double = -3.25565818622400915405e-01 #| let ps2 : Double = 2.01212532134862925881e-01 #| let ps3 : Double = -4.00555345006794114027e-02 #| let ps4 : Double = 7.91534994289814532176e-04 #| let ps5 : Double = 3.47933107596021167570e-05 #| let qs1 : Double = -2.40339491173441421878e+00 #| let qs2 : Double = 2.02094576023350569471e+00 #| let qs3 : Double = -6.88283971605453293030e-01 #| let qs4 : Double = 7.70381505559019352791e-02 #| let ix = get_high_word(x).reinterpret_as_int() & 0x7fffffff #| let absx = x.abs() #| if absx >= 1.0 { #| if absx == 1.0 { #| if x > 0 { #| return 0.0 #| } else { #| return pi + 2.0 * pio2_lo #| } #| } #| return @double.not_a_number #| } #| if absx < 0.5 { #| if ix <= 0x3c600000 { #| return pio2_hi + pio2_lo #| } #| let z = x * x #| let p = z * (ps0 + z * (ps1 + z * (ps2 + z * (ps3 + z * (ps4 + z * ps5))))) #| let q = one + z * (qs1 + z * (qs2 + z * (qs3 + z * qs4))) #| let r = p / q #| pio2_hi - (x - (pio2_lo - x * r)) #| } else if x < 0 { #| let z = (one + x) * 0.5 #| let p = z * (ps0 + z * (ps1 + z * (ps2 + z * (ps3 + z * (ps4 + z * ps5))))) #| let q = one + z * (qs1 + z * (qs2 + z * (qs3 + z * qs4))) #| let s = z.sqrt() #| let r = p / q #| let w = r * s - pio2_lo #| pi - 2.0 * (s + w) #| } else { #| let z = (one - x) * 0.5 #| let s = z.sqrt() #| let df = s #| let c = (z - df * df) / (s + df) #| let p = z * (ps0 + z * (ps1 + z * (ps2 + z * (ps3 + z * (ps4 + z * ps5))))) #| let q = one + z * (qs1 + z * (qs2 + z * (qs3 + z * qs4))) #| let r = p / q #| let w = r * s + c #| 2.0 * (df + w) #| } #|} #|pub fn atan(x : Double) -> Double { #| if x.is_nan() || x == 0.0 { #| return x #| } #| let atan_hi = [ #| 4.63647609000806093515e-01, 7.85398163397448278999e-01, 9.82793723247329054082e-01, #| 1.57079632679489655800e+00, #| ] #| let atan_lo = [ #| 2.26987774529616870924e-17, 3.06161699786838301793e-17, 1.39033110312309984516e-17, #| 6.12323399573676603587e-17, #| ] #| let a_t = [ #| 3.33333333333329318027e-01, -1.99999999998764832476e-01, 1.42857142725034663711e-01, #| -1.11111104054623557880e-01, 9.09088713343650656196e-02, -7.69187620504482999495e-02, #| 6.66107313738753120669e-02, -5.83357013379057348645e-02, 4.97687799461593236017e-02, #| -3.65315727442169155270e-02, 1.62858201153657823623e-02, #| ] #| let one = 1.0 #| let huge = 1.0e300 #| let ix = get_high_word(x).reinterpret_as_int() & 0x7fffffff #| let mut id = 0 #| let mut z = 0.0 #| let mut w = 0.0 #| let mut x = x #| let x_is_neg = x < 0.0 #| if ix >= 0x44100000 { #| if x > 0 { #| return atan_hi[3] + atan_lo[3] #| } else { #| return -atan_hi[3] - atan_lo[3] #| } #| } #| if ix < 0x3fdc0000 { #| if ix < 0x3e200000 { #| if huge + x > one { #| return x #| } #| } #| id = -1 #| } else { #| x = x.abs() #| if ix < 0x3ff30000 { #| if ix < 0x3fe60000 { #| id = 0 #| x = (2.0 * x - one) / (2.0 + x) #| } else { #| id = 1 #| x = (x - one) / (x + one) #| } #| } else if ix < 0x40038000 { #| id = 2 #| x = (x - 1.5) / (one + 1.5 * x) #| } else { #| id = 3 #| x = -1.0 / x #| } #| } #| z = x * x #| w = z * z #| let s1 = z * #| ( #| a_t[0] + #| w * (a_t[2] + w * (a_t[4] + w * (a_t[6] + w * (a_t[8] + w * a_t[10])))) #| ) #| let s2 = w * #| (a_t[1] + w * (a_t[3] + w * (a_t[5] + w * (a_t[7] + w * a_t[9])))) #| if id < 0 { #| x - x * (s1 + s2) #| } else { #| z = atan_hi[id] - (x * (s1 + s2) - atan_lo[id] - x) #| if x_is_neg { #| -z #| } else { #| z #| } #| } #|} #|pub fn atan2(y : Double, x : Double) -> Double { #| if x.is_nan() || y.is_nan() { #| return @double.not_a_number #| } #| let tiny = 1.0e-300 #| let zero = 0.0 #| let pi_o_4 = 7.8539816339744827900E-01 #| let pi_o_2 = 1.5707963267948965580E+00 #| let pi = 3.1415926535897931160E+00 #| let pi_lo = 1.2246467991473531772E-16 #| let hx = get_high_word(x).reinterpret_as_int() #| let hy = get_high_word(y).reinterpret_as_int() #| let ix = hx & 0x7fffffff #| let iy = hy & 0x7fffffff #| if x == 1.0 { #| return atan(y) #| } #| let m = ((hy >> 31) & 1) | ((hx >> 30) & 2) #| if y == 0 { #| match m { #| 0 | 1 => return y #| 2 => return pi + tiny #| _ => return -pi - tiny #| } #| } #| if x == 0 { #| return if hy < 0 { -pi_o_2 - tiny } else { pi_o_2 + tiny } #| } #| if x.is_inf() { #| if y.is_inf() { #| match m { #| 0 => return pi_o_4 + tiny #| 1 => return -pi_o_4 - tiny #| 2 => return 3.0 * pi_o_4 + tiny #| _ => return -3.0 * pi_o_4 - tiny #| } #| } else { #| match m { #| 0 => return zero #| 1 => return -zero #| 2 => return pi + tiny #| _ => return -pi - tiny #| } #| } #| } #| if y.is_inf() { #| return if hy < 0 { -pi_o_2 - tiny } else { pi_o_2 + tiny } #| } #| let k = (iy - ix) >> 20 #| let z = if k > 60 { #| pi_o_2 + 0.5 * pi_lo #| } else if hx < 0 && k < -60 { #| 0.0 #| } else { #| atan(abs(y / x)) #| } #| match m { #| 0 => z #| 1 => -z #| 2 => pi - (z - pi_lo) #| _ => z - pi_lo - pi #| } #|} #|fn rem_pio2(x : Double, y : Array[Double]) -> Int { #| let hx = get_high_word(x).reinterpret_as_int() #| let ix : Int = hx & 0x7fffffff #| let mut z = 0.0 #| if ix <= 0x3fe921fb { #| y[0] = x #| y[1] = 0.0 #| return 0 #| } #| if ix < 0x4002d97c { #| if hx > 0 { #| z = x - PIO2_1 #| if ix != 0x3ff921fb { #| y[0] = z - PIO2_1T #| y[1] = z - y[0] - PIO2_1T #| } else { #| z = z - PIO2_2 #| y[0] = z - PIO2_2T #| y[1] = z - y[0] - PIO2_2T #| } #| return 1 #| } else { #| z = x + PIO2_1 #| if ix != 0x3ff921fb { #| y[0] = z + PIO2_1T #| y[1] = z - y[0] + PIO2_1T #| } else { #| let z = z + PIO2_2 #| y[0] = z + PIO2_2T #| y[1] = z - y[0] + PIO2_2T #| } #| return -1 #| } #| } #| if ix <= 0x413921fb { #| let t = x.abs() #| let n = (t * INV_PIO2 + HALF).to_int() #| let fn_ = n.to_double() #| let mut r = t - fn_ * PIO2_1 #| let mut w = fn_ * PIO2_1T #| if n < 32 && ix != npio2_hw[n - 1] { #| y[0] = r - w #| } else { #| let j = ix >> 20 #| y[0] = r - w #| let i = j - ((get_high_word(y[0]) >> 20).reinterpret_as_int() & 0x7ff) #| if i > 16 { #| let t = r #| w = fn_ * PIO2_2 #| r = t - w #| w = fn_ * PIO2_2T - (t - r - w) #| y[0] = r - w #| let i = j - ((get_high_word(y[0]) >> 20).reinterpret_as_int() & 0x7ff) #| if i > 49 { #| let t = r #| w = fn_ * PIO2_3 #| r = t - w #| w = fn_ * PIO2_3T - (t - r - w) #| y[0] = r - w #| } #| } #| } #| y[1] = r - y[0] - w #| if hx > 0 { #| return n #| } else { #| y[0] = -y[0] #| y[1] = -y[1] #| return -n #| } #| } #| if ix >= 0x7ff00000 { #| y[0] = x - x #| y[1] = y[0] #| return 0 #| } #| z = set_low_word(z, get_low_word(x)) #| let e0 = (ix >> 20) - 1046 // e0 = ilogb(z) - 23 #| z = set_high_word(z, (ix - (e0 << 20)).reinterpret_as_uint()) #| let tx = [0.0, 0.0, 0.0] #| for i in 0..<2 { #| tx[i] = z.to_int().to_double() #| z = (z - tx[i]) * TWO24 #| } #| tx[2] = z #| let mut nx = 3 #| while tx[nx - 1] == 0.0 { #| nx -= 1 #| } #| let n = __kernel_rem_pio2(tx, y, e0, nx, 2) #| if hx > 0 { #| n #| } else { #| y[0] = -y[0] #| y[1] = -y[1] #| -n #| } #|} #|fn __kernel_rem_pio2( #| x : Array[Double], #| y : Array[Double], #| e0 : Int, #| nx : Int, #| prec : Int, #|) -> Int { #| let init_jk = [2, 3, 4, 6] #| let two24 : Double = 16777216.0 // 0x41700000, 0x00000000 #| let twon24 : Double = 5.96046447753906250000e-08 // 0x3E700000, 0x00000000 #| let mut jz : Int = 0 #| let mut jx : Int = 0 #| let mut jv : Int = 0 #| let mut jp : Int = 0 #| let mut jk : Int = 0 #| let mut carry : Int = 0 #| let mut n : Int = 0 #| let iq : Array[Int] = Array::make(20, 0) #| let mut i : Int = 0 #| let mut j : Int = 0 #| let mut k : Int = 0 #| let mut m : Int = 0 #| let mut q0 : Int = 0 #| let mut ih : Int = 0 #| let mut z : Double = 0 #| let mut fw : Double = 0 #| let f : Array[Double] = Array::make(20, 0.0) #| let fq : Array[Double] = Array::make(20, 0.0) #| let q : Array[Double] = Array::make(20, 0.0) #| jk = init_jk[prec] #| jp = jk #| jx = nx - 1 #| jv = (e0 - 3) / 24 #| if jv < 0 { #| jv = 0 #| } #| q0 = e0 - 24 * (jv + 1) #| j = jv - jx #| m = jx + jk #| i = 0 #| while i <= m { #| f[i] = if j < 0 { 0.0 } else { two_over_pi[j].to_double() } #| i += 1 #| j += 1 #| } #| i = 0 #| while i <= jk { #| j = 0 #| fw = 0.0 #| while j <= jx { #| fw += x[j] * f[jx + i - j] #| j += 1 #| } #| q[i] = fw #| i += 1 #| } #| jz = jk #| let mut recompute = true #| while recompute { #| recompute = false #| i = 0 #| j = jz #| z = q[jz] #| while j > 0 { #| fw = (twon24 * z).floor() #| iq[i] = (z - two24 * fw).to_int() #| z = q[j - 1] + fw #| i += 1 #| j -= 1 #| } #| z = scalbn(z, q0) // actual value of z #| z -= 8.0 * (z * 0.125).floor() // trim off integer >= 8 #| n = z.to_int() #| z -= n.to_double() #| ih = 0 #| if q0 > 0 { #| i = iq[jz - 1] >> (24 - q0) #| n += i #| iq[jz - 1] -= i << (24 - q0) #| ih = iq[jz - 1] >> (23 - q0) #| } else if q0 == 0 { #| ih = iq[jz - 1] >> 23 #| } else if z >= 0.5 { #| ih = 2 #| } #| if ih > 0 { #| n += 1 #| carry = 0 #| i = 0 #| while i < jz { #| j = iq[i] #| if carry == 0 { #| if j != 0 { #| carry = 1 #| iq[i] = 0x1000000 - j #| } #| } else { #| iq[i] = 0xffffff - j #| } #| i += 1 #| } #| if q0 > 0 { #| match q0 { #| 1 => iq[jz - 1] = iq[jz - 1] & 0x7fffff #| 2 => iq[jz - 1] = iq[jz - 1] & 0x3fffff #| _ => () #| } #| } #| if ih == 2 { #| z = 1.0 - z #| if carry != 0 { #| z -= scalbn(1.0, q0) #| } #| } #| } #| if z == 0.0 { #| j = 0 #| i = jz - 1 #| while i >= jk { #| j = j | iq[i] #| i -= 1 #| } #| if j == 0 { #| k = 1 #| while iq[jk - k] == 0 { #| k += 1 #| } #| i = jz + 1 #| while i <= jz + k { #| f[jx + i] = two_over_pi[jv + i].to_double() #| j = 0 #| fw = 0.0 #| while j <= jx { #| fw += x[j] * f[jx + i - j] #| j += 1 #| } #| q[i] = fw #| i += 1 #| } #| jz += k #| recompute = true // Continue to recompute #| continue #| } #| } // Skip the rest of the loop and recompute #| if z == 0.0 { #| jz -= 1 #| q0 -= 24 #| while iq[jz] == 0 { #| jz -= 1 #| q0 -= 24 #| } #| } else { #| z = scalbn(z, -q0) #| if z >= two24 { #| fw = (twon24 * z).floor() #| iq[jz] = (z - two24 * fw).to_int() #| jz += 1 #| q0 += 24 #| iq[jz] = fw.to_int() #| } else { #| iq[jz] = z.to_int() #| } #| } #| fw = scalbn(1.0, q0) #| i = jz #| while i >= 0 { #| q[i] = fw * iq[i].to_double() #| fw *= twon24 #| i -= 1 #| } #| i = jz #| while i >= 0 { #| fw = 0.0 #| k = 0 #| while k <= jp && k <= jz - i { #| fw += pi_over_2[k] * q[i + k] #| k += 1 #| } #| fq[jz - i] = fw #| i -= 1 #| } #| match prec { #| 0 => { #| fw = 0.0 #| i = jz #| while i >= 0 { #| fw += fq[i] #| i -= 1 #| } #| y[0] = if ih == 0 { fw } else { -fw } #| } #| 1 | 2 => { #| fw = 0.0 #| i = jz #| while i >= 0 { #| fw += fq[i] #| i -= 1 #| } #| y[0] = if ih == 0 { fw } else { -fw } #| fw = fq[0] - fw #| i = 1 #| while i <= jz { #| fw += fq[i] #| i += 1 #| } #| y[1] = if ih == 0 { fw } else { -fw } #| } #| 3 => { #| i = jz #| while i > 0 { #| fw = fq[i - 1] + fq[i] #| fq[i] += fq[i - 1] - fw #| fq[i - 1] = fw #| i -= 1 #| } #| i = jz #| while i > 1 { #| fw = fq[i - 1] + fq[i] #| fq[i] += fq[i - 1] - fw #| fq[i - 1] = fw #| i -= 1 #| } #| fw = 0.0 #| i = jz #| while i >= 2 { #| fw += fq[i] #| i -= 1 #| } #| if ih == 0 { #| y[0] = fq[0] #| y[1] = fq[1] #| y[2] = fw #| } else { #| y[0] = -fq[0] #| y[1] = -fq[1] #| y[2] = -fw #| } #| } #| _ => () #| } #| } #| n & 7 #|} #|fn __kernel_sin(x : Double, y : Double, iy : Int) -> Double { #| let s1 = -1.66666666666666324348e-01 #| let s2 = 8.33333333332248946124e-03 #| let s3 = -1.98412698298579493134e-04 #| let s4 = 2.75573137070700676789e-06 #| let s5 = -2.50507602534068634195e-08 #| let s6 = 1.58969099521155010221e-10 #| let mut z = 0.0 #| let mut r = 0.0 #| let mut v = 0.0 #| let ix = get_high_word(x) & 0x7fffffff #| if ix < 0x3e400000 { #| if x.to_int() == 0 { #| return x #| } #| } #| z = x * x #| v = z * x #| r = s2 + z * (s3 + z * (s4 + z * (s5 + z * s6))) #| if iy == 0 { #| x + v * (s1 + z * r) #| } else { #| x - (z * (0.5 * y - v * r) - y - v * s1) #| } #|} #|fn __kernel_cos(x : Double, y : Double) -> Double { #| let one = 1.00000000000000000000e+00 #| let c1 = 4.16666666666666019037e-02 #| let c2 = -1.38888888888741095749e-03 #| let c3 = 2.48015872894767294178e-05 #| let c4 = -2.75573143513906633035e-07 #| let c5 = 2.08757232129817482790e-09 #| let c6 = -1.13596475577881948265e-11 #| let mut a = 0.0 #| let mut hz = 0.0 #| let mut z = 0.0 #| let mut r = 0.0 #| let mut qx = 0.0 #| let ix = get_high_word(x) & 0x7fffffff #| if ix < 0x3e400000 { #| if x.to_int() == 0 { #| return one #| } #| } #| z = x * x #| r = z * (c1 + z * (c2 + z * (c3 + z * (c4 + z * (c5 + z * c6))))) #| if ix < 0x3fd33333 { #| return one - (0.5 * z - (z * r - x * y)) #| } else { #| if ix > 0x3fe90000 { #| qx = 0.28125 #| } else { #| qx = ((ix - 0x00200000).to_uint64() << 32).reinterpret_as_double() #| } #| hz = 0.5 * z - qx #| a = one - qx #| return a - (hz - (z * r - x * y)) #| } #|} #|fn __kernal_tan(x : Double, y : Double, iy : Int) -> Double { #| let one = 1.0 #| let pio4 = 7.85398163397448278999e-01 #| let pio4lo = 3.06161699786838301793e-17 #| let mut x = x #| let mut y = y #| let mut z = 0.0 #| let mut r = 0.0 #| let mut v = 0.0 #| let mut w = 0.0 #| let mut s = 0.0 #| let t = [ #| 3.33333333333334091986e-01, // 3FD55555, 55555563 */ #| 1.33333333333201242699e-01, // 3FC11111, 1110FE7A */ #| 5.39682539762260521377e-02, // 3FABA1BA, 1BB341FE */ #| 2.18694882948595424599e-02, // 3F9664F4, 8406D637 */ #| 8.86323982359930005737e-03, // 3F8226E3, E96E8493 */ #| 3.59207910759131235356e-03, // 3F6D6D22, C9560328 */ #| 1.45620945432529025516e-03, // 3F57DBC8, FEE08315 */ #| 5.88041240820264096874e-04, // 3F4344D8, F2F26501 */ #| 2.46463134818469906812e-04, // 3F3026F7, 1A8D1068 */ #| 7.81794442939557092300e-05, // 3F147E88, A03792A6 */ #| 7.14072491382608190305e-05, // 3F12B80F, 32F0A7E9 */ #| -1.85586374855275456654e-05, // BEF375CB, DB605373 */ #| 2.59073051863633712884e-05, // 3EFB2A70, 74BF7AD4 */ #| 1.00000000000000000000e+00, // 3FF00000, 00000000 (one) */ #| 7.85398163397448278999e-01, // 3FE921FB, 54442D18 (pio4) */ #| 3.06161699786838301793e-17, // 3C81A626, 33145C07 (pio4lo) */ #| ] #| let hx = get_high_word(x).reinterpret_as_int() #| let ix = hx & 0x7fffffff #| if ix < 0x3e300000 { #| if x.to_int() == 0 { #| if (ix | get_low_word(x).reinterpret_as_int() | (iy + 1)) == 0 { #| return one / x.abs() #| } else if iy == 1 { #| return x #| } else { #| w = x + y #| z = w #| z = set_low_word(z, 0) #| v = y - (z - x) #| let a = -one / w #| let mut t = a #| t = set_low_word(t, 0) #| s = one + t * z #| return t + a * (s + t * v) #| } #| } #| } #| if ix >= 0x3fe59428 { #| if hx < 0 { #| x = -x #| y = -y #| } #| z = pio4 - x #| w = pio4lo - y #| x = z + w #| y = 0.0 #| } #| z = x * x #| w = z * z #| r = t[1] + w * (t[3] + w * (t[5] + w * (t[7] + w * (t[9] + w * t[11])))) #| v = z * #| (t[2] + w * (t[4] + w * (t[6] + w * (t[8] + w * (t[10] + w * t[12]))))) #| s = z * x #| r = y + z * (s * (r + v) + y) #| r += t[0] * s #| w = x + r #| if ix >= 0x3fe59428 { #| v = iy.to_double() #| return (1 - ((hx >> 30) & 2)).to_double() * #| (v - 2.0 * (x - (w * w / (w + v) - r))) #| } #| if iy == 1 { #| w #| } else { #| z = w #| z = set_low_word(z, 0) #| v = r - (z - x) #| let a = -1.0 / w #| let mut t = a #| t = set_low_word(t, 0) #| s = 1.0 + t * z #| t + a * (s + t * v) #| } #|} ), "utils.mbt": ( #|fn abs(x : Double) -> Double { #| if x < 0.0 { #| -x #| } else { #| x #| } #|} #|let two_over_pi : FixedArray[Int] = [ #| 0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, 0x95993C, 0x439041, #| 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, 0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, #| 0xFE1DEB, 0x1CB129, 0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, #| 0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8, 0x97FFDE, 0x05980F, #| 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF, 0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, #| 0x7527BA, 0xC7EBE5, 0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, #| 0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, 0x91615E, 0xE61B08, #| 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, 0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, #| 0x60E27B, 0xC08C6B, #|] #|let pi_over_2 : FixedArray[Double] = [ #| 1.57079625129699707031e+00, // 0x3FF921FB, 0x40000000 */ #| 7.54978941586159635335e-08, // 0x3E74442D, 0x00000000 */ #| 5.39030252995776476554e-15, // 0x3CF84698, 0x80000000 */ #| 3.28200341580791294123e-22, // 0x3B78CC51, 0x60000000 */ #| 1.27065575308067607349e-29, // 0x39F01B83, 0x80000000 */ #| 1.22933308981111328932e-36, // 0x387A2520, 0x40000000 */ #| 2.73370053816464559624e-44, // 0x36E38222, 0x80000000 */ #| 2.16741683877804819444e-51, // 0x3569F31D, 0x00000000 */ #|] #|let npio2_hw : FixedArray[Int] = [ #| 0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C, 0x4025FDBB, #| 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C, 0x40346B9C, 0x4035FDBB, #| 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A, 0x403DD85A, 0x403F6A7A, 0x40407E4C, #| 0x4041475C, 0x4042106C, 0x4042D97C, 0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, #| 0x4046C6CB, 0x40478FDB, 0x404858EB, 0x404921FB, #|] #|const PI_OVER_4 : Double = 0.785398163397448309616 #|const PIO2_1 : Double = 1.5707963267341256e+00 // 0x3FF921FB, 0x54400000 */ #|const PIO2_1T : Double = 6.0771005065061922e-11 // 0x3DD0B461, 0x1A600000 */ #|const PIO2_2 : Double = 6.0771005063039660e-11 // 0x3DD0B461, 0x1A600000 */ #|const PIO2_2T : Double = 2.0222662487959506e-21 // 0x3BA3198A, 0x2E037073 */ #|const PIO2_3 : Double = 2.0222662487111665e-21 // 0x3BA3198A, 0x2E037073 */ #|const PIO2_3T : Double = 8.4784276603688996e-32 // 0x397B839A, 0x252049C1 */ #|const INV_PIO2 : Double = 6.3661977236758138e-01 // 0x3FE45F30, 0x6DC9C883 */ #|const HALF : Double = 0.5 #|const TWO24 : Double = 16777216.0 // 0x41700000, 0x00000000 */ #|fn set_low_word(d : Double, v : UInt) -> Double { #| let bits : UInt64 = d.reinterpret_as_uint64() #| let bits = bits & 0xFFFF_FFFF_0000_0000 #| let bits = bits | v.to_uint64() #| bits.reinterpret_as_double() #|} #|fn set_high_word(d : Double, v : UInt) -> Double { #| let bits : UInt64 = d.reinterpret_as_uint64() #| let bits = bits & 0x0000_0000_FFFF_FFFF #| let bits = bits | (v.to_uint64() << 32) #| bits.reinterpret_as_double() #|} #|fn get_high_word(x : Double) -> UInt { #| (x.reinterpret_as_uint64() >> 32).to_uint() #|} #|fn get_low_word(x : Double) -> UInt { #| x.reinterpret_as_uint64().to_uint() #|} #|const SQRT2 = 1.41421356237309504880168872420969807856967187537694807317667974 #|const LN2 = 0.693147180559945309417232121458176568075500134360255254120680009 #|const LN2_HI = 6.93147180369123816490e-01 // 3fe62e42 fee00000 #|const LN2_LO = 1.90821492927058770002e-10 // 3dea39ef 35793c76 #|fn normalize(f : Double) -> (Double, Int) { #| if f.abs() < @double.min_positive { #| return (f * (1L << 52).to_double(), -52) #| } #| (f, 0) #|} #|fn frexp(f : Double) -> (Double, Int) { #| if f == 0.0 || f.is_inf() || f.is_nan() { #| return (f, 0) #| } #| let (norm_f, exp) = normalize(f) #| let u = norm_f.reinterpret_as_uint64() #| let exp = exp + ((u >> 52) & 0x7FF).to_int() - 1022 #| let frac = ((u & (0x7FFUL << 52).lnot()) | (1022UL << 52)).reinterpret_as_double() #| return (frac, exp) #|} ), }, ) ///| let moonbitlang_core_option_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/option", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/quickcheck": moonbitlang_core_quickcheck_module, "moonbitlang/core/quickcheck/splitmix": moonbitlang_core_quickcheck_splitmix_module, }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/builtin", #| "moonbitlang/core/quickcheck", #| "moonbitlang/core/quickcheck/splitmix" #| ], #| "targets": { #| "panic_test.mbt": ["not", "native", "llvm"] #| } #|} ), "deprecated.mbt": ( #|#deprecated("inline instead for such tiny function") #|pub fn[T] when(condition : Bool, value : () -> T) -> T? { #| if condition { #| Some(value()) #| } else { #| None #| } #|} #|#deprecated("inline instead for such tiny function") #|pub fn[T] unless(condition : Bool, value : () -> T) -> T? { #| when(!condition, value) #|} #|#deprecated("inline instead for such tiny function") #|pub fn[T] empty() -> T? { #| None #|} #|#deprecated("inline instead for such tiny function") #|pub fn[T] some(value : T) -> T? { #| Some(value) #|} #|#deprecated("use unwrap_or instead") #|pub fn[T] Option::or(self : T?, default : T) -> T { #| match self { #| None => default #| Some(t) => t #| } #|} #|#deprecated("use unwrap_or_else instead") #|pub fn[T] Option::or_else(self : T?, default : () -> T) -> T { #| match self { #| None => default() #| Some(t) => t #| } #|} #|#deprecated("use unwrap_or_default instead") #|pub fn[T : Default] Option::or_default(self : T?) -> T { #| match self { #| None => T::default() #| Some(t) => t #| } #|} #|#deprecated("use `x is Some(_)` instead") #|pub fn[T] is_some(self : T?) -> Bool { #| self is Some(_) #|} #|#deprecated("use `x is None` instead") #|pub fn[T] is_none(self : T?) -> Bool { #| self is None #|} ), "option.mbt": ( #|test "some equals to Some" { #| let x : Int? = Some(5) #| let y : Int? = some(5) #| assert_eq(x, y) #|} #|pub fn[T, U] map(self : T?, f : (T) -> U) -> U? { #| match self { #| Some(t) => Some(f(t)) #| None => None #| } #|} #|test "map" { #| let a = Some(5) #| let b : Int? = None #| assert_eq(a.map(x => x * 2), Some(10)) #| assert_eq(b.map(x => x * 2), None) #|} #|pub fn[T, U] map_or(self : T?, default : U, f : (T) -> U) -> U { #| match self { #| None => default #| Some(x) => f(x) #| } #|} #|test "map_or" { #| let a = Option::Some("foo") #| let b : String? = Option::None #| assert_eq(a.map_or(42, x => x.length()), 3) #| assert_eq(b.map_or(42, x => x.length()), 42) #|} #|pub fn[T, U] map_or_else(self : T?, default : () -> U, f : (T) -> U) -> U { #| match self { #| None => default() #| Some(x) => f(x) #| } #|} #|test "map_or_else" { #| let k = 21 #| let a = Option::Some("foo") #| let b : String? = Option::None #| assert_eq(a.map_or_else(() => 2 * k, x => x.length()), 3) #| assert_eq(b.map_or_else(() => 2 * k, x => x.length()), 42) #|} #|pub fn[T, U] bind(self : T?, f : (T) -> U?) -> U? { #| match self { #| Some(t) => f(t) #| None => None #| } #|} #|test "bind" { #| let a = Option::Some(5) #| let b : Int? = None #| assert_eq(a.bind(x => Some(x * 2)), Some(10)) #| assert_eq(b.bind(x => Some(x * 2)), None) #|} #|pub fn[T] flatten(self : T??) -> T? { #| match self { #| Some(inner) => inner #| None => None #| } #|} #|test "flatten" { #| let a : Int?? = Some(Some(42)) #| assert_eq(a.flatten(), Some(42)) #| let b : Int?? = Some(None) #| assert_eq(b.flatten(), None) #|} #|pub fn[T] is_empty(self : T?) -> Bool { #| self is None #|} #|test "is_empty" { #| let x = Option::Some(3) #| let y : Int? = None #| assert_false(x.is_empty()) #| assert_true(y.is_empty()) #|} #|pub fn[T] filter(self : T?, f : (T) -> Bool) -> T? { #| match self { #| Some(t) => if f(t) { self } else { None } #| None => None #| } #|} #|test "filter" { #| let x = Option::Some(3) #| assert_eq(x.filter(x => x > 5), None) #| assert_eq(x.filter(x => x < 5), Some(3)) #|} #|pub fn[T] Option::unwrap_or(self : T?, default : T) -> T { #| match self { #| None => default #| Some(t) => t #| } #|} #|test "unwrap_or" { #| let x = Option::Some(3) #| assert_eq(x.unwrap_or(5), 3) #| assert_eq((None : Int?).unwrap_or(5), 5) #|} #|pub fn[T] Option::unwrap_or_else(self : T?, default : () -> T) -> T { #| match self { #| None => default() #| Some(t) => t #| } #|} #|test "or else" { #| let x = Option::Some(3) #| assert_eq(x.unwrap_or_else(() => 5), 3) #| assert_eq(None.unwrap_or_else(() => 5), 5) #|} #|pub fn[T : Default] Option::unwrap_or_default(self : T?) -> T { #| match self { #| None => T::default() #| Some(t) => t #| } #|} #|test "or default" { #| let x = Option::Some(3) #| assert_eq(x.unwrap_or_default(), 3) #| assert_eq((None : Int?).unwrap_or_default(), 0) #|} #|pub impl[X : Compare] Compare for X? with compare(self, other) { #| match (self, other) { #| (Some(x), Some(y)) => x.compare(y) #| (Some(_), None) => 1 #| (None, Some(_)) => -1 #| (None, None) => 0 #| } #|} #|test "compare" { #| let some1 = Option::Some(1) #| let some2 = Option::Some(2) #| let none = Option::None #| assert_eq(0, some1.compare(Option::Some(1))) #| assert_eq(-1, some1.compare(some2)) #| assert_eq(1, some2.compare(some1)) #| assert_eq(0, none.compare(none)) #| assert_eq(-1, none.compare(some1)) #| assert_eq(1, some2.compare(none)) #|} #|pub impl[X] Default for X? with default() { #| None #|} #|pub fn[T] iter(self : T?) -> Iter[T] { #| match self { #| Some(v) => Iter::singleton(v) #| None => Iter::empty() #| } #|} #|test "iter" { #| let x = Option::Some(42) #| let exb = StringBuilder::new(size_hint=0) #| x #| .iter() #| .each(x => { #| exb.write_string(x.to_string()) #| exb.write_char('\n') #| }) #| inspect( #| exb, #| content=( #| #|42 #| #| #| ), #| ) #| exb.reset() #| let y : Int? = None #| y #| .iter() #| .each(x => { #| exb.write_string(x.to_string()) #| exb.write_char('\n') #| }) #| inspect(exb, content="") #|} #|pub fn[T, Err : Error] or_error(self : T?, err : Err) -> T raise Err { #| match self { #| Some(v) => v #| None => raise err #| } #|} #|test "or error" { #| assert_eq( #| (None : String?).or_error(Failure("This is serious")) catch { #| Failure(err) => err #| }, #| "This is serious", #| ) #| assert_eq( #| Some("This is ok").or_error(Failure("This is serious")) catch { #| Failure(err) => err #| }, #| "This is ok", #| ) #|} #|pub impl[X : @quickcheck.Arbitrary] @quickcheck.Arbitrary for X? with arbitrary( #| i, #| rs, #|) { #| if rs.next_double() < 0.3 { #| None #| } else { #| Some(@quickcheck.Arbitrary::arbitrary(i, rs)) #| } #|} #|test "arbitrary" { #| let samples : Array[Int?] = @quickcheck.samples(10) #| inspect( #| samples, #| content="[None, None, Some(-1), Some(0), None, Some(0), Some(-5), Some(2), None, Some(4)]", #| ) #|} ), }, ) ///| let moonbitlang_core_prelude_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/prelude", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/bigint": moonbitlang_core_bigint_module, "moonbitlang/core/set": moonbitlang_core_set_module, "moonbitlang/core/array": moonbitlang_core_array_module, }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/builtin", #| "moonbitlang/core/bigint", #| "moonbitlang/core/set", #| "moonbitlang/core/array" #| ] #|} ), "deprecated.mbt": ( #|#deprecated("Use `@array.View` instead") #|pub typealias @array.View as ArrayView ), "prelude.mbt": ( #|pub typealias @builtin.( #| ArgsLoc, #| Array, #| UninitializedArray, #| Failure, #| Hasher, #| Iter, #| Iter2, #| IterResult, #| Json, #| Map, #| InspectError, #| SnapshotError, #| SourceLoc, #| StringBuilder #|) #|pub typealias @set.Set #|pub typealias @bigint.BigInt #|pub traitalias @builtin.( #| Eq, #| Compare, #| Hash, #| Logger, #| Show, #| ToJson, #| Default, #| Add, #| Sub, #| Mul, #| Div, #| Mod, #| Neg, #| Shl, #| Shr, #| BitAnd, #| BitOr, #| BitXOr #|) #|pub fnalias @builtin.( #| abort, #| assert_eq, #| assert_not_eq, #| assert_true, #| assert_false, #| fail, #| ignore, #| inspect, #| panic, #| physical_equal, #| println, #| not, #| repr, #| dump #|) #|pub fn[T] tap(value : T, f : (T) -> Unit) -> T { #| f(value) #| value #|} #|pub fn[T, R] then(value : T, f : (T) -> R) -> R { #| f(value) #|} #|pub let null : Json = @builtin.null ), }, ) ///| let moonbitlang_core_priority_queue_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/priority_queue", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/array": moonbitlang_core_array_module, "moonbitlang/core/quickcheck": moonbitlang_core_quickcheck_module, "moonbitlang/core/quickcheck/splitmix": moonbitlang_core_quickcheck_splitmix_module, "moonbitlang/core/json": moonbitlang_core_json_module, }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/builtin", #| "moonbitlang/core/array", #| "moonbitlang/core/quickcheck", #| "moonbitlang/core/quickcheck/splitmix", #| "moonbitlang/core/json" #| ], #| "test-import": ["moonbitlang/core/random"], #| "targets": { #| "panic_test.mbt": ["not", "native", "llvm"] #| } #|} ), "priority_queue.mbt": ( #|pub fn[A] new() -> T[A] { #| { len: 0, top: Nil } #|} #|pub fn[A : Compare] from_array(arr : Array[A]) -> T[A] { #| let len = arr.length() #| for i = 0, acc = Node::Nil { #| if i < len { #| continue i + 1, meld(acc, Cons(content=arr[i], sibling=Nil, child=Nil)) #| } else { #| break { len, top: acc } #| } #| } #|} #|fn[A] copy_node(x : Node[A]) -> Node[A] { #| match x { #| Nil => Nil #| Cons(_) as node => #| Cons( #| content=node.content, #| sibling=copy_node(node.sibling), #| child=copy_node(node.child), #| ) #| } #|} #|pub fn[A] copy(self : T[A]) -> T[A] { #| let new_que : T[A] = { len: self.len, top: copy_node(self.top) } #| new_que #|} #|pub fn[A : Compare] to_array(self : T[A]) -> Array[A] { #| let arr = Array::new(capacity=self.len) #| fn go(x : Node[A]) { #| match x { #| Cons(_) as x => { #| arr.push(x.content) #| go(x.sibling) #| go(x.child) #| } #| Nil => () #| } #| } #| go(self.top) #| arr.sort_by((x, y) => y.compare(x)) #| arr #|} #|pub fn[A : Compare] iter(self : T[A]) -> Iter[A] { #| Iter::new(yield_ => { #| let arr = self.to_array() #| for i in 0.. T[K] { #| let s = new() #| iter.each(e => s.push(e)) #| s #|} #|fn[A : Compare] meld(x : Node[A], y : Node[A]) -> Node[A] { #| match (x, y) { #| (Nil, _) => y #| (_, Nil) => x #| (Cons(_) as x_top, Cons(_) as y_top) => #| if x_top.content > y_top.content { #| y_top.sibling = x_top.child #| x_top.child = y #| x #| } else { #| x_top.sibling = y_top.child #| y_top.child = x #| y #| } #| } #|} #|fn[A : Compare] merges(x : Node[A]) -> Node[A] { #| loop (x, Nil) { #| (Nil, acc) => acc #| (Cons(sibling=Nil, ..) as x, acc) => meld(acc, x) #| (Cons(sibling=Cons(sibling=s2, ..) as s1, ..) as x, acc) => { #| x.sibling = Nil #| s1.sibling = Nil #| continue (s2, meld(acc, meld(x, s1))) #| } #| } #|} #|pub fn[A] length(self : T[A]) -> Int { #| self.len #|} #|#internal(unsafe, "Panic if the queue is empty.") #|pub fn[A : Compare] unsafe_pop(self : T[A]) -> Unit { #| self.top = match self.top { #| Nil => abort("The PriorityQueue is empty!") #| Cons(child~, ..) => merges(child) #| } #| self.len -= 1 #|} #|pub fn[A : Compare] pop(self : T[A]) -> A? { #| let result = self.peek() #| self.top = match self.top { #| Nil => Nil #| Cons(child~, ..) => { #| self.len -= 1 #| merges(child) #| } #| } #| result #|} #|pub fn[A : Compare] push(self : T[A], value : A) -> Unit { #| self.top = meld(self.top, Cons(content=value, sibling=Nil, child=Nil)) #| self.len += 1 #|} #|pub fn[A] peek(self : T[A]) -> A? { #| match self.top { #| Nil => None #| Cons(content~, ..) => Some(content) #| } #|} #|pub fn[A] clear(self : T[A]) -> Unit { #| self.top = Nil #| self.len = 0 #|} #|pub fn[A] is_empty(self : T[A]) -> Bool { #| self.len == 0 #|} #|pub fn[A : Compare] of(arr : FixedArray[A]) -> T[A] { #| let len = arr.length() #| for i = 0, acc = Node::Nil { #| if i < len { #| continue i + 1, meld(acc, Cons(content=arr[i], sibling=Nil, child=Nil)) #| } else { #| break { len, top: acc } #| } #| } #|} #|test "meld_and_merges" { #| inspect( #| match meld(Cons(content=1, sibling=Nil, child=Nil), Nil) { #| Nil => false #| Cons(..) => true #| }, #| content="true", #| ) #|} #|pub impl[A : Show + Compare] Show for T[A] with output(self, logger) { #| logger.write_iter(self.iter(), prefix="@priority_queue.of([", suffix="])") #|} #|pub impl[X : @quickcheck.Arbitrary + Compare] @quickcheck.Arbitrary for T[X] with arbitrary( #| size, #| rs, #|) { #| let len : Int = if size == 0 { 0 } else { rs.next_positive_int() % size } #| for i = 0, acc = Node::Nil { #| if i < len { #| continue i + 1, #| meld(acc, Cons(content=X::arbitrary(i, rs), sibling=Nil, child=Nil)) #| } else { #| break { len, top: acc } #| } #| } #|} #|test "priority queue arbitrary" { #| let samples : Array[T[Int]] = @quickcheck.samples(20) #| inspect( #| samples[5:10], #| content="[@priority_queue.of([]), @priority_queue.of([]), @priority_queue.of([0]), @priority_queue.of([0, 0]), @priority_queue.of([3, 2, 1, 0, 0, 0, 0])]", #| ) #| inspect( #| samples[11:15], #| content="[@priority_queue.of([0, 0, 0, -1, -2]), @priority_queue.of([8, 4, 0, 0, 0, 0, 0, 0, -2, -5]), @priority_queue.of([2, 0, 0, -1]), @priority_queue.of([0, 0])]", #| ) #|} #|pub impl[K] Default for T[K] with default() { #| new() #|} ), "types.mbt": ( #|priv enum Node[A] { #| Nil #| Cons(content~ : A, mut sibling~ : Node[A], mut child~ : Node[A]) #|} #|struct T[A] { #| mut len : Int #| mut top : Node[A] #|} ), }, ) ///| let moonbitlang_core_queue_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/queue", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/quickcheck": moonbitlang_core_quickcheck_module, }, files={ "moon.pkg.json": ( #|{ #| "import": ["moonbitlang/core/builtin", "moonbitlang/core/quickcheck"], #| "test-import": ["moonbitlang/core/array"], #| "targets": { #| "panic_test.mbt": ["not", "native", "llvm"] #| } #|} ), "deprecated.mbt": ( #|#deprecated("Use `unsafe_peek` instead") #|#coverage.skip #|pub fn[A] peek_exn(self : T[A]) -> A { #| self.unsafe_peek() #|} #|#deprecated("Use `unsafe_pop` instead") #|#coverage.skip #|pub fn[A] pop_exn(self : T[A]) -> A { #| self.unsafe_pop() #|} ), "queue.mbt": ( #|pub fn[A] new() -> T[A] { #| { length: 0, first: None, last: None } #|} #|pub fn[A] from_array(arr : Array[A]) -> T[A] { #| guard arr.length() > 0 else { return new() } #| let length = arr.length() #| let last = { content: arr[length - 1], next: None } #| let first = for i = length - 2, x = last; i >= 0; { #| continue i - 1, { content: arr[i], next: Some(x) } #| } else { #| x #| } #| { length, first: Some(first), last: Some(last) } #|} #|pub impl[A : Show] Show for T[A] with output(self, logger) { #| logger.write_iter(self.iter(), prefix="@queue.of([", suffix="])") #|} #|impl[A : Eq] Eq for T[A] with op_equal(self, other) { #| self.length == other.length && self.first == other.first #|} #|pub fn[A] clear(self : T[A]) -> Unit { #| self.length = 0 #| self.first = None #| self.last = None #|} #|pub fn[A] length(self : T[A]) -> Int { #| self.length #|} #|pub fn[A] is_empty(self : T[A]) -> Bool { #| self.length == 0 #|} #|pub fn[A] push(self : T[A], x : A) -> Unit { #| let cell = Some({ content: x, next: None }) #| match self.last { #| None => { #| self.length = 1 #| self.first = cell #| self.last = cell #| } #| Some(last) => { #| last.next = cell #| self.length += 1 #| self.last = cell #| } #| } #|} #|#internal(unsafe, "Panics if the queue is empty.") #|pub fn[A] unsafe_peek(self : T[A]) -> A { #| match self.first { #| None => abort("Queue is empty") #| Some(first) => first.content #| } #|} #|pub fn[A] peek(self : T[A]) -> A? { #| match self.first { #| None => None #| Some(first) => Some(first.content) #| } #|} #|#internal(unsafe, "Panics if the queue is empty.") #|pub fn[A] unsafe_pop(self : T[A]) -> A { #| match self.first { #| None => abort("Queue is empty") #| Some({ content, next: None }) => { #| self.clear() #| content #| } #| Some({ content, next }) => { #| self.length -= 1 #| self.first = next #| content #| } #| } #|} #|pub fn[A] pop(self : T[A]) -> A? { #| match self.first { #| None => None #| Some({ content, next: None }) => { #| self.clear() #| Some(content) #| } #| Some({ content, next }) => { #| self.length -= 1 #| self.first = next #| Some(content) #| } #| } #|} #|pub fn[A] each(self : T[A], f : (A) -> Unit) -> Unit { #| loop self.first { #| Some({ content, next }) => { #| f(content) #| continue next #| } #| None => () #| } #|} #|pub fn[A] eachi(self : T[A], f : (Int, A) -> Unit) -> Unit { #| loop (self.first, 0) { #| (Some({ content, next }), index) => { #| f(index, content) #| continue (next, index + 1) #| } #| (None, _) => () #| } #|} #|pub fn[A, B] fold(self : T[A], init~ : B, f : (B, A) -> B) -> B { #| loop (self.first, init) { #| (None, acc) => acc #| (Some({ content, next }), acc) => continue (next, f(acc, content)) #| } #|} #|pub fn[A] copy(self : T[A]) -> T[A] { #| guard self.first is Some({ content, next }) else { return new() } #| let first = { content, next: None } #| let last = loop (first, next) { #| (pre, Some({ content, next })) => { #| let curr = { content, next: None } #| pre.next = Some(curr) #| continue (curr, next) #| } #| (pre, None) => pre #| } #| { length: self.length, first: Some(first), last: Some(last) } #|} #|pub fn[A] transfer(self : T[A], dst : T[A]) -> Unit { #| if self.length > 0 { #| match dst.last { #| None => { #| dst.length = self.length #| dst.first = self.first #| dst.last = self.last #| self.clear() #| } #| Some(last) => { #| last.next = self.first #| dst.length = dst.length + self.length #| dst.last = self.last #| self.clear() #| } #| } #| } #|} #|pub fn[A] iter(self : T[A]) -> Iter[A] { #| Iter::new(yield_ => loop self.first { #| Some({ content, next }) => { #| if yield_(content) == IterEnd { #| break IterEnd #| } #| continue next #| } #| None => IterContinue #| }) #|} #|pub fn[A] from_iter(iter : Iter[A]) -> T[A] { #| let q = new() #| iter.each(e => q.push(e)) #| q #|} #|pub fn[A] of(arr : FixedArray[A]) -> T[A] { #| guard arr.length() > 0 else { return new() } #| let length = arr.length() #| let last = { content: arr[length - 1], next: None } #| let first = for i = length - 2, x = last; i >= 0; { #| continue i - 1, { content: arr[i], next: Some(x) } #| } else { #| Some(x) #| } #| { length, first, last: Some(last) } #|} #|test "from_fixed_array_2" { #| let q = of([1, 2, 3, 4]) #| q.push(11) #| assert_eq(q, of([1, 2, 3, 4, 11])) #| q.unsafe_pop() |> ignore #| assert_eq(q, of([2, 3, 4, 11])) #|} #|test "from_array_2" { #| let q = of([1, 2, 3, 4]) #| q.push(11) #| assert_eq(q, of([1, 2, 3, 4, 11])) #| q.unsafe_pop() |> ignore #| assert_eq(q, of([2, 3, 4, 11])) #|} #|test "op_equal" { #| let queue = of([1, 2, 3, 4]) #| let queue2 = of([1, 2, 3, 4]) #| let queue3 = of([1, 2, 3, 5]) #| assert_true(queue == queue2) #| assert_false(queue == queue3) #| queue.unsafe_pop() |> ignore #| assert_false(queue == queue2) #| assert_eq(queue, of([2, 3, 4])) #|} #|test "push" { #| let queue : T[Int] = new() #| queue.push(1) #| queue.push(2) #| queue.push(3) #| queue.push(1) #| assert_eq(queue.length(), 4) #| assert_eq(queue, of([1, 2, 3, 1])) #|} #|test "copy" { #| let queue : T[Int] = of([1, 2, 3, 4]) #| let queue2 : T[Int] = queue.copy() #| assert_eq(queue2.length(), 4) #| assert_eq(queue2, of([1, 2, 3, 4])) #| assert_eq(queue.length(), 4) #| assert_eq(queue, of([1, 2, 3, 4])) #|} #|test "transfer" { #| let queue : T[Int] = of([1, 2, 3, 4]) #| let queue2 : T[Int] = of([5, 6, 7, 8]) #| queue.transfer(queue2) #| assert_eq(queue.length(), 0) #| assert_eq(queue2.length(), 8) #| assert_eq(queue2, of([5, 6, 7, 8, 1, 2, 3, 4])) #|} #|test "cell_equal" { #| assert_false(of([]).first == of([1]).first) #|} #|pub impl[X : @quickcheck.Arbitrary] @quickcheck.Arbitrary for T[X] with arbitrary( #| size, #| rs, #|) { #| @quickcheck.Arbitrary::arbitrary(size, rs) |> from_iter #|} ), "types.mbt": ( #|priv struct Cons[A] { #| content : A #| mut next : Cons[A]? #|} derive(Eq) #|struct T[A] { #| mut length : Int #| mut first : Cons[A]? #| mut last : Cons[A]? #|} ), }, ) ///| let moonbitlang_core_quickcheck_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/quickcheck", deps={ "moonbitlang/core/quickcheck/splitmix": moonbitlang_core_quickcheck_splitmix_module, "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/char": moonbitlang_core_char_module, }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/quickcheck/splitmix", #| "moonbitlang/core/builtin", #| "moonbitlang/core/char" #| ], #| "test-import": [ #| "moonbitlang/core/array", #| "moonbitlang/core/bigint", #| "moonbitlang/core/float", #| "moonbitlang/core/double", #| "moonbitlang/core/tuple" #| ] #|} ), "arbitrary.mbt": ( #|pub(open) trait Arbitrary { #| arbitrary(Int, @splitmix.RandomState) -> Self #|} #|pub impl Arbitrary for Unit with arbitrary(_, _) { #| () #|} #|pub impl Arbitrary for Bool with arbitrary(_, rs) { #| rs.next_double() < 0.5 #|} #|pub impl Arbitrary for Int with arbitrary(size, rs) { #| if size == 0 { #| 0 #| } else { #| rs.next_int() % size #| } #|} #|pub impl Arbitrary for UInt with arbitrary(size, rs) { #| if size == 0 { #| 0 #| } else { #| rs.next_uint() % size.reinterpret_as_uint() #| } #|} #|pub impl Arbitrary for Byte with arbitrary(_, rs) { #| rs.next_uint().to_byte() #|} #|pub impl Arbitrary for Bytes with arbitrary(size, rs) { #| if size == 0 { #| Bytes::new(0) #| } else { #| let sz = rs.next_positive_int() % size #| Bytes::makei(sz, _ => Arbitrary::arbitrary(size, rs)) #| } #|} #|pub impl Arbitrary for Int64 with arbitrary(size, rs) { #| if size == 0 { #| 0 #| } else { #| rs.next_int64() % size.to_int64() #| } #|} #|pub impl Arbitrary for UInt64 with arbitrary(size, rs) { #| if size == 0 { #| 0 #| } else { #| rs.next_uint64() % size.to_uint64() #| } #|} #|pub impl Arbitrary for Float with arbitrary(_, rs) { #| rs.next_float() #|} #|pub impl Arbitrary for Double with arbitrary(_, rs) { #| rs.next_double() #|} #|pub impl Arbitrary for Char with arbitrary(_, rs) { #| ((rs.next_uint() % 128) |> UInt::reinterpret_as_int).unsafe_to_char() #|} #|pub impl Arbitrary for String with arbitrary(size, rs) { #| let len = if size == 0 { 0 } else { rs.next_positive_int() % size } #| let mut s = "" #| for i in 0.. for i in 0.. T { #| let size = match size { #| None => 0 #| Some(x) => x #| } #| let state = match state { #| None => @splitmix.RandomState::default() #| Some(x) => x #| } #| Arbitrary::arbitrary(size, state) #|} ), "utils.mbt": ( #|pub fn[X : Arbitrary] samples(x : Int) -> Array[X] { #| let rs = @splitmix.new() #| let array = Array::make(x, X::arbitrary(0, rs)) #| for i in 1.. RandomState { #| new(seed~) #|} ), "random.mbt": ( #|struct RandomState { #| mut seed : UInt64 #| gamma : UInt64 #|} derive(Show, Default) #|let golden_gamma : UInt64 = 0x9e3779b97f4a7c15 #|let double_ulp : Double = 1.0 / (1L << 53).to_double() #|let float_ulp : Float = 1.0.to_float() / (1L << 24).to_float() #|pub fn new(seed? : UInt64 = 37) -> RandomState { #| { seed: mix64(seed), gamma: mix_gamma(seed + golden_gamma) } #|} #|pub fn clone(self : RandomState) -> RandomState { #| { ..self } #|} #|pub fn next(self : RandomState) -> Unit { #| self.next_uint64() |> ignore #|} #|pub fn next_uint64(self : RandomState) -> UInt64 { #| let { seed, gamma } = self #| self.seed = seed + gamma #| mix64(self.seed) #|} #|pub fn next_uint(self : RandomState) -> UInt { #| self.next_uint64().to_uint() #|} #|pub fn next_int64(self : RandomState) -> Int64 { #| self.next_uint64().reinterpret_as_int64() #|} #|pub fn next_two_uint(self : RandomState) -> (UInt, UInt) { #| let g = self.next_uint64() #| ((g >> 32).to_uint(), g.to_uint()) #|} #|pub fn next_int(self : RandomState) -> Int { #| self.next_uint().reinterpret_as_int() #|} #|pub fn next_positive_int(self : RandomState) -> Int { #| let r = self.next_int() #| match r { #| -2147483648 => 2147483647 #| 0 => 1 #| r if r < 0 => -r #| r => r #| } #|} #|pub fn next_float(self : RandomState) -> Float { #| let u = self.next_uint64() #| (u >> 11).to_float() * float_ulp #|} #|pub fn next_double(self : RandomState) -> Double { #| let u = self.next_uint64() #| (u >> 11).to_double() * double_ulp #|} #|pub fn split(self : RandomState) -> RandomState { #| let seed1 = self.seed + self.gamma #| self.seed = seed1 + self.gamma #| { seed: mix64(seed1), gamma: mix_gamma(self.seed) } #|} #|fn shift_xor(n : Int, w : UInt64) -> UInt64 { #| w ^ (w >> n) #|} #|fn shift_xor_mul(n : Int, k : UInt64, w : UInt64) -> UInt64 { #| shift_xor(n, w) * k #|} #|fn mix64(z0 : UInt64) -> UInt64 { #| let z1 = shift_xor_mul(30, 0xff51afd7ed558ccd, z0) #| let z2 = shift_xor_mul(33, 0xc4ceb9fe1a85ec53, z1) #| shift_xor(33, z2) #|} #|fn mix64variant13(z0 : UInt64) -> UInt64 { #| let z1 = shift_xor_mul(30, 0xbf58476d1ce4e5b9, z0) #| let z2 = shift_xor_mul(27, 0x94d049bb133111eb, z1) #| shift_xor(31, z2) #|} #|fn mix_gamma(z0 : UInt64) -> UInt64 { #| let z1 = mix64variant13(z0 | 1) #| let n = (z1 | (z1 >> 1)).popcnt() #| if n >= 24 { #| z1 #| } else { #| z1 ^ 0xaaaaaaaaaaaaaaaa #| } #|} ), }, ) ///| let moonbitlang_core_random_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/random", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/double": moonbitlang_core_double_module, "moonbitlang/core/random/internal/random_source": moonbitlang_core_random_internal_random_source_module, "moonbitlang/core/bigint": moonbitlang_core_bigint_module, }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/builtin", #| "moonbitlang/core/double", #| "moonbitlang/core/random/internal/random_source", #| "moonbitlang/core/bigint" #| ], #| "test-import": [ #| "moonbitlang/core/float", #| "moonbitlang/core/bench" #| ] #|} ), "deprecated.mbt": ( #|#deprecated("Use `Rand::new()` instead") #|pub fn new(seed? : Bytes = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ123456") -> Rand { #| if seed.length() != 32 { #| abort("seed must be 32 bytes long") #| } #| @random_source.ChaCha8::new(seed) as &Source #|} ), "random.mbt": ( #|struct Rand(&Source) #|pub(open) trait Source { #| next(Self) -> UInt64 #|} #|impl Source for @random_source.ChaCha8 with next(self : @random_source.ChaCha8) -> UInt64 { #| for { #| if self.next() is Some(x) { #| return x #| } #| self.refill() #| } #|} #|pub fn Rand::chacha8( #| seed? : Bytes = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ123456", #|) -> Rand { #| if seed.length() != 32 { #| abort("seed must be 32 bytes long") #| } #| Rand(@random_source.ChaCha8::new(seed) as &Source) #|} #|#deprecated("You may use `Rand::chacha8(seed~)` instead of `Rand::new(chacha8(seed~))") #|pub fn chacha8(seed? : Bytes = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ123456") -> &Source { #| @random_source.ChaCha8::new(seed) #|} #|pub fn Rand::new(generator? : &Source) -> Rand { #| match generator { #| None => chacha8() #| Some(gen) => Rand(gen) #| } #|} #|fn next(self : Rand) -> UInt64 { #| let Rand(s) = self #| s.next() #|} #|test "next" { #| let r = new() #| let n = r.next() #| let exp = 13219109469176600229UL #| assert_eq(n, exp) #|} #|pub fn int(self : Rand, limit? : Int = 0) -> Int { #| if limit == 0 { #| (self.next() >> 33).to_int() #| } else { #| self.uint(limit=limit.reinterpret_as_uint()).reinterpret_as_int() #| } #|} #|pub fn int64(self : Rand, limit? : Int64 = 0) -> Int64 { #| if limit == 0 { #| let mask : UInt64 = (1UL << 63) - 1UL #| return (self.next() & mask).reinterpret_as_int64() #| } else { #| self.uint64(limit=limit.reinterpret_as_uint64()).reinterpret_as_int64() #| } #|} #|pub fn uint(self : Rand, limit? : UInt = 0) -> UInt { #| if limit == 0 { #| return self.next().to_uint() #| } #| self.uint64(limit=limit.to_uint64()).to_uint() #|} #|test "uint" { #| let r = new() #| let n = r.uint(limit=10U) #| inspect(n, content="7") #| let n = r.uint(limit=10U) #| inspect(n, content="0") #| let n = r.uint(limit=10U) #| inspect(n, content="5") #|} #|pub fn uint64(self : Rand, limit? : UInt64 = 0) -> UInt64 { #| if limit == 0 { #| return self.next() #| } else if (limit & (limit - 1)) == 0 { #| return self.next() & (limit - 1) #| } #| let mut r = umul128(self.next(), limit) #| if r.lo < limit { #| let thresh = limit.lnot() % limit #| while r.lo < thresh { #| r = umul128(self.next(), limit) #| } #| } #| r.hi #|} #|test "UInt64" { #| let r = new() #| let n = r.uint64() #| let exp = 13219109469176600229UL #| assert_eq(n, exp) #| let r = new() #| let n = r.uint64(limit=10UL) #| inspect(n, content="7") #| let n = r.uint64(limit=10UL) #| inspect(n, content="0") #| let n = r.uint64(limit=10UL) #| inspect(n, content="5") #|} #|pub fn double(self : Rand) -> Double { #| Double::convert_uint64(self.next() << 11 >> 11) / #| Double::convert_uint64(1UL << 53) #|} #|test "double" { #| let r = new() #| let n = r.double() #| inspect(n, content="0.615969772029264") #|} #|pub fn float(self : Rand) -> Float { #| (self.uint() << 8 >> 8).to_float() / (1U << 24).to_float() #|} #|pub fn bigint(self : Rand, bits : Int) -> @bigint.BigInt { #| let mod = bits % 8 #| let len = if mod == 0 { bits / 8 } else { bits / 8 + 1 } #| let bytes = Bytes::makei(len, i => if i == 0 && mod != 0 { #| let mask = (1U << mod) - 1U #| (self.uint(limit=256) & mask).to_byte() #| } else { #| self.uint(limit=256).to_byte() #| }) #| @bigint.BigInt::from_octets(bytes) #|} #|test "bigint" { #| let r = new() #| inspect(r.bigint(1), content="1") #| inspect(r.bigint(3), content="4") #| inspect(r.bigint(7), content="124") #| inspect(r.bigint(8), content="214") #| inspect(r.bigint(32), content="2910404175") #| inspect(r.bigint(40), content="714745001576") #| inspect(r.bigint(64), content="13430064486797060338") #| inspect(r.bigint(128), content="251068071753473224445949321151725639522") #|} #|#valtype #|priv struct UInt128 { #| hi : UInt64 #| lo : UInt64 #|} #|fn umul128(a : UInt64, b : UInt64) -> UInt128 { #| let aLo = a & 0xffffffff #| let aHi = a >> 32 #| let bLo = b & 0xffffffff #| let bHi = b >> 32 #| let x = aLo * bLo #| let y = aHi * bLo + (x >> 32) #| let z = aLo * bHi + (y & 0xffffffff) #| let w = aHi * bHi + (y >> 32) + (z >> 32) #| { hi: w, lo: a * b } #|} #|test "umul128" { #| let r = umul128(0x123456789ABCDEF0, 0xFEDCBA9876543210) #| assert_eq(r.hi, 1305938385386173474UL) #| assert_eq(r.lo, 2552847189736476416UL) #|} #|test "umul128: handles small numbers correctly" { #| let r = umul128(1UL, 1UL) #| assert_eq(r.hi, 0UL) #| assert_eq(r.lo, 1UL) #|} #|test "umul128: handles large numbers correctly" { #| let r = umul128(1UL, 0xFFFFFFFFFFFFFFFFUL) #| assert_eq(r.hi, 0UL) #| assert_eq(r.lo, 0xFFFFFFFFFFFFFFFFUL) #|} #|test "umul128: handles zero correctly" { #| let r = umul128(0UL, 0UL) #| assert_eq(r.hi, 0UL) #| assert_eq(r.lo, 0UL) #|} #|pub fn shuffle(self : Rand, limit : Int, swap : (Int, Int) -> Unit) -> Unit { #| if limit < 0 { #| abort("Rand::shuffle: invalid argument limit") #| } #| for i = limit - 1; i > 0; i = i - 1 { #| let j = self.int(limit=i + 1) #| swap(i, j) #| } #|} #|test "shuffle" { #| let r = new() #| let a = [1, 2, 3, 4, 5] #| r.shuffle(a.length(), (i : Int, j : Int) => { #| let t = a[i] #| a[i] = a[j] #| a[j] = t #| }) #| inspect(a, content="[3, 5, 2, 1, 4]") #|} ), }, ) ///| let moonbitlang_core_random_internal_random_source_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/random/internal/random_source", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/array": moonbitlang_core_array_module, "moonbitlang/core/bytes": moonbitlang_core_bytes_module, }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/builtin", #| "moonbitlang/core/array", #| "moonbitlang/core/bytes" #| ] #|} ), "random_source_chacha.mbt": ( #|struct ChaCha8 { #| buffer : FixedArray[UInt] #| seed : FixedArray[UInt] #| mut i : UInt #| mut n : UInt #| mut counter : UInt #|} #|pub fn ChaCha8::new(seed : Bytes) -> ChaCha8 { #| let seed = FixedArray::makei(SEED_CHUNK_NUM * 2, i => seed[i * 4:i * 4 + 4].to_uint_le()) #| let buffer = FixedArray::make(BUFFER_CHUNK_NUM * 2, 0U) #| chacha_block(seed, buffer, 0) #| { seed, buffer, counter: 0, i: 0, n: BUFFER_CHUNK_NUM.reinterpret_as_uint() } #|} #|const COUNTER_INC = 4U #|const COUNTER_MAX = 16U #|const BUFFER_CHUNK_NUM = 32 #|const SEED_CHUNK_NUM = 4 #|pub fn ChaCha8::next(self : ChaCha8) -> UInt64? { #| let i = self.i #| if i >= self.n { #| return None #| } #| self.i = i + 1 #| let index = i.reinterpret_as_int() & (BUFFER_CHUNK_NUM - 1) #| let lo = self.buffer[index * 2].to_uint64() #| let hi = self.buffer[index * 2 + 1].to_uint64() #| Some((hi << 32) | lo) #|} #|pub fn ChaCha8::refill(self : ChaCha8) -> Unit { #| self.counter += COUNTER_INC #| if self.counter == COUNTER_MAX { #| self.buffer.blit_to( #| self.seed, #| len=SEED_CHUNK_NUM * 2, #| src_offset=(BUFFER_CHUNK_NUM - SEED_CHUNK_NUM) * 2, #| ) #| self.counter = 0 #| } #| chacha_block(self.seed, self.buffer, self.counter) #| self.i = 0 #| self.n = if self.counter == COUNTER_MAX - COUNTER_INC { #| (BUFFER_CHUNK_NUM - SEED_CHUNK_NUM).reinterpret_as_uint() #| } else { #| BUFFER_CHUNK_NUM.reinterpret_as_uint() #| } #|} #|#valtype #|priv struct Quadruple { #| _0 : UInt #| _1 : UInt #| _2 : UInt #| _3 : UInt #|} #|fn chacha_block( #| seed : FixedArray[UInt], #| buf : FixedArray[UInt], #| counter : UInt, #|) -> Unit { #| fn qr(t : Quadruple) -> Quadruple { #| let a = t._0 #| let b = t._1 #| let c = t._2 #| let d = t._3 #| let a = a + b #| let d = d ^ a #| let d = (d << 16) | (d >> 16) #| let c = c + d #| let b = b ^ c #| let b = (b << 12) | (b >> 20) #| let a = a + b #| let d = d ^ a #| let d = (d << 8) | (d >> 24) #| let c = c + d #| let b = b ^ c #| let b = (b << 7) | (b >> 25) #| { _0: a, _1: b, _2: c, _3: d } #| } #| setup(seed, buf, counter) #| for i in 0..<4 { #| let mut b0 = buf[0 * 4 + i] #| let mut b1 = buf[1 * 4 + i] #| let mut b2 = buf[2 * 4 + i] #| let mut b3 = buf[3 * 4 + i] #| let mut b4 = buf[4 * 4 + i] #| let mut b5 = buf[5 * 4 + i] #| let mut b6 = buf[6 * 4 + i] #| let mut b7 = buf[7 * 4 + i] #| let mut b8 = buf[8 * 4 + i] #| let mut b9 = buf[9 * 4 + i] #| let mut b10 = buf[10 * 4 + i] #| let mut b11 = buf[11 * 4 + i] #| let mut b12 = buf[12 * 4 + i] #| let mut b13 = buf[13 * 4 + i] #| let mut b14 = buf[14 * 4 + i] #| let mut b15 = buf[15 * 4 + i] #| for round in 0..<4 { #| let tb1 = qr({ _0: b0, _1: b4, _2: b8, _3: b12 }) #| b0 = tb1._0 #| b4 = tb1._1 #| b8 = tb1._2 #| b12 = tb1._3 #| let tb2 = qr({ _0: b1, _1: b5, _2: b9, _3: b13 }) #| b1 = tb2._0 #| b5 = tb2._1 #| b9 = tb2._2 #| b13 = tb2._3 #| let tb3 = qr({ _0: b2, _1: b6, _2: b10, _3: b14 }) #| b2 = tb3._0 #| b6 = tb3._1 #| b10 = tb3._2 #| b14 = tb3._3 #| let tb4 = qr({ _0: b3, _1: b7, _2: b11, _3: b15 }) #| b3 = tb4._0 #| b7 = tb4._1 #| b11 = tb4._2 #| b15 = tb4._3 #| let tb5 = qr({ _0: b0, _1: b5, _2: b10, _3: b15 }) #| b0 = tb5._0 #| b5 = tb5._1 #| b10 = tb5._2 #| b15 = tb5._3 #| let tb6 = qr({ _0: b1, _1: b6, _2: b11, _3: b12 }) #| b1 = tb6._0 #| b6 = tb6._1 #| b11 = tb6._2 #| b12 = tb6._3 #| let tb7 = qr({ _0: b2, _1: b7, _2: b8, _3: b13 }) #| b2 = tb7._0 #| b7 = tb7._1 #| b8 = tb7._2 #| b13 = tb7._3 #| let tb8 = qr({ _0: b3, _1: b4, _2: b9, _3: b14 }) #| b3 = tb8._0 #| b4 = tb8._1 #| b9 = tb8._2 #| b14 = tb8._3 #| } #| buf[0 * 4 + i] = b0 #| buf[1 * 4 + i] = b1 #| buf[2 * 4 + i] = b2 #| buf[3 * 4 + i] = b3 #| buf[4 * 4 + i] += b4 #| buf[5 * 4 + i] += b5 #| buf[6 * 4 + i] += b6 #| buf[7 * 4 + i] += b7 #| buf[8 * 4 + i] += b8 #| buf[9 * 4 + i] += b9 #| buf[10 * 4 + i] += b10 #| buf[11 * 4 + i] += b11 #| buf[12 * 4 + i] = b12 #| buf[13 * 4 + i] = b13 #| buf[14 * 4 + i] = b14 #| buf[15 * 4 + i] = b15 #| } #|} #|fn setup( #| seed : FixedArray[UInt], #| b32 : FixedArray[UInt], #| counter : UInt, #|) -> Unit { #| b32[0 * 4 + 0] = 0x61707865 #| b32[0 * 4 + 1] = 0x61707865 #| b32[0 * 4 + 2] = 0x61707865 #| b32[0 * 4 + 3] = 0x61707865 #| b32[1 * 4 + 0] = 0x3320646e #| b32[1 * 4 + 1] = 0x3320646e #| b32[1 * 4 + 2] = 0x3320646e #| b32[1 * 4 + 3] = 0x3320646e #| b32[2 * 4 + 0] = 0x79622d32 #| b32[2 * 4 + 1] = 0x79622d32 #| b32[2 * 4 + 2] = 0x79622d32 #| b32[2 * 4 + 3] = 0x79622d32 #| b32[3 * 4 + 0] = 0x6b206574 #| b32[3 * 4 + 1] = 0x6b206574 #| b32[3 * 4 + 2] = 0x6b206574 #| b32[3 * 4 + 3] = 0x6b206574 #| b32[4 * 4 + 0] = seed[0] #| b32[4 * 4 + 1] = seed[0] #| b32[4 * 4 + 2] = seed[0] #| b32[4 * 4 + 3] = seed[0] #| b32[5 * 4 + 0] = seed[1] #| b32[5 * 4 + 1] = seed[1] #| b32[5 * 4 + 2] = seed[1] #| b32[5 * 4 + 3] = seed[1] #| b32[6 * 4 + 0] = seed[2] #| b32[6 * 4 + 1] = seed[2] #| b32[6 * 4 + 2] = seed[2] #| b32[6 * 4 + 3] = seed[2] #| b32[7 * 4 + 0] = seed[3] #| b32[7 * 4 + 1] = seed[3] #| b32[7 * 4 + 2] = seed[3] #| b32[7 * 4 + 3] = seed[3] #| b32[8 * 4 + 0] = seed[4] #| b32[8 * 4 + 1] = seed[4] #| b32[8 * 4 + 2] = seed[4] #| b32[8 * 4 + 3] = seed[4] #| b32[9 * 4 + 0] = seed[5] #| b32[9 * 4 + 1] = seed[5] #| b32[9 * 4 + 2] = seed[5] #| b32[9 * 4 + 3] = seed[5] #| b32[10 * 4 + 0] = seed[6] #| b32[10 * 4 + 1] = seed[6] #| b32[10 * 4 + 2] = seed[6] #| b32[10 * 4 + 3] = seed[6] #| b32[11 * 4 + 0] = seed[7] #| b32[11 * 4 + 1] = seed[7] #| b32[11 * 4 + 2] = seed[7] #| b32[11 * 4 + 3] = seed[7] #| b32[12 * 4 + 0] = counter + 0 #| b32[12 * 4 + 1] = counter + 1 #| b32[12 * 4 + 2] = counter + 2 #| b32[12 * 4 + 3] = counter + 3 #| b32[13 * 4 + 0] = 0 #| b32[13 * 4 + 1] = 0 #| b32[13 * 4 + 2] = 0 #| b32[13 * 4 + 3] = 0 #| b32[14 * 4 + 0] = 0 #| b32[14 * 4 + 1] = 0 #| b32[14 * 4 + 2] = 0 #| b32[14 * 4 + 3] = 0 #| b32[15 * 4 + 0] = 0 #| b32[15 * 4 + 1] = 0 #| b32[15 * 4 + 2] = 0 #| b32[15 * 4 + 3] = 0 #|} #|test "BUFFER_CHUNK_NUM is power of 2" { #| assert_eq(BUFFER_CHUNK_NUM.clz() + BUFFER_CHUNK_NUM.ctz(), 31) #|} #|test "output" { #| let s = ChaCha8::new(b"ABCDEFGHIJKLMNOPQRSTUVWXYZ123456") #| let res = Array::new(capacity=372) #| fn uint64(s : ChaCha8) -> UInt64 { #| for { #| if s.next() is Some(x) { #| return x #| } #| s.refill() #| } #| } #| for i in 0..<372 { #| let x = uint64(s) #| res.push(x) #| } #| let expected = [ #| 13219109469176600229UL, 1252193259764759612UL, 10098646897834928252UL, 9142445797040479446UL, #| 14963947397558572717UL, 1011356013395962489UL, 4360278772332321598UL, 11266561239126549327UL, #| 16103107970030431910UL, 3951155890335085418UL, 17217491508779737119UL, 620366957612729398UL, #| 15701003340574544488UL, 16946962128229337786UL, 5734710318278665825UL, 14107018073513584172UL, #| 10514695901183618686UL, 8668570317698669510UL, 6644195231047269920UL, 5695522258251995816UL, #| 18173674537264966642UL, 6561080880156464316UL, 7896566770606135777UL, 17198961315715285235UL, #| 3258233649777561765UL, 4039019003980269744UL, 17199080872890330697UL, 17597083911441838460UL, #| 9541597232904836516UL, 10269632480771352091UL, 1791309313159652499UL, 1121290688170442051UL, #| 14767415290099658880UL, 18264015867885335344UL, 10795746865526236211UL, 7814966709161082135UL, #| 5056082071174014306UL, 6606687772221963370UL, 902460967827941768UL, 15247644503822243389UL, #| 13837920613503741631UL, 6215820458297045417UL, 2701601382099612372UL, 8049443921449462014UL, #| 12580932726856406240UL, 5068579462968063859UL, 2054759765710618254UL, 8060325759976441792UL, #| 3952703220727229276UL, 11868554197401451959UL, 5611917470950228677UL, 14826085289999852455UL, #| 18131733951999902497UL, 6983040833037131399UL, 15098965934858340182UL, 7162487557317849930UL, #| 389612597396113390UL, 5480468948381420210UL, 14924541494497045954UL, 438038016380948435UL, #| 15107526033745383085UL, 3577988464916041960UL, 12379376873809997548UL, 4629939204773816090UL, #| 4382836348202044776UL, 15911307370497934714UL, 16912525941835256446UL, 1749399752872286892UL, #| 17865934552210109010UL, 6342441227090084049UL, 6679300346758746971UL, 16633103117551110662UL, #| 369926567391976152UL, 3270154504052173416UL, 12351442307584366520UL, 14053856752323452444UL, #| 5700095014850418212UL, 18134114469714363192UL, 11060594460025237009UL, 1231359220627153402UL, #| 562452272787830041UL, 2978775404523127572UL, 4722226048622717816UL, 6253931703231703629UL, #| 9215422719337958629UL, 3873253580645818250UL, 1288530853271360801UL, 11001669669030575221UL, #| 15088099745414120440UL, 10121311161118028787UL, 2646319338087045047UL, 8736474933647836016UL, #| 10270419548610515257UL, 4775977266197392933UL, 5858955664787759631UL, 15884112255303985129UL, #| 1570402559843208890UL, 14683984304255533684UL, 4590793746421620769UL, 15088822470495597798UL, #| 430063278371467896UL, 17951554591419905623UL, 871816740556950425UL, 17903421440867820178UL, #| 13750571273678813240UL, 17408919480923799904UL, 14550467517685344003UL, 17801022151644150006UL, #| 15135601085914355452UL, 3483086720686978374UL, 9411102566564534151UL, 1565275101947305404UL, #| 18195171881473325257UL, 3771067494878101692UL, 7443114766343082856UL, 1311911009840065015UL, #| 1031414546975514137UL, 16727931877057143004UL, 420176525623228030UL, 16779254430513255833UL, #| 2085321528439172864UL, 14769502908867070793UL, 3476754806476653326UL, 9663999206884821105UL, #| 6864012991572870279UL, 2719468417766812445UL, 13735767778024137757UL, 7331676388138190150UL, #| 15110277136215905228UL, 118894811326561078UL, 6308935423749160781UL, 1857610629058673910UL, #| 15843686394045370811UL, 10951543581626859443UL, 3587431610669043023UL, 670469650389812154UL, #| 476209600999700306UL, 6589566024609793738UL, 8281611217869782149UL, 15129277549214352190UL, #| 13446421929377692845UL, 17071158676955966275UL, 7349330903428905191UL, 3277698994734830674UL, #| 14731635658592643043UL, 5477400073429632652UL, 67518392538487036UL, 11035168000757098093UL, #| 9797693702590129641UL, 14649582299731326424UL, 15236666389149272153UL, 16511980240231261314UL, #| 2249833951459307500UL, 13214955418772830438UL, 329963039908253864UL, 8574511220958401562UL, #| 4538345089129965474UL, 16353802882881726632UL, 8935276449126753317UL, 13532443277699696063UL, #| 8669346374187395779UL, 17810417737921607796UL, 3904677225590828551UL, 10264576476552345822UL, #| 3042606770072189440UL, 12878478126980245939UL, 17862138228081367377UL, 16992359172961651842UL, #| 17034107108697981338UL, 12909026467335450156UL, 2470441546010339704UL, 3634699771143106326UL, #| 366960336551226348UL, 5510841956427041079UL, 15461212383052875073UL, 16433279593065139848UL, #| 4486890193637877972UL, 14360905330534596440UL, 4449385520993789019UL, 3743094329222006520UL, #| 2212668117926313829UL, 4681723502265844963UL, 13296513799272088946UL, 2343616111600662093UL, #| 14717171566066041529UL, 11738831003851491807UL, 15851419960104864784UL, 8132762647638440149UL, #| 3464418631265929631UL, 340027485718840165UL, 8395791638092059350UL, 3109485649064359417UL, #| 10944349985020042736UL, 6522608726689095595UL, 17803052569896648610UL, 2064238649661354599UL, #| 4092763376312896325UL, 15988266335744638521UL, 16848187183754420180UL, 199841868197609864UL, #| 17491157950173501157UL, 12533485177359032661UL, 6254686503080376974UL, 5499127381395659705UL, #| 10487847042307388775UL, 12368654789669906974UL, 2361938659724380109UL, 8148818964487342298UL, #| 12717021730603072605UL, 15728257831000719154UL, 15823591063810279774UL, 6928887951986678348UL, #| 17959062744186568888UL, 16016655507227678734UL, 14898526437837544110UL, 16974466848830908932UL, #| 15320157178342639871UL, 8261903640164714632UL, 14435417271854760UL, 9182672404209601003UL, #| 5994285655773158181UL, 15654703508405219038UL, 16079243345868226083UL, 10784497444694088416UL, #| 4442318623009455690UL, 7578904045792755239UL, 4660917127407640248UL, 1338871040102977572UL, #| 7923968833761895669UL, 16874906449763725362UL, 6867431507591727612UL, 6311558572587278442UL, #| 11133241125491102835UL, 11738312930013082355UL, 11475845091361842759UL, 1643869946623606078UL, #| 10415771985971144045UL, 16177299554619494974UL, 539570561320537202UL, 14686903393511273001UL, #| 4445884513647149105UL, 5098090666552700373UL, 15054419504752089185UL, 3474469100259604016UL, #| 6290470378995655110UL, 12581245818984890955UL, 12787308417917333104UL, 15615073174539148765UL, #| 12984984669203863910UL, 5985056152809872019UL, 11524779172526084917UL, 12665285781050723551UL, #| 17258307941988319274UL, 1228317169172941352UL, 11160397433235040502UL, 9071341095814202162UL, #| 16466220084500004578UL, 17881879368693790694UL, 11823018491644357805UL, 16578188432210840351UL, #| 9406010430949605407UL, 11905115929048085077UL, 9944213925190004442UL, 7029678422186467496UL, #| 11401152387492259905UL, 10919895159361451251UL, 8495109194203518959UL, 16018667729961568082UL, #| 167446916071967039UL, 5832416432401633017UL, 2555624166217836526UL, 4693948454793001376UL, #| 15027938303073958689UL, 3816085682362256244UL, 3185235675206645589UL, 14811052307061536715UL, #| 16390566561388972206UL, 16262619695511054469UL, 18052593823409859051UL, 3945540604022845918UL, #| 15826009464703323776UL, 7719326347171925540UL, 9769778031520080067UL, 421859423473436660UL, #| 13367093898566883586UL, 6779889834239319169UL, 609582038820777224UL, 8614685872506396309UL, #| 4322299411370527537UL, 12846241946314463225UL, 7603764924892388925UL, 14478986206635481787UL, #| 12755177540574038518UL, 6194314060039108547UL, 7432498317049243916UL, 13744344095303706494UL, #| 4564573594452194471UL, 15206391374377392170UL, 14985029622013689232UL, 14328768324291300885UL, #| 10654090591156151429UL, 7338671807663089189UL, 16334907285225846266UL, 7423398075744368270UL, #| 13908293662617472937UL, 17175512688958868014UL, 7864028190390018941UL, 13126986956610526127UL, #| 7926473773501694475UL, 1941817884837167576UL, 15856689629067382306UL, 11177334980354607906UL, #| 7146885710676518584UL, 15983324774902192370UL, 17386093453964105449UL, 4150817240659351930UL, #| 7715942048190956297UL, 7276773301104081815UL, 13271959532491042945UL, 1194118668544183835UL, #| 17605071903565571062UL, 8948583740938417863UL, 3864418170274807074UL, 3699237212540510096UL, #| 14714003198217388528UL, 14269453830925281739UL, 8957047989018367339UL, 12402048382093370001UL, #| 11758047802384768757UL, 7093460309329455699UL, 384408371497488372UL, 1458858056370266940UL, #| 15774153359596962328UL, 5577985376535770293UL, 3965786813088619889UL, 17835800480481320920UL, #| 32994991092960231UL, 17146972595756459521UL, 12264557860820767038UL, 13718959782553074566UL, #| 1372337231943282583UL, 15958043944784669526UL, 17520298198669188203UL, 3031291504644241637UL, #| 6514984797562383624UL, 4345071177348538448UL, 3359260195018829989UL, 2607793539626362761UL, #| 16792663172613334423UL, 9898393582456908268UL, 2786478731415243607UL, 12029113901756054096UL, #| 3691479334576095829UL, 11929280456476427793UL, 18327972477027512052UL, 254886074006853656UL, #| 2927328918014182935UL, 4439939690082200099UL, 5969478689443458641UL, 14369317615642310767UL, #| 17764732325494572140UL, 10115938472474762880UL, 369466901724782737UL, 2269989694701338999UL, #| 1231466417883291608UL, 4918841702239877720UL, 13883670878602349637UL, 11470126477371023265UL, #| 17128636052794644986UL, 205335811880395712UL, 12443170494233065292UL, 15986026963143729439UL, #| ] #| assert_eq(res, expected) #|} ), }, ) ///| let moonbitlang_core_rational_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/rational", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/double": moonbitlang_core_double_module, "moonbitlang/core/int64": moonbitlang_core_int64_module, "moonbitlang/core/quickcheck": moonbitlang_core_quickcheck_module, }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/builtin", #| "moonbitlang/core/double", #| "moonbitlang/core/int64", #| "moonbitlang/core/quickcheck" #| ] #|} ), "rational.mbt": ( #|#deprecated("Use @rational in module moonbitlang/x instead. Note that you need to rename Rational to Rational64.") #|#coverage.skip #|struct T { #| numerator : Int64 #| denominator : Int64 #|} #|fn gcd(a : Int64, b : Int64) -> Int64 { #| for a = a, b = b { #| if b == 0L { #| break a #| } #| continue b, a % b #| } #|} #|#deprecated("Use @rational in module moonbitlang/x instead. Note that you need to rename Rational to Rational64.") #|#coverage.skip #|pub fn new(numerator : Int64, denominator : Int64) -> T? { #| if denominator == 0L { #| None #| } else { #| let sign = if (numerator < 0L && denominator < 0L) || #| (numerator > 0L && denominator > 0L) { #| 1L #| } else { #| -1L #| } #| let numerator = numerator.abs() #| let denominator = denominator.abs() #| let gcd = gcd(numerator, denominator) #| Some({ numerator: sign * numerator / gcd, denominator: denominator / gcd }) #| } #|} #|fn new_unchecked(numerator : Int64, denominator : Int64) -> T { #| let gcd = gcd(numerator.abs(), denominator) #| { numerator: numerator / gcd, denominator: denominator / gcd } #|} #|#coverage.skip #|pub impl Add for T with op_add(self : T, other : T) -> T { #| new_unchecked( #| self.numerator * other.denominator + other.numerator * self.denominator, #| self.denominator * other.denominator, #| ) #|} #|#coverage.skip #|pub impl Sub for T with op_sub(self : T, other : T) -> T { #| new_unchecked( #| self.numerator * other.denominator - other.numerator * self.denominator, #| self.denominator * other.denominator, #| ) #|} #|#coverage.skip #|pub impl Mul for T with op_mul(self : T, other : T) -> T { #| new_unchecked( #| self.numerator * other.numerator, #| self.denominator * other.denominator, #| ) #|} #|#coverage.skip #|pub impl Div for T with op_div(self : T, other : T) -> T { #| if other.numerator < 0L { #| new_unchecked( #| self.numerator * -other.denominator, #| self.denominator * -other.numerator, #| ) #| } else { #| new_unchecked( #| self.numerator * other.denominator, #| self.denominator * other.numerator, #| ) #| } #|} #|#deprecated("Use @rational in module moonbitlang/x instead. Note that you need to rename Rational to Rational64.") #|#coverage.skip #|pub fn reciprocal(self : T) -> T { #| if self.numerator < 0L { #| new_unchecked(-self.denominator, -self.numerator) #| } else { #| new_unchecked(self.denominator, self.numerator) #| } #|} #|#deprecated("Use @rational in module moonbitlang/x instead. Note that you need to rename Rational to Rational64.") #|#coverage.skip #|pub fn T::neg(self : T) -> T { #| new_unchecked(-self.numerator, self.denominator) #|} #|#deprecated("Use @rational in module moonbitlang/x instead. Note that you need to rename Rational to Rational64.") #|#coverage.skip #|pub fn T::abs(self : T) -> T { #| new_unchecked(self.numerator.abs(), self.denominator) #|} #|#coverage.skip #|pub impl Eq for T with op_equal(self : T, other : T) -> Bool { #| self.numerator * other.denominator == other.numerator * self.denominator #|} #|#coverage.skip #|pub impl Compare for T with compare(self : T, other : T) -> Int { #| let left = self.numerator * other.denominator #| let right = other.numerator * self.denominator #| left.compare(right) #|} #|#deprecated("Use @rational in module moonbitlang/x instead. Note that you need to rename Rational to Rational64.") #|#coverage.skip #|pub fn to_double(self : T) -> Double { #| self.numerator.to_double() / self.denominator.to_double() #|} #|fn[T] nan_error() -> T raise RationalError { #| raise RationalError("Rational::from_double: cannot convert NaN") #|} #|fn[T] overflow_error() -> T raise RationalError { #| raise RationalError("Rational::from_double: overflow") #|} #|#deprecated("Use @rational in module moonbitlang/x instead. Note that you need to rename Rational to Rational64.") #|#coverage.skip #|pub(all) suberror RationalError String derive(Show, ToJson(style="flat")) #|#coverage.skip #|pub impl Eq for RationalError with op_equal( #| self : RationalError, #| other : RationalError, #|) -> Bool { #| match (self, other) { #| (RationalError(e1), RationalError(e2)) => e1 == e2 #| } #|} #|#deprecated("Use @rational in module moonbitlang/x instead. Note that you need to rename Rational to Rational64.") #|#coverage.skip #|pub fn from_double(value : Double) -> T raise RationalError { #| if value.is_nan() { #| nan_error() #| } #| let sign = if value < 0.0 { -1L } else { 1L } #| let value = value.abs() #| let mut q = value #| let mut n0 = 0L #| let mut d0 = 1L #| let mut n1 = 1L #| let mut d1 = 0L #| let t_max = @int64.max_value #| let t_max_f = t_max.to_double() #| let epsilon = 1.0 / t_max_f #| let max_iteration = 30 #| let max_error = 10.0e-20 #| if q > t_max_f { #| overflow_error() #| } #| for i in 0..= -9223372036854775808.0 && q < 9223372036854775808.0) { #| break // overflow #| } #| let a = q.to_int64() #| let a_f = a.to_double() #| let f = q - a_f #| if !(a == 0L) && #| ( #| n1 > t_max / a || #| d1 > t_max / a || #| a * n1 > t_max - n0 || #| a * d1 > t_max - d0 #| ) { #| break #| } #| let n = a * n1 + n0 #| let d = a * d1 + d0 #| n0 = n1 #| d0 = d1 #| n1 = n #| d1 = d #| let g = gcd(n1, d1) #| if !(g == 0L) { #| n1 = n1 / g #| d1 = d1 / g #| } #| let (n_f, d_f) = (n.to_double(), d.to_double()) #| if (n_f / d_f - value).abs() < max_error { #| break #| } #| if f < epsilon { #| break #| } #| q = 1.0 / f #| } #| if d1 == 0L { #| overflow_error() #| } #| match new(sign * n1, d1) { #| Some(r) => r #| None => abort("Impossible to reach") #| } #|} #|#deprecated("Use @rational in module moonbitlang/x instead. Note that you need to rename Rational to Rational64.") #|#coverage.skip #|pub fn T::ceil(self : T) -> Int64 { #| let sign = if self.numerator < 0L { -1L } else { 1L } #| let quotient = self.numerator / self.denominator #| if self.numerator % self.denominator == 0L { #| quotient #| } else { #| quotient + (1L + sign) / 2L #| } #|} #|#deprecated("Use @rational in module moonbitlang/x instead. Note that you need to rename Rational to Rational64.") #|#coverage.skip #|pub fn T::floor(self : T) -> Int64 { #| let sign = if self.numerator < 0L { -1L } else { 1L } #| let quotient = self.numerator / self.denominator #| if self.numerator % self.denominator == 0L { #| quotient #| } else { #| quotient + (-1L + sign) / 2L #| } #|} #|#deprecated("Use @rational in module moonbitlang/x instead. Note that you need to rename Rational to Rational64.") #|#coverage.skip #|pub fn T::trunc(self : T) -> Int64 { #| if self.numerator < 0L { #| -(-self.numerator / self.denominator) #| } else { #| self.numerator / self.denominator #| } #|} #|#deprecated("Use @rational in module moonbitlang/x instead. Note that you need to rename Rational to Rational64.") #|#coverage.skip #|pub fn fract(self : T) -> T { #| new_unchecked(self.numerator % self.denominator, self.denominator) #|} #|#coverage.skip #|pub impl Show for T with output(self, logger) { #| if self.numerator == 0L { #| logger.write_char('0') #| } else if self.denominator == 1L { #| self.numerator.output(logger) #| } else { #| self.numerator.output(logger) #| logger.write_char('/') #| self.denominator.output(logger) #| } #|} #|#coverage.skip #|pub impl @quickcheck.Arbitrary for T with arbitrary(size, rs) { #| let numerator : Int64 = @quickcheck.Arbitrary::arbitrary(size, rs) #| let denominator : Int64 = { #| let d : Int64 = @quickcheck.Arbitrary::arbitrary(size, rs) #| if d <= 0 { #| -d + 1 #| } else { #| d #| } #| } #| new_unchecked(numerator, denominator) #|} #|#deprecated("Use @rational in module moonbitlang/x instead. Note that you need to rename Rational to Rational64.") #|#coverage.skip #|pub fn is_integer(self : T) -> Bool { #| self.denominator == 1L #|} #|#deprecated("Use @rational in module moonbitlang/x instead. Note that you need to rename Rational to Rational64.") #|#coverage.skip #|pub fnalias T::(neg, abs, ceil, floor, trunc) ), }, ) ///| let moonbitlang_core_ref_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/ref", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/quickcheck": moonbitlang_core_quickcheck_module, }, files={ "moon.pkg.json": ( #|{ #| "import": ["moonbitlang/core/builtin", "moonbitlang/core/quickcheck"] #|} ), "ref.mbt": ( #|pub fn[T] Ref::new(x : T) -> Ref[T] { #| { val: x } #|} #|test "to_string" { #| inspect(new(3), content="{val: 3}") #|} #|pub fn[T] new(x : T) -> Ref[T] { #| { val: x } #|} #|pub fn[T, R] map(self : Ref[T], f : (T) -> R raise?) -> Ref[R] raise? { #| { val: f(self.val) } #|} #|pub fn[T, R] protect(self : Ref[T], a : T, f : () -> R raise?) -> R raise? { #| let old = self.val #| self.val = a #| try f() catch { #| err => { #| self.val = old #| raise err #| } #| } noraise { #| r => { #| self.val = old #| r #| } #| } #|} #|pub fn[T] Ref::swap(self : Ref[T], that : Ref[T]) -> Unit { #| let tmp = self.val #| self.val = that.val #| that.val = tmp #|} #|pub fnalias Ref::swap #|test "swap" { #| let x = new(1) #| let y = new(2) #| swap(x, y) #| inspect(x.val, content="2") #| inspect(y.val, content="1") #|} #|pub fn[T] update(self : Ref[T], f : (T) -> T raise?) -> Unit raise? { #| self.val = f(self.val) #|} #|test "decr" { #| let a = new(1) #| a.val -= 1 #| inspect(a.val, content="0") #| a.val -= 5 #| inspect(a.val, content="-5") #|} #|test "incr" { #| let a = new(1) #| a.val += 1 #| inspect(a.val, content="2") #| a.val += 5 #| inspect(a.val, content="7") #|} #|pub impl[X : @quickcheck.Arbitrary] @quickcheck.Arbitrary for Ref[X] with arbitrary( #| size, #| rs, #|) { #| new(X::arbitrary(size, rs)) #|} ), }, ) ///| let moonbitlang_core_result_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/result", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/quickcheck": moonbitlang_core_quickcheck_module, }, files={ "moon.pkg.json": ( #|{ #| "import": ["moonbitlang/core/builtin", "moonbitlang/core/quickcheck"], #| "targets": { #| "panic_test.mbt": ["not", "native", "llvm"] #| } #|} ), "deprecated.mbt": ( #|#deprecated("use try? instead") #|#coverage.skip #|pub fn[T, E : Error] wrap0(f~ : () -> T raise E) -> Result[T, E] { #| try f() |> Ok catch { #| e => Err(e) #| } #|} #|#deprecated("use try? instead") #|#coverage.skip #|pub fn[T, A, E : Error] wrap1(f~ : (A) -> T raise E, a : A) -> Result[T, E] { #| try f(a) |> Ok catch { #| e => Err(e) #| } #|} #|#deprecated("use try? instead") #|#coverage.skip #|pub fn[T, A, B, E : Error] wrap2( #| f~ : (A, B) -> T raise E, #| a : A, #| b : B, #|) -> Result[T, E] { #| try f(a, b) |> Ok catch { #| e => Err(e) #| } #|} ), "result.mbt": ( #|pub fn[T, E, U] map(self : Result[T, E], f : (T) -> U) -> Result[U, E] { #| match self { #| Ok(value) => Ok(f(value)) #| Err(err) => Err(err) #| } #|} #|test "map" { #| let x : Result[Int, Unit] = Ok(6) #| let y = x.map((v : Int) => v * 7) #| let z : Result[Int, Int] = Err(3) #| let w = z.map((v : Int) => v * 7) #| assert_eq(y, Ok(42)) #| assert_eq(w, Err(3)) #|} #|pub fn[T, E, F] map_err(self : Result[T, E], f : (E) -> F) -> Result[T, F] { #| match self { #| Ok(value) => Ok(value) #| Err(err) => Err(f(err)) #| } #|} #|test "map_err" { #| let x : Result[Int, String] = Err("error") #| let y = x.map_err((v : String) => v + "!") #| let z : Result[Int, Int] = Ok(6) #| let w = z.map_err((v : Int) => v + 6) #| assert_eq(y, Err("error!")) #| assert_eq(w, Ok(6)) #|} #|pub fn[T, E] err(value : E) -> Result[T, E] { #| Err(value) #|} #|test "err" { #| let x : Result[Int, String] = err("error") #| assert_eq(x, Err("error")) #|} #|pub fn[T, E] ok(value : T) -> Result[T, E] { #| Ok(value) #|} #|test "ok" { #| let x : Result[String, Unit] = ok("yes") #| assert_eq(x, Ok("yes")) #|} #|pub fn[T, E] is_ok(self : Result[T, E]) -> Bool { #| self is Ok(_) #|} #|test "is_ok" { #| let x : Result[Int, String] = Ok(6) #| let y : Result[Int, String] = Err("error") #| assert_eq(x.is_ok(), true) #| assert_eq(y.is_ok(), false) #|} #|pub fn[T, E] is_err(self : Result[T, E]) -> Bool { #| self is Err(_) #|} #|test "is_err" { #| let x : Result[Int, String] = Ok(6) #| let y : Result[Int, String] = Err("error") #| assert_eq(x.is_err(), false) #| assert_eq(y.is_err(), true) #|} #|pub fn[T, E] or(self : Result[T, E], default : T) -> T { #| match self { #| Ok(value) => value #| Err(_) => default #| } #|} #|test "or" { #| let x : Result[Int, String] = Ok(6) #| let y : Result[Int, String] = Err("error") #| let z = x.or(0) #| let w = y.or(0) #| assert_eq(z, 6) #| assert_eq(w, 0) #|} #|pub fn[T, E] or_else(self : Result[T, E], default : () -> T) -> T { #| match self { #| Ok(value) => value #| Err(_) => default() #| } #|} #|test "or_else" { #| let x : Result[Int, String] = Ok(6) #| let y : Result[Int, String] = Err("error") #| let z = x.or_else(() => 0) #| let w = y.or_else(() => 0) #| assert_eq(z, 6) #| assert_eq(w, 0) #|} #|pub fn[T, E] flatten(self : Result[Result[T, E], E]) -> Result[T, E] { #| match self { #| Ok(value) => value #| Err(err) => Err(err) #| } #|} #|test "flatten" { #| let x : Result[Result[Int, String], String] = Ok(Ok(6)) #| let y = x.flatten() #| let z : Result[Result[Int, String], String] = Err("error") #| let w = z.flatten() #| assert_eq(y, Ok(6)) #| assert_eq(w, Err("error")) #|} #|pub fn[T, E, U] bind( #| self : Result[T, E], #| g : (T) -> Result[U, E], #|) -> Result[U, E] { #| match self { #| Ok(value) => g(value) #| Err(err) => Err(err) #| } #|} #|test "bind" { #| let x : Result[Int, String] = Ok(6) #| let y = x.bind((v : Int) => Ok(v * 7)) #| assert_eq(y, Ok(42)) #|} #|pub fn[T, E, V] fold(self : Result[T, E], ok : (T) -> V, err : (E) -> V) -> V { #| match self { #| Ok(value) => ok(value) #| Err(error) => err(error) #| } #|} #|test "fold" { #| let x : Result[Int, String] = Ok(6) #| let y = x.fold((v : Int) => v * 7, (_e : String) => 0) #| let z : Result[Int, String] = Err("error") #| let w = z.fold((v : Int) => v * 7, (_e : String) => 0) #| assert_eq(y, 42) #| assert_eq(w, 0) #|} #|pub fn[T, E] to_option(self : Result[T, E]) -> T? { #| match self { #| Ok(value) => Some(value) #| Err(_) => None #| } #|} #|test "to_option" { #| let x : Result[Int, String] = Ok(6) #| let y : Result[Int, String] = Err("error") #| let z = x.to_option() #| let w = y.to_option() #| assert_eq(z, Some(6)) #| assert_eq(w, None) #|} #|pub impl[T : Compare, E : Compare] Compare for Result[T, E] with compare( #| self : Result[T, E], #| other : Result[T, E], #|) -> Int { #| match (self, other) { #| (Ok(x), Ok(y)) => x.compare(y) #| (Ok(_), Err(_)) => -1 #| (Err(_), Ok(_)) => 1 #| (Err(x), Err(y)) => x.compare(y) #| } #|} #|test "compare" { #| let ok1 = Result::Ok(1) #| let ok2 = Result::Ok(2) #| let err1 = Result::Err(1) #| let err2 = Result::Err(2) #| assert_eq(0, ok1.compare(ok1)) #| assert_eq(0, err2.compare(Result::Err(2))) #| assert_eq(-1, ok1.compare(ok2)) #| assert_eq(1, ok2.compare(ok1)) #| assert_eq(-1, err1.compare(err2)) #| assert_eq(1, err2.compare(err1)) #| assert_eq(-1, ok2.compare(err1)) #| assert_eq(1, err1.compare(ok2)) #|} #|pub fn[T, E] unwrap(self : Result[T, E]) -> T { #| match self { #| Ok(x) => x #| Err(_) => abort("called `Result::unwrap()` on an `Err` value") #| } #|} #|pub fn[T, E] unwrap_err(self : Result[T, E]) -> E { #| match self { #| Ok(_) => abort("called `Result::unwrap_err()` on an `Ok` value") #| Err(e) => e #| } #|} #|test "show" { #| let ok : Result[_, String] = Ok("hello") #| inspect( #| ok, #| content=( #| #|Ok("hello") #| ), #| ) #| let err : Result[String, _] = Err("world") #| inspect( #| err, #| content=( #| #|Err("world") #| ), #| ) #|} #|pub fn[T, E : Error] unwrap_or_error(self : Result[T, E]) -> T raise E { #| match self { #| Ok(x) => x #| Err(e) => raise e #| } #|} #|test "unwrap exn" { #| (try #| (Err(Failure("This is serious")) : Result[Unit, Failure]).unwrap_or_error() #| |> Ok #| catch { #| Failure(msg) => Err(msg) #| }) #| |> inspect( #| content=( #| #|Err("This is serious") #| ), #| ) #|} #|pub impl[T : @quickcheck.Arbitrary, E : @quickcheck.Arbitrary] @quickcheck.Arbitrary for Result[ #| T, #| E, #|] with arbitrary(size, rs) { #| if @quickcheck.Arbitrary::arbitrary(size, rs) { #| Ok(T::arbitrary(size, rs)) #| } else { #| Err(E::arbitrary(size, rs)) #| } #|} ), }, ) ///| let moonbitlang_core_set_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/set", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/int": moonbitlang_core_int_module, }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/builtin", #| "moonbitlang/core/int" #| ], #| "test-import": [ #| "moonbitlang/core/json", #| "moonbitlang/core/array" #| ] #|} ), "deprecated.mbt": ( #|#deprecated("Use `add` instead.") #|#coverage.skip #|pub fn[K : Hash + Eq] insert(self : Set[K], key : K) -> Unit { #| self.add(key) #|} ), "grow_heuristic.mbt": ( #|fn calc_grow_threshold(capacity : Int) -> Int { #| capacity * 13 / 16 #|} ), "linked_hash_set.mbt": ( #|priv struct Entry[K] { #| mut prev : Int #| mut next : Entry[K]? #| mut psl : Int #| hash : Int #| key : K #|} derive(Show) #|struct Set[K] { #| mut entries : FixedArray[Entry[K]?] #| mut size : Int // active keys count #| mut capacity : Int // current capacity #| mut capacity_mask : Int // capacity_mask = capacity - 1, used to find idx #| mut grow_at : Int // threshold that triggers grow #| mut head : Entry[K]? // head of linked list #| mut tail : Int // tail of linked list #|} #|pub fn[K] Set::new(capacity? : Int = 8) -> Set[K] { #| let capacity = capacity.next_power_of_two() #| { #| size: 0, #| capacity, #| capacity_mask: capacity - 1, #| grow_at: calc_grow_threshold(capacity), #| entries: FixedArray::make(capacity, None), #| head: None, #| tail: -1, #| } #|} #|pub fn[K : Hash + Eq] Set::from_array(arr : Array[K]) -> Set[K] { #| let m = Set::new(capacity=arr.length()) #| arr.each(e => m.add(e)) #| m #|} #|pub fn[K : Hash + Eq] add(self : Set[K], key : K) -> Unit { #| self.add_with_hash(key, key.hash()) #|} #|fn[K : Eq] add_with_hash(self : Set[K], key : K, hash : Int) -> Unit { #| if self.size >= self.grow_at { #| self.grow() #| } #| let (idx, psl) = for psl = 0, idx = hash & self.capacity_mask { #| match self.entries[idx] { #| None => break (idx, psl) #| Some(curr_entry) => { #| if curr_entry.hash == hash && curr_entry.key == key { #| return #| } #| if psl > curr_entry.psl { #| self.push_away(idx, curr_entry) #| break (idx, psl) #| } #| continue psl + 1, (idx + 1) & self.capacity_mask #| } #| } #| } #| let entry = { prev: self.tail, next: None, psl, key, hash } #| self.add_entry_to_tail(idx, entry) #|} #|fn[K] push_away(self : Set[K], idx : Int, entry : Entry[K]) -> Unit { #| for psl = entry.psl + 1, idx = (idx + 1) & self.capacity_mask, entry = entry { #| match self.entries[idx] { #| None => { #| entry.psl = psl #| self.set_entry(entry, idx) #| break #| } #| Some(curr_entry) => #| if psl > curr_entry.psl { #| entry.psl = psl #| self.set_entry(entry, idx) #| continue curr_entry.psl + 1, #| (idx + 1) & self.capacity_mask, #| curr_entry #| } else { #| continue psl + 1, (idx + 1) & self.capacity_mask, entry #| } #| } #| } #|} #|fn[K] set_entry(self : Set[K], entry : Entry[K], new_idx : Int) -> Unit { #| self.entries[new_idx] = Some(entry) #| match entry.next { #| None => self.tail = new_idx #| Some(next) => next.prev = new_idx #| } #|} #|pub fn[K : Hash + Eq] add_and_check(self : Set[K], key : K) -> Bool { #| if self.size >= self.grow_at { #| self.grow() #| } #| let hash = key.hash() #| let (idx, psl, added) = for psl = 0, idx = hash & self.capacity_mask { #| match self.entries[idx] { #| None => break (idx, psl, true) #| Some(curr_entry) => { #| if curr_entry.hash == hash && curr_entry.key == key { #| break (idx, psl, false) #| } #| if psl > curr_entry.psl { #| self.push_away(idx, curr_entry) #| break (idx, psl, true) #| } #| continue psl + 1, (idx + 1) & self.capacity_mask #| } #| } #| } #| if added { #| let entry = { prev: self.tail, next: None, psl, key, hash } #| self.add_entry_to_tail(idx, entry) #| } #| added #|} #|pub fn[K : Hash + Eq] Set::contains(self : Set[K], key : K) -> Bool { #| let hash = key.hash() #| for i = 0, idx = hash & self.capacity_mask { #| guard self.entries[idx] is Some(entry) else { break false } #| if entry.hash == hash && entry.key == key { #| break true #| } #| if i > entry.psl { #| break false #| } #| continue i + 1, (idx + 1) & self.capacity_mask #| } #|} #|pub fn[K : Hash + Eq] remove(self : Set[K], key : K) -> Unit { #| let hash = key.hash() #| for i = 0, idx = hash & self.capacity_mask { #| guard self.entries[idx] is Some(entry) else { break } #| if entry.hash == hash && entry.key == key { #| self.remove_entry(entry) #| self.shift_back(idx) #| self.size -= 1 #| break #| } #| if i > entry.psl { #| break #| } #| continue i + 1, (idx + 1) & self.capacity_mask #| } #|} #|pub fn[K : Hash + Eq] remove_and_check(self : Set[K], key : K) -> Bool { #| let hash = key.hash() #| for i = 0, idx = hash & self.capacity_mask { #| guard self.entries[idx] is Some(entry) else { break false } #| if entry.hash == hash && entry.key == key { #| self.remove_entry(entry) #| self.shift_back(idx) #| self.size -= 1 #| break true #| } #| if i > entry.psl { #| break false #| } #| continue i + 1, (idx + 1) & self.capacity_mask #| } #|} #|fn[K] add_entry_to_tail(self : Set[K], idx : Int, entry : Entry[K]) -> Unit { #| match self.tail { #| -1 => self.head = Some(entry) #| tail => self.entries[tail].unwrap().next = Some(entry) #| } #| self.tail = idx #| self.entries[idx] = Some(entry) #| self.size += 1 #|} #|fn[K] remove_entry(self : Set[K], entry : Entry[K]) -> Unit { #| match entry.prev { #| -1 => self.head = entry.next #| idx => self.entries[idx].unwrap().next = entry.next #| } #| match entry.next { #| None => self.tail = entry.prev #| Some(next) => next.prev = entry.prev #| } #|} #|fn[K] shift_back(self : Set[K], idx : Int) -> Unit { #| let next = (idx + 1) & self.capacity_mask #| match self.entries[next] { #| None | Some({ psl: 0, .. }) => self.entries[idx] = None #| Some(entry) => { #| entry.psl -= 1 #| self.set_entry(entry, idx) #| self.shift_back(next) #| } #| } #|} #|fn[K : Eq] grow(self : Set[K]) -> Unit { #| let old_head = self.head #| let new_capacity = self.capacity << 1 #| self.entries = FixedArray::make(new_capacity, None) #| self.capacity = new_capacity #| self.capacity_mask = new_capacity - 1 #| self.grow_at = calc_grow_threshold(self.capacity) #| self.size = 0 #| self.head = None #| self.tail = -1 #| loop old_head { #| Some({ next, key, hash, .. }) => { #| self.add_with_hash(key, hash) #| continue next #| } #| None => break #| } #|} #|pub impl[K : Show] Show for Set[K] with output(self, logger) { #| logger.write_string("{") #| loop (0, self.head) { #| (_, None) => logger.write_string("}") #| (i, Some({ key, next, .. })) => { #| if i > 0 { #| logger.write_string(", ") #| } #| logger.write_object(key) #| continue (i + 1, next) #| } #| } #|} #|pub fn[K] size(self : Set[K]) -> Int { #| self.size #|} #|pub fn[K] capacity(self : Set[K]) -> Int { #| self.capacity #|} #|pub fn[K] is_empty(self : Set[K]) -> Bool { #| self.size == 0 #|} #|#locals(f) #|pub fn[K] each(self : Set[K], f : (K) -> Unit raise?) -> Unit raise? { #| loop self.head { #| Some({ key, next, .. }) => { #| f(key) #| continue next #| } #| None => break #| } #|} #|#locals(f) #|pub fn[K] eachi(self : Set[K], f : (Int, K) -> Unit raise?) -> Unit raise? { #| loop (0, self.head) { #| (i, Some({ key, next, .. })) => { #| f(i, key) #| continue (i + 1, next) #| } #| (_, None) => break #| } #|} #|pub fn[K] clear(self : Set[K]) -> Unit { #| self.entries.fill(None) #| self.size = 0 #| self.head = None #| self.tail = -1 #|} #|pub fn[K] iter(self : Set[K]) -> Iter[K] { #| Iter::new(yield_ => loop self.head { #| Some({ key, next, .. }) => { #| guard yield_(key) is IterContinue else { break IterEnd } #| continue next #| } #| None => break IterContinue #| }) #|} #|pub fn[K] to_array(self : Set[K]) -> Array[K] { #| let arr = Array::new(capacity=self.size) #| loop self.head { #| Some({ key, next, .. }) => { #| arr.push(key) #| continue next #| } #| None => break #| } #| arr #|} #|pub impl[K : Hash + Eq] Eq for Set[K] with op_equal(self, other) { #| guard self.size == other.size else { return false } #| for k in self { #| guard other.contains(k) else { return false } #| } else { #| true #| } #|} #|pub fn[K : Hash + Eq] Set::of(arr : FixedArray[K]) -> Set[K] { #| let length = arr.length() #| let m = Set::new(capacity=length) #| for i in 0.. Set[K] { #| let m = Set::new() #| for e in iter { #| m.add(e) #| } #| m #|} #|pub impl[K] Default for Set[K] with default() { #| Set::new() #|} #|pub fn[K] copy(self : Set[K]) -> Set[K] { #| let other = { #| capacity: self.capacity, #| entries: FixedArray::make(self.capacity, None), #| size: self.size, #| capacity_mask: self.capacity_mask, #| grow_at: self.grow_at, #| head: None, #| tail: self.tail, #| } #| if self.size == 0 { #| return other #| } #| guard self.entries[self.tail] is Some(last) #| loop (last, self.tail, None) { #| ({ prev, psl, hash, key, .. }, idx, next) => { #| let new_entry = { prev, next, psl, hash, key } #| other.entries[idx] = Some(new_entry) #| if prev != -1 { #| continue (self.entries[prev].unwrap(), prev, Some(new_entry)) #| } else { #| other.head = Some(new_entry) #| } #| } #| } #| other #|} #|pub fn[K : Hash + Eq] difference(self : Set[K], other : Set[K]) -> Set[K] { #| let m = Set::new() #| self.each(k => if !other.contains(k) { m.add(k) }) #| m #|} #|pub fn[K : Hash + Eq] symmetric_difference( #| self : Set[K], #| other : Set[K], #|) -> Set[K] { #| let m = Set::new() #| self.each(k => if !other.contains(k) { m.add(k) }) #| other.each(k => if !self.contains(k) { m.add(k) }) #| m #|} #|pub fn[K : Hash + Eq] union(self : Set[K], other : Set[K]) -> Set[K] { #| let m = Set::new() #| self.each(k => m.add(k)) #| other.each(k => m.add(k)) #| m #|} #|pub fn[K : Hash + Eq] intersection(self : Set[K], other : Set[K]) -> Set[K] { #| let m = Set::new() #| self.each(k => if other.contains(k) { m.add(k) }) #| m #|} #|pub impl[X : ToJson] ToJson for Set[X] with to_json(self) { #| let res = Array::new(capacity=self.size) #| for v in self { #| res.push(v.to_json()) #| } #| Json::array(res) #|} #|pub fn[K : Hash + Eq] is_disjoint(self : Set[K], other : Set[K]) -> Bool { #| if self.size() <= other.size() { #| for k in self { #| if other.contains(k) { #| return false #| } #| } #| } else { #| for k in other { #| if self.contains(k) { #| return false #| } #| } #| } #| true #|} #|pub fn[K : Hash + Eq] is_subset(self : Set[K], other : Set[K]) -> Bool { #| if self.size() <= other.size() { #| for k in self { #| if !other.contains(k) { #| return false #| } #| } #| true #| } else { #| false #| } #|} #|pub fn[K : Hash + Eq] is_superset(self : Set[K], other : Set[K]) -> Bool { #| other.is_subset(self) #|} #|pub impl[K : Hash + Eq] BitAnd for Set[K] with land(self, other) { #| self.intersection(other) #|} #|pub impl[K : Hash + Eq] BitOr for Set[K] with lor(self, other) { #| self.union(other) #|} #|pub impl[K : Hash + Eq] BitXOr for Set[K] with lxor(self, other) { #| self.symmetric_difference(other) #|} #|pub impl[K : Hash + Eq] Sub for Set[K] with op_sub(self, other) { #| self.difference(other) #|} #|pub fnalias Set::(new, from_array, from_iter, of) ), }, ) ///| let moonbitlang_core_sorted_map_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/sorted_map", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/option": moonbitlang_core_option_module, "moonbitlang/core/tuple": moonbitlang_core_tuple_module, "moonbitlang/core/quickcheck": moonbitlang_core_quickcheck_module, }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/builtin", #| "moonbitlang/core/option", #| "moonbitlang/core/tuple", #| "moonbitlang/core/quickcheck" #| ], #| "test-import": ["moonbitlang/core/array"] #|} ), "deprecated.mbt": ( #|#deprecated("Use @sorted_map.from_array instead") #|pub fn[K : Compare, V] of(entries : Array[(K, V)]) -> T[K, V] { #| let map = { root: None, size: 0 } #| entries.each(e => map.add(e.0, e.1)) #| map #|} #|#deprecated("Use `keys_as_iter` instead. `keys` will return `Iter[K]` instead of `Array[K]` in the future.") #|#coverage.skip #|pub fn[K, V] keys(self : T[K, V]) -> Array[K] { #| let keys = Array::new(capacity=self.size) #| self.each(fn(k, _v) { keys.push(k) }) #| keys #|} #|#deprecated("Use `values_as_iter` instead. `values` will return `Iter[V]` instead of `Array[V]` in the future.") #|#coverage.skip #|pub fn[K, V] values(self : T[K, V]) -> Array[V] { #| let values = Array::new(capacity=self.size) #| self.each(fn(_k, v) { values.push(v) }) #| values #|} ), "map.mbt": ( #|pub fn[K : Compare, V] op_set(self : T[K, V], key : K, value : V) -> Unit { #| self.add(key, value) #|} #|pub impl[K : Eq, V : Eq] Eq for T[K, V] with op_equal(self, other) { #| self.to_array() == other.to_array() #|} #|pub fn[K, V] new() -> T[K, V] { #| { root: None, size: 0 } #|} #|pub fn[K : Compare, V] from_array(entries : Array[(K, V)]) -> T[K, V] { #| let map = { root: None, size: 0 } #| entries.each(e => map.add(e.0, e.1)) #| map #|} #|pub fn[K : Compare, V] add(self : T[K, V], key : K, value : V) -> Unit { #| let (new_root, inserted) = add_node(self.root, key, value) #| if self.root != new_root { #| self.root = new_root #| } #| if inserted { #| self.size += 1 #| } #|} #|pub fn[K : Compare, V] remove(self : T[K, V], key : K) -> Unit { #| if self.root is Some(old_root) { #| let (new_root, deleted) = delete_node(old_root, key) #| if self.root != new_root { #| self.root = new_root #| } #| if deleted { #| self.size -= 1 #| } #| } #|} #|pub fn[K : Compare, V] get(self : T[K, V], key : K) -> V? { #| loop self.root { #| Some(node) => { #| let cmp = key.compare(node.key) #| if cmp == 0 { #| break Some(node.value) #| } else if cmp > 0 { #| continue node.right #| } else { #| continue node.left #| } #| } #| None => break None #| } #|} #|pub fn[K : Compare, V] op_get(self : T[K, V], key : K) -> V { #| loop self.root { #| Some(node) => { #| let cmp = key.compare(node.key) #| if cmp == 0 { #| break node.value #| } else if cmp > 0 { #| continue node.right #| } else { #| continue node.left #| } #| } #| None => panic() #| } #|} #|pub fn[K : Compare, V] contains(self : T[K, V], key : K) -> Bool { #| match self.get(key) { #| Some(_) => true #| None => false #| } #|} #|pub fn[K, V] is_empty(self : T[K, V]) -> Bool { #| self.size == 0 #|} #|pub fn[K, V] size(self : T[K, V]) -> Int { #| self.size #|} #|pub fn[K, V] clear(self : T[K, V]) -> Unit { #| self.root = None #| self.size = 0 #|} #|pub fn[K, V] each(self : T[K, V], f : (K, V) -> Unit raise?) -> Unit raise? { #| fn dfs(root : Node[K, V]?) -> Unit raise? { #| if root is Some(root) { #| dfs(root.left) #| f(root.key, root.value) #| dfs(root.right) #| } #| } #| dfs(self.root) #|} #|pub fn[K, V] eachi( #| self : T[K, V], #| f : (Int, K, V) -> Unit raise?, #|) -> Unit raise? { #| let mut i = 0 #| self.each((k, v) => { #| f(i, k, v) #| i = i + 1 #| }) #|} #|pub fn[K, V] keys_as_iter(self : T[K, V]) -> Iter[K] { #| Iter::new(fn(yield_) { #| fn go(x : Node[K, V]?) { #| match x { #| None => IterContinue #| Some({ left, right, key, .. }) => #| if go(left) is IterEnd { #| IterEnd #| } else if yield_(key) is IterEnd { #| IterEnd #| } else { #| go(right) #| } #| } #| } #| go(self.root) #| }) #|} #|pub fn[K, V] values_as_iter(self : T[K, V]) -> Iter[V] { #| Iter::new(fn(yield_) { #| fn go(x : Node[K, V]?) { #| match x { #| None => IterContinue #| Some({ left, right, value, .. }) => #| if go(left) is IterEnd { #| IterEnd #| } else if yield_(value) is IterEnd { #| IterEnd #| } else { #| go(right) #| } #| } #| } #| go(self.root) #| }) #|} #|pub fn[K, V] to_array(self : T[K, V]) -> Array[(K, V)] { #| let arr = Array::new(capacity=self.size) #| self.each((k, v) => arr.push((k, v))) #| arr #|} #|pub fn[K, V] iter(self : T[K, V]) -> Iter[(K, V)] { #| Iter::new(yield_ => { #| fn go(x : Node[K, V]?) { #| match x { #| None => IterContinue #| Some({ left, right, key, value, .. }) => #| if go(left) is IterEnd { #| IterEnd #| } else if yield_((key, value)) is IterEnd { #| IterEnd #| } else { #| go(right) #| } #| } #| } #| go(self.root) #| }) #|} #|pub fn[K, V] iter2(self : T[K, V]) -> Iter2[K, V] { #| Iter2::new(yield_ => { #| fn go(x : Node[K, V]?) { #| match x { #| None => IterContinue #| Some({ left, right, key, value, .. }) => #| if go(left) is IterEnd { #| IterEnd #| } else if yield_(key, value) is IterEnd { #| IterEnd #| } else { #| go(right) #| } #| } #| } #| go(self.root) #| }) #|} #|pub fn[K : Compare, V] from_iter(iter : Iter[(K, V)]) -> T[K, V] { #| let m = new() #| iter.each(e => m[e.0] = e.1) #| m #|} #|pub impl[K : @quickcheck.Arbitrary + Compare, V : @quickcheck.Arbitrary] @quickcheck.Arbitrary for T[ #| K, #| V, #|] with arbitrary(size, rs) { #| @quickcheck.Arbitrary::arbitrary(size, rs) |> from_iter #|} #|pub fn[K : Compare, V] range(self : T[K, V], low : K, high : K) -> Iter2[K, V] { #| Iter2::new(yield_ => { #| fn go(x : Node[K, V]?) { #| match x { #| None => IterContinue #| Some({ left, right, key, value, .. }) => { #| let cmp_key_low = key.compare(low) #| let cmp_key_high = key.compare(high) #| if cmp_key_low > 0 && go(left) is IterEnd { #| IterEnd #| } else if cmp_key_low >= 0 && #| cmp_key_high <= 0 && #| yield_(key, value) is IterEnd { #| IterEnd #| } else if cmp_key_high < 0 { #| go(right) #| } else { #| IterContinue #| } #| } #| } #| } #| go(self.root) #| }) #|} #|fn[K : Compare, V] replace_root_with_min( #| root : Node[K, V], #| node : Node[K, V], #|) -> Node[K, V]? { #| let (l, r) = (node.left, node.right) #| match l { #| None => { #| root.key = node.key #| root.value = node.value #| r #| } #| Some(ln) => { #| node.left = replace_root_with_min(root, ln) #| Some(balance(node)) #| } #| } #|} #|fn[K, V] update_height(self : Node[K, V]) -> Unit { #| self.height = 1 + max(height(self.left), height(self.right)) #|} #|fn[K, V] height_ge(x1 : Node[K, V]?, x2 : Node[K, V]?) -> Bool { #| match x2 { #| None => true #| Some(n2) => #| match x1 { #| None => false #| Some(n1) => n1.height >= n2.height #| } #| } #|} #|fn[K, V] balance(root : Node[K, V]) -> Node[K, V] { #| let (l, r) = (root.left, root.right) #| let (hl, hr) = (height(l), height(r)) #| let new_root = if hl > hr + 1 { #| let { left: ll, right: lr, .. } = l.unwrap() #| if height_ge(ll, lr) { #| rotate_r(root) #| } else { #| rotate_lr(root) #| } #| } else if hr > hl + 1 { #| let { left: rl, right: rr, .. } = r.unwrap() #| if height_ge(rr, rl) { #| rotate_l(root) #| } else { #| rotate_rl(root) #| } #| } else { #| root #| } #| new_root.update_height() #| new_root #|} #|fn[K, V] rotate_l(n : Node[K, V]) -> Node[K, V] { #| let r = n.right.unwrap() #| n.right = r.left #| r.left = Some(n) #| n.update_height() #| r.update_height() #| r #|} #|fn[K, V] rotate_r(n : Node[K, V]) -> Node[K, V] { #| let l = n.left.unwrap() #| n.left = l.right #| l.right = Some(n) #| n.update_height() #| l.update_height() #| l #|} #|fn[K, V] rotate_lr(n : Node[K, V]) -> Node[K, V] { #| let l = n.left.unwrap() #| let v = rotate_l(l) #| n.left = Some(v) #| rotate_r(n) #|} #|fn[K, V] rotate_rl(n : Node[K, V]) -> Node[K, V] { #| let r = n.right.unwrap() #| let v = rotate_r(r) #| n.right = Some(v) #| rotate_l(n) #|} #|fn[K : Compare, V] add_node( #| root : Node[K, V]?, #| key : K, #| value : V, #|) -> (Node[K, V]?, Bool) { #| match root { #| None => (Some(new_node(key, value)), true) #| Some(n) => #| if key == n.key { #| n.value = value #| (Some(n), false) #| } else { #| let (l, r) = (n.left, n.right) #| if key < n.key { #| let (nl, inserted) = add_node(l, key, value) #| n.left = nl #| (Some(balance(n)), inserted) #| } else { #| let (nr, inserted) = add_node(r, key, value) #| n.right = nr #| (Some(balance(n)), inserted) #| } #| } #| } #|} #|fn[K : Compare, V] delete_node( #| root : Node[K, V], #| key : K, #|) -> (Node[K, V]?, Bool) { #| if key == root.key { #| let (l, r) = (root.left, root.right) #| let n = match (l, r) { #| (Some(_), Some(nr)) => { #| root.right = replace_root_with_min(root, nr) #| Some(balance(root)) #| } #| (None, Some(_)) => r #| (Some(_), None) | (None, None) => l #| } #| (n, true) #| } else if key < root.key { #| match root.left { #| None => (Some(root), false) #| Some(l) => { #| let (nl, deleted) = delete_node(l, key) #| root.left = nl #| (Some(balance(root)), deleted) #| } #| } #| } else { #| match root.right { #| None => (Some(root), false) #| Some(r) => { #| let (nr, deleted) = delete_node(r, key) #| root.right = nr #| (Some(balance(root)), deleted) #| } #| } #| } #|} #|test "new" { #| let map : T[Int, String] = new() #| inspect(map.debug_tree(), content="_") #| inspect(map.size(), content="0") #|} #|test "of" { #| let map = from_array([(3, "c"), (2, "b"), (1, "a")]) #| inspect(map.debug_tree(), content="([2]2,b,([1]1,a,_,_),([1]3,c,_,_))") #| inspect(map.size(), content="3") #|} #|test "add1" { #| let map = new() #| map.add(6, "a") #| map.add(5, "b") #| map.add(4, "c") #| map.add(3, "d") #| map.add(2, "e") #| map.add(1, "f") #| inspect( #| map.debug_tree(), #| content="([3]3,d,([2]2,e,([1]1,f,_,_),_),([2]5,b,([1]4,c,_,_),([1]6,a,_,_)))", #| ) #| inspect(map.size(), content="6") #|} #|test "add2" { #| let map = new() #| map.add(1, "a") #| map.add(2, "b") #| map.add(3, "c") #| map.add(4, "d") #| map.add(5, "e") #| map.add(6, "f") #| inspect( #| map.debug_tree(), #| content="([3]4,d,([2]2,b,([1]1,a,_,_),([1]3,c,_,_)),([2]5,e,_,([1]6,f,_,_)))", #| ) #| inspect(map.size(), content="6") #|} #|test "add3" { #| let map = new() #| map.add(4, "a") #| map.add(1, "b") #| map.add(3, "c") #| map.add(2, "d") #| inspect( #| map.debug_tree(), #| content="([3]3,c,([2]1,b,_,([1]2,d,_,_)),([1]4,a,_,_))", #| ) #|} #|test "add4" { #| let map = new() #| map.add(1, "a") #| map.add(4, "b") #| map.add(2, "c") #| map.add(3, "d") #| inspect( #| map.debug_tree(), #| content="([3]2,c,([1]1,a,_,_),([2]4,b,([1]3,d,_,_),_))", #| ) #|} #|test "add duplicate key" { #| let map = from_array([(3, "c"), (2, "b"), (1, "a")]) #| inspect(map.debug_tree(), content="([2]2,b,([1]1,a,_,_),([1]3,c,_,_))") #| map.add(1, "x") #| inspect(map.debug_tree(), content="([2]2,b,([1]1,x,_,_),([1]3,c,_,_))") #|} #|test "remove" { #| let map = from_array([ #| (1, "a"), #| (2, "b"), #| (3, "c"), #| (4, "d"), #| (5, "e"), #| (6, "f"), #| (7, "g"), #| (8, "h"), #| ]) #| inspect( #| map.debug_tree(), #| content="([4]4,d,([2]2,b,([1]1,a,_,_),([1]3,c,_,_)),([3]6,f,([1]5,e,_,_),([2]7,g,_,([1]8,h,_,_))))", #| ) #| inspect(map.size(), content="8") #| map.remove(6) #| inspect( #| map.debug_tree(), #| content="([3]4,d,([2]2,b,([1]1,a,_,_),([1]3,c,_,_)),([2]7,g,([1]5,e,_,_),([1]8,h,_,_)))", #| ) #| inspect(map.size(), content="7") #| map.remove(4) #| inspect( #| map.debug_tree(), #| content="([3]5,e,([2]2,b,([1]1,a,_,_),([1]3,c,_,_)),([2]7,g,_,([1]8,h,_,_)))", #| ) #| inspect(map.size(), content="6") #| map.remove(2) #| inspect( #| map.debug_tree(), #| content="([3]5,e,([2]3,c,([1]1,a,_,_),_),([2]7,g,_,([1]8,h,_,_)))", #| ) #| inspect(map.size(), content="5") #| map.remove(3) #| inspect( #| map.debug_tree(), #| content="([3]5,e,([1]1,a,_,_),([2]7,g,_,([1]8,h,_,_)))", #| ) #| inspect(map.size(), content="4") #| map.remove(5) #| inspect(map.debug_tree(), content="([2]7,g,([1]1,a,_,_),([1]8,h,_,_))") #| inspect(map.size(), content="3") #| map.remove(7) #| inspect(map.debug_tree(), content="([2]8,h,([1]1,a,_,_),_)") #| inspect(map.size(), content="2") #| map.remove(8) #| inspect(map.debug_tree(), content="([1]1,a,_,_)") #| inspect(map.size(), content="1") #| map.remove(1) #| inspect(map.debug_tree(), content="_") #| inspect(map.size, content="0") #|} #|test "op_set" { #| let map = new() #| map[1] = "a" #| map[2] = "b" #| map[3] = "c" #| inspect(map.debug_tree(), content="([2]2,b,([1]1,a,_,_),([1]3,c,_,_))") #|} #|test "clear" { #| let map = from_array([(3, "c"), (2, "b"), (1, "a")]) #| map.clear() #| inspect(map.debug_tree(), content="_") #| inspect(map.size(), content="0") #|} #|pub impl[K, V] Default for T[K, V] with default() { #| new() #|} ), "types.mbt": ( #|priv struct Node[K, V] { #| mut key : K #| mut value : V #| mut left : Node[K, V]? #| mut right : Node[K, V]? #| mut height : Int #|} #|struct T[K, V] { #| mut root : Node[K, V]? #| mut size : Int #|} ), "utils.mbt": ( #|fn[K, V] new_node(key : K, value : V) -> Node[K, V] { #| { key, value, left: None, right: None, height: 1 } #|} #|impl[K : Eq, V] Eq for Node[K, V] with op_equal(self, other) { #| self.key == other.key #|} #|fn max(x : Int, y : Int) -> Int { #| if x > y { #| x #| } else { #| y #| } #|} #|fn[K, V] height(node : Node[K, V]?) -> Int { #| match node { #| None => 0 #| Some(n) => n.height #| } #|} #|fn[K : Show, V : Show] debug_node(self : Node[K, V]) -> String { #| let l = match self.left { #| Some(left) => left.debug_node() #| None => "_" #| } #| let r = match self.right { #| Some(right) => right.debug_node() #| None => "_" #| } #| "([\{self.height}]\{self.key},\{self.value},\{l},\{r})" #|} #|fn[K : Show, V : Show] debug_tree(self : T[K, V]) -> String { #| match self.root { #| Some(root) => root.debug_node() #| None => "_" #| } #|} #|pub impl[K : Show, V : Show] Show for T[K, V] with output(self, logger) { #| logger.write_iter(self.iter(), prefix="@sorted_map.of([", suffix="])") #|} ), }, ) ///| let moonbitlang_core_sorted_set_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/sorted_set", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/option": moonbitlang_core_option_module, "moonbitlang/core/quickcheck": moonbitlang_core_quickcheck_module, }, files={ "moon.pkg.json": ( #|{ #| "import": ["moonbitlang/core/builtin", "moonbitlang/core/option", "moonbitlang/core/quickcheck"], #| "test-import": ["moonbitlang/core/array"] #|} ), "deprecated.mbt": ( #|#deprecated("use `@sorted_set.from_iter` instead") #|#coverage.skip #|pub fn[V : Compare] T::from_iter(iter : Iter[V]) -> T[V] { #| from_iter(iter) #|} #|#deprecated("Use @sorted_set.from_array instead") #|pub fn[V : Compare] of(array : Array[V]) -> T[V] { #| let set = new() #| for i in 0.. T[V] { #| self.copy() #|} #|#deprecated("Use `difference` instead") #|#coverage.skip #|pub fn[V : Compare] diff(self : T[V], src : T[V]) -> T[V] { #| let ret = new() #| self.each(x => if !src.contains(x) { ret.add(x) }) #| ret #|} #|#deprecated("Use `intersection` instead") #|#coverage.skip #|pub fn[V : Compare] intersect(self : T[V], src : T[V]) -> T[V] { #| self.intersection(src) #|} ), "set.mbt": ( #|pub fn[V] new() -> T[V] { #| { root: None, size: 0 } #|} #|pub fn[V] singleton(value : V) -> T[V] { #| { root: Some({ value, left: None, right: None, height: 1 }), size: 1 } #|} #|pub fn[V : Compare] from_array(array : Array[V]) -> T[V] { #| let set = new() #| for i in 0.. T[V] { #| match self.root { #| None => new() #| Some(_) => { root: copy_tree(self.root), size: self.size } #| } #|} #|fn[V] copy_tree(node : Node[V]?) -> Node[V]? { #| match node { #| None => None #| Some(node) => { #| let left = copy_tree(node.left) #| let right = copy_tree(node.right) #| let new_node = new_node(node.value, left~, right~, height=node.height) #| Some(new_node) #| } #| } #|} #|fn[V] new_node( #| value : V, #| left? : Node[V]? = None, #| right? : Node[V]? = None, #| height? : Int = 1, #|) -> Node[V] { #| { value, left, right, height } #|} #|fn[V] new_node_update_height( #| value : V, #| left~ : Node[V]?, #| right~ : Node[V]?, #|) -> Node[V] { #| { value, left, right, height: max(height(left), height(right)) + 1 } #|} #|pub fn[V : Compare] add(self : T[V], value : V) -> Unit { #| let (new_root, inserted) = add_node(self.root, value) #| if self.root != new_root { #| self.root = new_root #| } #| if inserted { #| self.size += 1 #| } #|} #|pub fn[V : Compare] remove(self : T[V], value : V) -> Unit { #| if self.root is Some(old_root) { #| let (new_root, deleted) = delete_node(old_root, value) #| if self.root != new_root { #| self.root = new_root #| } #| if deleted { #| self.size -= 1 #| } #| } #|} #|pub fn[V : Compare] contains(self : T[V], value : V) -> Bool { #| loop (self.root, value) { #| (None, _) => false #| (Some(node), value) => { #| let compare_result = value.compare(node.value) #| if compare_result == 0 { #| true #| } else if compare_result < 0 { #| continue (node.left, value) #| } else { #| continue (node.right, value) #| } #| } #| } #|} #|pub fn[V : Compare] union(self : T[V], src : T[V]) -> T[V] { #| fn aux(a : Node[V]?, b : Node[V]?) -> Node[V]? { #| match (a, b) { #| (Some(_), None) => a #| (None, Some(_)) => b #| (Some({ value: va, left: la, right: ra, .. }), Some(_)) => { #| let (l, r) = split(b, va) #| Some(join(aux(la, l), va, aux(ra, r))) #| } #| (None, None) => None #| } #| } #| match (self.root, src.root) { #| (Some(_), Some(_)) => { #| let t1 = copy_tree(self.root) #| let t2 = copy_tree(src.root) #| let t = aux(t1, t2) #| let mut ct = 0 #| let ret = { root: t, size: 0 } #| ret.each(_x => ct = ct + 1) #| ret.size = ct #| ret #| } #| (Some(_), None) => { root: copy_tree(self.root), size: self.size } #| (None, Some(_)) => { root: copy_tree(src.root), size: src.size } #| (None, None) => new() #| } #|} #|fn[V : Compare] split(root : Node[V]?, value : V) -> (Node[V]?, Node[V]?) { #| match root { #| None => (None, None) #| Some(node) => { #| let comp = value.compare(node.value) #| if comp == 0 { #| (node.left, node.right) #| } else if comp < 0 { #| let (l, r) = split(node.left, value) #| (l, Some(join(r, node.value, node.right))) #| } else { #| let (l, r) = split(node.right, value) #| (Some(join(node.left, node.value, l)), r) #| } #| } #| } #|} #|fn[V : Compare] join(left : Node[V]?, value : V, right : Node[V]?) -> Node[V] { #| let (hl, hr) = (height(left), height(right)) #| if hl > hr + 1 { #| join_right(left, value, right) #| } else if hr > hl + 1 { #| join_left(left, value, right) #| } else { #| new_node_update_height(value, left~, right~) #| } #|} #|fn[V : Compare] join_left(l : Node[V]?, v : V, r : Node[V]?) -> Node[V] { #| let { value: rv, left: rl, right: rr, .. } = r.unwrap() #| let node = if height(rl) <= height(l) + 1 { #| let new_l = new_node_update_height(left=l, v, right=rl) #| if height(Some(new_l)) <= height(rr) + 1 { #| new_node_update_height(left=Some(new_l), rv, right=rr) #| } else { #| let new_l = rotate_l(new_l) #| let new = new_node_update_height(left=Some(new_l), rv, right=rr) #| rotate_r(new) #| } #| } else { #| let new_l = join_left(l, v, rl) #| let new = new_node_update_height(left=Some(new_l), rv, right=rr) #| if height(Some(new_l)) <= height(rr) + 1 { #| new #| } else { #| rotate_r(new) #| } #| } #| node.update_height() #| node #|} #|fn[V : Compare] join_right(l : Node[V]?, v : V, r : Node[V]?) -> Node[V] { #| let { value: lv, left: ll, right: lr, .. } = l.unwrap() #| let node = if height(lr) <= height(r) + 1 { #| let new_r = new_node_update_height(left=lr, v, right=r) #| if height(Some(new_r)) <= height(ll) + 1 { #| new_node_update_height(left=ll, lv, right=Some(new_r)) #| } else { #| let new_r = rotate_r(new_r) #| let new = new_node_update_height(left=ll, lv, right=Some(new_r)) #| rotate_l(new) #| } #| } else { #| let new_r = join_right(lr, v, r) #| let new = new_node_update_height(left=ll, lv, right=Some(new_r)) #| if height(Some(new_r)) <= height(ll) + 1 { #| new #| } else { #| rotate_l(new) #| } #| } #| node.update_height() #| node #|} #|pub fn[V : Compare] difference(self : T[V], src : T[V]) -> T[V] { #| let ret = new() #| self.each(x => if !src.contains(x) { ret.add(x) }) #| ret #|} #|pub fn[V : Compare] symmetric_difference(self : T[V], other : T[V]) -> T[V] { #| let set1 = self.difference(other) #| let set2 = other.difference(self) #| set1.union(set2) #|} #|pub fn[V : Compare] intersection(self : T[V], src : T[V]) -> T[V] { #| let ret = new() #| self.each(x => if src.contains(x) { ret.add(x) }) #| ret #|} #|pub fn[V : Compare] subset(self : T[V], src : T[V]) -> Bool { #| let mut ret = true #| self.each(x => if !src.contains(x) { ret = false }) #| ret #|} #|pub fn[V : Compare] disjoint(self : T[V], src : T[V]) -> Bool { #| let mut ret = true #| self.each(x => if src.contains(x) { ret = false }) #| ret #|} #|pub impl[V : Eq] Eq for T[V] with op_equal(self, other) { #| self.to_array() == other.to_array() #|} #|pub fn[V] is_empty(self : T[V]) -> Bool { #| self.root is None #|} #|pub fn[V] size(self : T[V]) -> Int { #| self.size #|} #|pub fn[V] each(self : T[V], f : (V) -> Unit raise?) -> Unit raise? { #| fn dfs(root : Node[V]?) -> Unit raise? { #| if root is Some(root) { #| dfs(root.left) #| f(root.value) #| dfs(root.right) #| } #| } #| dfs(self.root) #|} #|pub fn[V] eachi(self : T[V], f : (Int, V) -> Unit raise?) -> Unit raise? { #| let mut i = 0 #| self.each(v => { #| f(i, v) #| i = i + 1 #| }) #|} #|pub fn[V] to_array(self : T[V]) -> Array[V] { #| if self.size == 0 { #| [] #| } else { #| let padding = self.root.unwrap().value #| let arr = Array::make(self.size, padding) #| let mut i = 0 #| fn dfs(root : Node[V]?) -> Unit { #| if root is Some(root) { #| dfs(root.left) #| arr[i] = root.value #| i = i + 1 #| dfs(root.right) #| } #| } #| dfs(self.root) #| arr #| } #|} #|pub fn[V] iter(self : T[V]) -> Iter[V] { #| Iter::new(yield_ => { #| fn go(x : Node[V]?) { #| match x { #| None => IterContinue #| Some({ left, right, value, .. }) => #| if go(left) is IterEnd { #| IterEnd #| } else if yield_(value) is IterEnd { #| IterEnd #| } else { #| go(right) #| } #| } #| } #| go(self.root) #| }) #|} #|pub fn[V : Compare] from_iter(iter : Iter[V]) -> T[V] { #| let s = new() #| iter.each(e => s.add(e)) #| s #|} #|pub impl[V : Show] Show for T[V] with output(self, logger) { #| logger.write_iter(self.iter(), prefix="@sorted_set.from_array([", suffix="])") #|} #|pub impl[X : @quickcheck.Arbitrary + Compare] @quickcheck.Arbitrary for T[X] with arbitrary( #| size, #| rs, #|) { #| @quickcheck.Arbitrary::arbitrary(size, rs) |> from_iter #|} #|impl[T : Show] Show for Node[T] with output(self, logger) { #| let x = { root: Some(self), size: 0 } // Hack for test #| logger.write_iter(x.iter()) #|} #|pub fn[V : Compare] range(self : T[V], low : V, high : V) -> Iter[V] { #| Iter::new(yield_ => { #| fn go(x : Node[V]?) { #| match x { #| None => IterContinue #| Some({ left, right, value, .. }) => { #| let cmp_key_low = value.compare(low) #| let cmp_key_high = value.compare(high) #| if cmp_key_low > 0 && go(left) is IterEnd { #| IterEnd #| } else if cmp_key_low >= 0 && #| cmp_key_high <= 0 && #| yield_(value) is IterEnd { #| IterEnd #| } else if cmp_key_high < 0 { #| go(right) #| } else { #| IterContinue #| } #| } #| } #| } #| go(self.root) #| }) #|} #|fn[V : Compare] replace_root_with_min( #| root : Node[V], #| node : Node[V], #|) -> Node[V]? { #| let (l, r) = (node.left, node.right) #| match l { #| None => { #| root.value = node.value #| r #| } #| Some(ln) => { #| node.left = replace_root_with_min(root, ln) #| Some(balance(node)) #| } #| } #|} #|fn[V] update_height(self : Node[V]) -> Unit { #| self.height = 1 + max(height(self.left), height(self.right)) #|} #|fn[V] height_ge(x1 : Node[V]?, x2 : Node[V]?) -> Bool { #| match x2 { #| None => true #| Some(n2) => #| match x1 { #| None => false #| Some(n1) => n1.height >= n2.height #| } #| } #|} #|fn[V] balance(root : Node[V]) -> Node[V] { #| let (l, r) = (root.left, root.right) #| let (hl, hr) = (height(l), height(r)) #| let new_root = if hl > hr + 1 { #| let { left: ll, right: lr, .. } = l.unwrap() #| if height_ge(ll, lr) { #| rotate_r(root) #| } else { #| rotate_lr(root) #| } #| } else if hr > hl + 1 { #| let { left: rl, right: rr, .. } = r.unwrap() #| if height_ge(rr, rl) { #| rotate_l(root) #| } else { #| rotate_rl(root) #| } #| } else { #| root #| } #| new_root.update_height() #| new_root #|} #|fn[V] rotate_l(n : Node[V]) -> Node[V] { #| let r = n.right.unwrap() #| n.right = r.left #| r.left = Some(n) #| n.update_height() #| r.update_height() #| r #|} #|fn[V] rotate_r(n : Node[V]) -> Node[V] { #| let l = n.left.unwrap() #| n.left = l.right #| l.right = Some(n) #| n.update_height() #| l.update_height() #| l #|} #|fn[V] rotate_lr(n : Node[V]) -> Node[V] { #| let l = n.left.unwrap() #| let v = rotate_l(l) #| n.left = Some(v) #| rotate_r(n) #|} #|fn[V] rotate_rl(n : Node[V]) -> Node[V] { #| let r = n.right.unwrap() #| let v = rotate_r(r) #| n.right = Some(v) #| rotate_l(n) #|} #|fn[V : Compare] add_node(root : Node[V]?, value : V) -> (Node[V]?, Bool) { #| match root { #| None => (Some(new_node(value)), true) #| Some(n) => { #| let comp = value.compare(n.value) #| if comp == 0 { #| n.value = value #| (Some(n), false) #| } else { #| let (l, r) = (n.left, n.right) #| if comp < 0 { #| let (nl, inserted) = add_node(l, value) #| n.left = nl #| (Some(balance(n)), inserted) #| } else { #| let (nr, inserted) = add_node(r, value) #| n.right = nr #| (Some(balance(n)), inserted) #| } #| } #| } #| } #|} #|fn[V : Compare] delete_node(root : Node[V], value : V) -> (Node[V]?, Bool) { #| let comp = value.compare(root.value) #| if comp == 0 { #| let (l, r) = (root.left, root.right) #| let n = match (l, r) { #| (Some(_), Some(nr)) => { #| root.right = replace_root_with_min(root, nr) #| Some(balance(root)) #| } #| (None, Some(_)) => r #| (Some(_), None) | (None, None) => l #| } #| (n, true) #| } else if comp < 0 { #| match root.left { #| None => (Some(root), false) #| Some(l) => { #| let (nl, deleted) = delete_node(l, value) #| root.left = nl #| (Some(balance(root)), deleted) #| } #| } #| } else { #| match root.right { #| None => (Some(root), false) #| Some(r) => { #| let (nr, deleted) = delete_node(r, value) #| root.right = nr #| (Some(balance(root)), deleted) #| } #| } #| } #|} #|test "copy" { #| let set = from_array([1, 2, 3, 4, 5]) #| let copied_set = set.copy() #| inspect(copied_set, content="@sorted_set.from_array([1, 2, 3, 4, 5])") #| inspect(set.debug_tree() == copied_set.debug_tree(), content="true") #| let set : T[Int] = from_array([]) #| let copied_set = set.copy() #| inspect(copied_set, content="@sorted_set.from_array([])") #| inspect(set.debug_tree() == copied_set.debug_tree(), content="true") #|} #|test "union" { #| let set1 = from_array([1, 2, 3]) #| let set2 = from_array([4, 5, 6]) #| let set3 = set1.union(set2) #| inspect(set3, content="@sorted_set.from_array([1, 2, 3, 4, 5, 6])") #| inspect( #| set3.debug_tree(), #| content="([3]3,([2]2,([1]1,_,_),_),([2]5,([1]4,_,_),([1]6,_,_)))", #| ) #| let set1 = from_array([1, 2, 3]) #| let set2 = from_array([2, 3, 4]) #| let set3 = set1.union(set2) #| inspect(set3, content="@sorted_set.from_array([1, 2, 3, 4])") #| inspect(set3.debug_tree(), content="([3]2,([1]1,_,_),([2]3,_,([1]4,_,_)))") #| let set1 = from_array([1, 2, 3]) #| let set2 = from_array([2, 3]) #| let set3 = set1.union(set2) #| inspect(set3, content="@sorted_set.from_array([1, 2, 3])") #| inspect(set3.debug_tree(), content="([2]2,([1]1,_,_),([1]3,_,_))") #| let set1 : T[Int] = new() #| let set2 = new() #| let set3 = set1.union(set2) #| inspect(set3, content="@sorted_set.from_array([])") #| inspect(set3.debug_tree(), content="_") #| let set1 = from_array([1, 2, 3]) #| let set2 = from_array([]) #| let set3 = set1.union(set2) #| inspect(set3, content="@sorted_set.from_array([1, 2, 3])") #| inspect(set3.debug_tree(), content="([2]2,([1]1,_,_),([1]3,_,_))") #| let set1 = from_array([]) #| let set2 = from_array([1, 2, 3]) #| let set3 = set1.union(set2) #| inspect(set3, content="@sorted_set.from_array([1, 2, 3])") #| inspect(set3.debug_tree(), content="([2]2,([1]1,_,_),([1]3,_,_))") #| let set1 = from_array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) #| let set2 = from_array([11, 12, 13, 14, 15, 16, 17, 18, 19, 20]) #| let set3 = set1.union(set2) #| inspect( #| set3, #| content="@sorted_set.from_array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])", #| ) #| inspect( #| set3.debug_tree(), #| content="([5]14,([4]8,([3]4,([2]2,([1]1,_,_),([1]3,_,_)),([2]6,([1]5,_,_),([1]7,_,_))),([3]12,([2]10,([1]9,_,_),([1]11,_,_)),([1]13,_,_))),([3]18,([2]16,([1]15,_,_),([1]17,_,_)),([2]19,_,([1]20,_,_))))", #| ) #| let set1 = from_array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) #| let set2 = from_array([6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) #| let set3 = set1.union(set2) #| inspect( #| set3, #| content="@sorted_set.from_array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])", #| ) #| inspect( #| set3.debug_tree(), #| content="([5]11,([4]4,([2]2,([1]1,_,_),([1]3,_,_)),([3]8,([2]6,([1]5,_,_),([1]7,_,_)),([2]9,_,([1]10,_,_)))),([3]13,([1]12,_,_),([2]14,_,([1]15,_,_))))", #| ) #| let set1 = from_array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) #| let set2 = from_array([6, 7, 8, 9, 10]) #| let set3 = set1.union(set2) #| inspect( #| set3, #| content="@sorted_set.from_array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])", #| ) #| inspect( #| set3.debug_tree(), #| content="([4]4,([2]2,([1]1,_,_),([1]3,_,_)),([3]8,([2]6,([1]5,_,_),([1]7,_,_)),([2]9,_,([1]10,_,_))))", #| ) #|} #|test "split" { #| let (l, r) = split(from_array([7, 2, 9, 4, 5, 6, 3, 8, 1]).root, 5) #| inspect(l, content="Some([1, 2, 3, 4])") #| inspect(r, content="Some([6, 7, 8, 9])") #| let (l, r) = split(from_array([7, 2, 9, 4, 5, 6, 3, 8, 1]).root, 0) #| inspect(l, content="None") #| inspect(r, content="Some([1, 2, 3, 4, 5, 6, 7, 8, 9])") #| let (l, r) = split(from_array([7, 2, 9, 4, 5, 6, 3, 8, 1]).root, 10) #| inspect(l, content="Some([1, 2, 3, 4, 5, 6, 7, 8, 9])") #| inspect(r, content="None") #| let (l, r) = split(from_array([7, 2, 9, 4, 5, 6, 3, 8, 1]).root, 4) #| inspect(l, content="Some([1, 2, 3])") #| inspect(r, content="Some([5, 6, 7, 8, 9])") #| let (l, r) = split(from_array([]).root, 7) #| inspect(l, content="None") #| inspect(r, content="None") #| let (l, r) = split( #| from_array([ #| 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, #| 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, #| 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, #| 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, #| 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, #| 98, 99, 100, #| ]).root, #| 50, #| ) #| inspect( #| l, #| content="Some([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49])", #| ) #| inspect( #| r, #| content="Some([51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100])", #| ) #|} #|test "join" { #| let l = from_array([13, 8, 17, 1, 11, 15, 25, 6]) #| let r = from_array([27, 28, 40, 35, 33]) #| inspect( #| join(l.root, 26, r.root), #| content="[1, 6, 8, 11, 13, 15, 17, 25, 26, 27, 28, 33, 35, 40]", #| ) #| let l = from_array([3, 2, 5, 1, 4]) #| let r = from_array([7]) #| inspect(join(l.root, 6, r.root), content="[1, 2, 3, 4, 5, 6, 7]") #| let l = from_array([3, 2, 5, 1, 4]) #| let r = from_array([]) #| inspect(join(l.root, 6, r.root), content="[1, 2, 3, 4, 5, 6]") #| let l = from_array([]) #| let r = from_array([]) #| inspect(join(l.root, 6, r.root), content="[6]") #| let l = from_array([]) #| let r = from_array([7, 8, 9, 10, 11, 12]) #| inspect(join(l.root, 6, r.root), content="[6, 7, 8, 9, 10, 11, 12]") #|} #|test "add to empty set" { #| let set = new() #| set.add(1) #| assert_eq(set.contains(1), true) #| inspect(set.debug_tree(), content="([1]1,_,_)") #|} #|test "add to non-empty set" { #| let set = new() #| set.add(1) #| set.add(2) #| assert_eq(set.contains(1), true) #| assert_eq(set.contains(2), true) #| inspect(set.debug_tree(), content="([2]1,_,([1]2,_,_))") #|} #|test "add duplicate value" { #| let set = new() #| set.add(1) #| set.add(1) #| assert_eq(set.contains(1), true) #| assert_eq(set.size(), 1) #| inspect(set.debug_tree(), content="([1]1,_,_)") #|} #|test "add multiple values" { #| let set = new() #| set.add(1) #| set.add(2) #| set.add(3) #| assert_eq(set.contains(1), true) #| assert_eq(set.contains(2), true) #| assert_eq(set.contains(3), true) #| assert_eq(set.size(), 3) #| inspect(set.debug_tree(), content="([2]2,([1]1,_,_),([1]3,_,_))") #|} #|test "add_and_remove" { #| let set = from_array([7, 2, 9, 4, 5, 6, 3, 8, 1]) #| set.remove(8) #| inspect(set, content="@sorted_set.from_array([1, 2, 3, 4, 5, 6, 7, 9])") #| inspect( #| set.debug_tree(), #| content="([4]5,([3]3,([2]2,([1]1,_,_),_),([1]4,_,_)),([2]7,([1]6,_,_),([1]9,_,_)))", #| ) #| let set = from_array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) #| set.remove(1) #| inspect(set, content="@sorted_set.from_array([2, 3, 4, 5, 6, 7, 8, 9, 10])") #| inspect( #| set.debug_tree(), #| content="([4]4,([2]2,_,([1]3,_,_)),([3]8,([2]6,([1]5,_,_),([1]7,_,_)),([2]9,_,([1]10,_,_))))", #| ) #| set.remove(5) #| inspect(set, content="@sorted_set.from_array([2, 3, 4, 6, 7, 8, 9, 10])") #| inspect( #| set.debug_tree(), #| content="([4]4,([2]2,_,([1]3,_,_)),([3]8,([2]6,_,([1]7,_,_)),([2]9,_,([1]10,_,_))))", #| ) #| set.remove(10) #| inspect(set, content="@sorted_set.from_array([2, 3, 4, 6, 7, 8, 9])") #| inspect( #| set.debug_tree(), #| content="([4]4,([2]2,_,([1]3,_,_)),([3]8,([2]6,_,([1]7,_,_)),([1]9,_,_)))", #| ) #| set.remove(4) #| inspect(set, content="@sorted_set.from_array([2, 3, 6, 7, 8, 9])") #| inspect( #| set.debug_tree(), #| content="([3]6,([2]2,_,([1]3,_,_)),([2]8,([1]7,_,_),([1]9,_,_)))", #| ) #| set.add(1) #| inspect(set, content="@sorted_set.from_array([1, 2, 3, 6, 7, 8, 9])") #| inspect( #| set.debug_tree(), #| content="([3]6,([2]2,([1]1,_,_),([1]3,_,_)),([2]8,([1]7,_,_),([1]9,_,_)))", #| ) #| set.add(5) #| inspect(set, content="@sorted_set.from_array([1, 2, 3, 5, 6, 7, 8, 9])") #| inspect( #| set.debug_tree(), #| content="([4]6,([3]2,([1]1,_,_),([2]3,_,([1]5,_,_))),([2]8,([1]7,_,_),([1]9,_,_)))", #| ) #| set.add(10) #| inspect(set, content="@sorted_set.from_array([1, 2, 3, 5, 6, 7, 8, 9, 10])") #| inspect( #| set.debug_tree(), #| content="([4]6,([3]2,([1]1,_,_),([2]3,_,([1]5,_,_))),([3]8,([1]7,_,_),([2]9,_,([1]10,_,_))))", #| ) #| set.add(4) #| inspect( #| set, #| content="@sorted_set.from_array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])", #| ) #| inspect( #| set.debug_tree(), #| content="([4]6,([3]2,([1]1,_,_),([2]4,([1]3,_,_),([1]5,_,_))),([3]8,([1]7,_,_),([2]9,_,([1]10,_,_))))", #| ) #| set.add(11) #| inspect( #| set, #| content="@sorted_set.from_array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])", #| ) #| inspect( #| set.debug_tree(), #| content="([4]6,([3]2,([1]1,_,_),([2]4,([1]3,_,_),([1]5,_,_))),([3]8,([1]7,_,_),([2]10,([1]9,_,_),([1]11,_,_))))", #| ) #| set.remove(11) #| inspect( #| set, #| content="@sorted_set.from_array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])", #| ) #| inspect( #| set.debug_tree(), #| content="([4]6,([3]2,([1]1,_,_),([2]4,([1]3,_,_),([1]5,_,_))),([3]8,([1]7,_,_),([2]10,([1]9,_,_),_)))", #| ) #| set.remove(12) #| inspect( #| set, #| content="@sorted_set.from_array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])", #| ) #| set.add(10) #| inspect( #| set, #| content="@sorted_set.from_array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])", #| ) #| set.remove(1) #| inspect(set, content="@sorted_set.from_array([2, 3, 4, 5, 6, 7, 8, 9, 10])") #| inspect( #| set.debug_tree(), #| content="([4]6,([3]4,([2]2,_,([1]3,_,_)),([1]5,_,_)),([3]8,([1]7,_,_),([2]10,([1]9,_,_),_)))", #| ) #| set.remove(2) #| inspect(set, content="@sorted_set.from_array([3, 4, 5, 6, 7, 8, 9, 10])") #| inspect( #| set.debug_tree(), #| content="([4]6,([2]4,([1]3,_,_),([1]5,_,_)),([3]8,([1]7,_,_),([2]10,([1]9,_,_),_)))", #| ) #| set.remove(3) #| inspect(set, content="@sorted_set.from_array([4, 5, 6, 7, 8, 9, 10])") #| inspect( #| set.debug_tree(), #| content="([4]6,([2]4,_,([1]5,_,_)),([3]8,([1]7,_,_),([2]10,([1]9,_,_),_)))", #| ) #| set.remove(4) #| inspect(set, content="@sorted_set.from_array([5, 6, 7, 8, 9, 10])") #| inspect( #| set.debug_tree(), #| content="([3]8,([2]6,([1]5,_,_),([1]7,_,_)),([2]10,([1]9,_,_),_))", #| ) #| set.remove(5) #| inspect(set, content="@sorted_set.from_array([6, 7, 8, 9, 10])") #| inspect( #| set.debug_tree(), #| content="([3]8,([2]6,_,([1]7,_,_)),([2]10,([1]9,_,_),_))", #| ) #| set.remove(6) #| inspect(set, content="@sorted_set.from_array([7, 8, 9, 10])") #| inspect(set.debug_tree(), content="([3]8,([1]7,_,_),([2]10,([1]9,_,_),_))") #| set.remove(7) #| inspect(set, content="@sorted_set.from_array([8, 9, 10])") #| inspect(set.debug_tree(), content="([2]9,([1]8,_,_),([1]10,_,_))") #| set.remove(8) #| inspect(set, content="@sorted_set.from_array([9, 10])") #| inspect(set.debug_tree(), content="([2]9,_,([1]10,_,_))") #| set.remove(9) #| inspect(set, content="@sorted_set.from_array([10])") #| inspect(set.debug_tree(), content="([1]10,_,_)") #| set.remove(10) #| inspect(set, content="@sorted_set.from_array([])") #| inspect(set.debug_tree(), content="_") #| let set = from_array([7, 2, 9, 4, 5, 6, 3, 1]) #| set.remove(3) #| inspect(set, content="@sorted_set.from_array([1, 2, 4, 5, 6, 7, 9])") #| inspect( #| set.debug_tree(), #| content="([3]5,([2]2,([1]1,_,_),([1]4,_,_)),([2]7,([1]6,_,_),([1]9,_,_)))", #| ) #| set.remove(2) #| inspect(set, content="@sorted_set.from_array([1, 4, 5, 6, 7, 9])") #| inspect( #| set.debug_tree(), #| content="([3]5,([2]4,([1]1,_,_),_),([2]7,([1]6,_,_),([1]9,_,_)))", #| ) #| set.remove(5) #| inspect(set, content="@sorted_set.from_array([1, 4, 6, 7, 9])") #| inspect( #| set.debug_tree(), #| content="([3]6,([2]4,([1]1,_,_),_),([2]7,_,([1]9,_,_)))", #| ) #| set.remove(9) #| inspect(set, content="@sorted_set.from_array([1, 4, 6, 7])") #| inspect(set.debug_tree(), content="([3]6,([2]4,([1]1,_,_),_),([1]7,_,_))") #| set.remove(1) #| inspect(set, content="@sorted_set.from_array([4, 6, 7])") #| inspect(set.debug_tree(), content="([2]6,([1]4,_,_),([1]7,_,_))") #| set.remove(7) #| inspect(set, content="@sorted_set.from_array([4, 6])") #| inspect(set.debug_tree(), content="([2]6,([1]4,_,_),_)") #| set.remove(4) #| inspect(set, content="@sorted_set.from_array([6])") #| inspect(set.debug_tree(), content="([1]6,_,_)") #| set.remove(6) #| inspect(set, content="@sorted_set.from_array([])") #| inspect(set.debug_tree(), content="_") #|} #|pub impl[K] Default for T[K] with default() { #| new() #|} ), "types.mbt": ( #|struct T[V] { #| mut root : Node[V]? #| mut size : Int #|} #|priv struct Node[V] { #| mut value : V #| mut left : Node[V]? #| mut right : Node[V]? #| mut height : Int #|} ), "utils.mbt": ( #|impl[V : Eq] Eq for Node[V] with op_equal(self, other) { #| self.value == other.value #|} #|fn max(x : Int, y : Int) -> Int { #| if x > y { #| x #| } else { #| y #| } #|} #|fn[V] height(node : Node[V]?) -> Int { #| match node { #| None => 0 #| Some(n) => n.height #| } #|} #|fn[V : Show] debug_node(self : Node[V]) -> String { #| let l = match self.left { #| Some(left) => left.debug_node() #| None => "_" #| } #| let r = match self.right { #| Some(right) => right.debug_node() #| None => "_" #| } #| let value = self.value #| let height = self.height #| "([\{height}]\{value},\{l},\{r})" #|} #|fn[V : Show] debug_tree(self : T[V]) -> String { #| match self.root { #| Some(root) => root.debug_node() #| None => "_" #| } #|} ), }, ) ///| let moonbitlang_core_strconv_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/strconv", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/double": moonbitlang_core_double_module, "moonbitlang/core/uint64": moonbitlang_core_uint64_module, "moonbitlang/core/string": moonbitlang_core_string_module, "moonbitlang/core/char": moonbitlang_core_char_module, }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/builtin", #| "moonbitlang/core/double", #| "moonbitlang/core/uint64", #| "moonbitlang/core/string", #| "moonbitlang/core/char" #| ] #|} ), "bool.mbt": ( #|pub fn parse_bool(str : @string.View) -> Bool raise StrConvError { #| match str { #| "1" | "t" | "T" | "true" | "TRUE" | "True" => true #| "0" | "f" | "F" | "false" | "FALSE" | "False" => false #| _ => syntax_err() #| } #|} #|test "parse_bool" { #| let tests : Array[(String, Result[Bool, String])] = [ #| ("", Err(syntax_err_str)), #| ("zutomayo", Err(syntax_err_str)), #| ("0", Ok(false)), #| ("f", Ok(false)), #| ("F", Ok(false)), #| ("FALSE", Ok(false)), #| ("false", Ok(false)), #| ("False", Ok(false)), #| ("1", Ok(true)), #| ("t", Ok(true)), #| ("T", Ok(true)), #| ("TRUE", Ok(true)), #| ("true", Ok(true)), #| ("True", Ok(true)), #| ] #| for i in 0.. Err(err) #| }, #| t.1, #| ) #| } #|} ), "decimal.mbt": ( #|let max_shift = 59 #|let powtab = [ #| 1, 3, 6, 9, 13, 16, 19, 23, 26, 29, 33, 36, 39, 43, 46, 49, 53, 56, 59, #|] #|fn Decimal::new_priv() -> Decimal { #| { #| digits: FixedArray::make(800, Byte::default()), #| digits_num: 0, #| decimal_point: 0, #| negative: false, #| truncated: false, #| } #|} #|fn Decimal::from_int64_priv(v : Int64) -> Decimal { #| let d = Decimal::new_priv() #| d.assign(v) #| d #|} #|fn parse_decimal_priv(str : @string.View) -> Decimal raise StrConvError { #| parse_decimal_from_view(str) #|} #|fn parse_decimal_from_view(str : @string.View) -> Decimal raise StrConvError { #| let d = Decimal::new_priv() #| let mut has_dp = false #| let mut has_digits = false #| let rest = match str { #| ['-', .. rest] => { #| d.negative = true #| rest #| } #| ['+', .. rest] => rest #| _ => str #| } #| let rest = loop rest { #| ['_', .. rest] => continue rest #| ['.', .. rest] => { #| guard !has_dp else { syntax_err() } #| has_dp = true #| d.decimal_point = d.digits_num #| continue rest #| } #| ['0'..='9' as digit, .. rest] => { #| has_digits = true #| if digit == '0' && d.digits_num == 0 { #| d.decimal_point -= 1 #| continue rest #| } #| if d.digits_num < d.digits.length() { #| d.digits[d.digits_num] = (digit.to_int() - '0').to_byte() #| d.digits_num += 1 #| } else if digit != '0' { #| d.truncated = true #| } #| continue rest #| } #| rest => rest #| } #| guard has_digits else { syntax_err() } #| if !has_dp { #| d.decimal_point = d.digits_num #| } #| let rest = match rest { #| ['e' | 'E', .. rest] => { #| let mut exp_sign = 1 #| let rest = match rest { #| ['+', .. rest] => rest #| ['-', .. rest] => { #| exp_sign = -1 #| rest #| } #| rest => rest #| } #| guard rest is ['0'..='9', ..] else { syntax_err() } #| let mut exp = 0 #| let rest = loop rest { #| ['_', .. rest] => continue rest #| ['0'..='9' as digit, .. rest] => { #| exp = exp * 10 + (digit.to_int() - '0') #| continue rest #| } #| rest => rest #| } #| d.decimal_point += exp_sign * exp #| rest #| } #| rest => rest #| } #| guard rest is [] else { syntax_err() } #| d.trim() #| d #|} #|fn to_double_priv(self : Decimal) -> Double raise StrConvError { #| let mut exponent = 0 #| let mut mantissa = 0L #| if self.digits_num == 0 || self.decimal_point < -330 { #| mantissa = 0 #| exponent = double_info.bias #| let bits = assemble_bits(mantissa, exponent, self.negative) #| return bits.reinterpret_as_double() #| } #| if self.decimal_point > 310 { #| range_err() #| } #| while self.decimal_point > 0 { #| let mut n = 0 #| if self.decimal_point >= powtab.length() { #| n = 60 #| } else { #| n = powtab[self.decimal_point] #| } #| self.shift_priv(-n) #| exponent += n #| } #| while self.decimal_point < 0 || #| (self.decimal_point == 0 && self.digits[0].to_int() < 5) { #| let mut n = 0 #| if -self.decimal_point >= powtab.length() { #| n = 60 #| } else { #| n = powtab[-self.decimal_point] #| } #| self.shift_priv(n) #| exponent -= n #| } #| exponent -= 1 #| if exponent < double_info.bias + 1 { #| let n = double_info.bias + 1 - exponent #| self.shift_priv(-n) #| exponent += n #| } #| if exponent - double_info.bias >= (1 << double_info.exponent_bits) - 1 { #| range_err() #| } #| self.shift_priv(double_info.mantissa_bits + 1) #| mantissa = self.rounded_integer() #| if mantissa == 2L << double_info.mantissa_bits { #| mantissa = mantissa << 1 #| exponent += 1 #| if exponent - double_info.bias >= (1 << double_info.exponent_bits) - 1 { #| range_err() #| } #| } #| if (mantissa & (1L << double_info.mantissa_bits)) == 0L { #| exponent = double_info.bias #| } #| let bits = assemble_bits(mantissa, exponent, self.negative) #| bits.reinterpret_as_double() #|} #|fn shift_priv(self : Decimal, s : Int) -> Unit { #| if self.digits_num == 0 { #| return #| } #| let mut s = s #| if s > 0 { #| while s > max_shift { #| self.left_shift(max_shift) #| s -= max_shift #| } #| self.left_shift(s) #| } #| if s < 0 { #| while s < -max_shift { #| self.right_shift(max_shift) #| s += max_shift #| } #| self.right_shift(-s) #| } #|} #|fn assemble_bits(mantissa : Int64, exponent : Int, negative : Bool) -> Int64 { #| let biased_exp = exponent - double_info.bias #| let mut bits = mantissa & ((1L << double_info.mantissa_bits) - 1L) #| let exp_bits = (biased_exp & ((1 << double_info.exponent_bits) - 1)).to_int64() #| bits = bits | (exp_bits << double_info.mantissa_bits) #| if negative { #| bits = bits | (1L << double_info.mantissa_bits << double_info.exponent_bits) #| } #| bits #|} #|fn rounded_integer(self : Decimal) -> Int64 { #| if self.decimal_point > 20 { #| return 0xFFFFFFFFFFFFFFFFL #| } #| let mut n = 0L #| let mut i = 0 #| while i < self.decimal_point && i < self.digits_num { #| n = n * 10L + self.digits[i].to_int64() #| i += 1 #| } #| while i < self.decimal_point { #| n *= 10L #| i += 1 #| } #| if self.should_round_up(self.decimal_point) { #| n += 1L #| } #| n #|} #|fn should_round_up(self : Decimal, d : Int) -> Bool { #| if d < 0 || d >= self.digits_num { #| return false #| } #| if self.digits[d].to_int() == 5 && d + 1 == self.digits_num { #| if self.truncated { #| return true #| } #| return d > 0 && self.digits[d - 1].to_int() % 2 != 0 #| } #| self.digits[d].to_int() >= 5 #|} #|fn assign(self : Decimal, v : Int64) -> Unit { #| let buf = FixedArray::make(24, Byte::default()) #| let mut n = 0 #| let mut v = v #| while v > 0 { #| let v1 = v / 10 #| buf[n] = (v - v1 * 10).to_byte() #| n += 1 #| v = v1 #| } #| self.digits_num = 0 #| for i = n - 1; i >= 0; i = i - 1 { #| self.digits[self.digits_num] = buf[i] #| self.digits_num += 1 #| } #| self.decimal_point = self.digits_num #| self.trim() #|} #|fn right_shift(self : Decimal, s : Int) -> Unit { #| let mut read_index = 0 #| let mut write_index = 0 #| let mut acc = 0UL #| while acc >> s == 0 { #| if read_index >= self.digits_num { #| while acc >> s == 0 { #| acc *= 10 #| read_index += 1 #| } #| break #| } #| let d = self.digits[read_index] #| acc = acc * 10 + d.to_int64().reinterpret_as_uint64() #| read_index += 1 #| } #| self.decimal_point -= read_index - 1 #| let mask = (1UL << s) - 1 #| while read_index < self.digits_num { #| let out = acc >> s #| self.digits[write_index] = out.to_byte() #| write_index += 1 #| acc = acc & mask #| let d = self.digits[read_index] #| acc = acc * 10 + d.to_int64().reinterpret_as_uint64() #| read_index += 1 #| } #| while acc > 0 { #| let out = acc >> s #| if write_index < self.digits.length() { #| self.digits[write_index] = out.to_byte() #| write_index += 1 #| } else if out > 0 { #| self.truncated = true #| } #| acc = acc & mask #| acc = acc * 10 #| } #| self.digits_num = write_index #| self.trim() #|} #|let left_shift_cheats = [ #| (0, ""), #| (1, "5"), // * 2 #| (1, "25"), // * 4 #| (1, "125"), // * 8 #| (2, "625"), // * 16 #| (2, "3125"), // * 32 #| (2, "15625"), // * 64 #| (3, "78125"), // * 128 #| (3, "390625"), // * 256 #| (3, "1953125"), // * 512 #| (4, "9765625"), // * 1024 #| (4, "48828125"), // * 2048 #| (4, "244140625"), // * 4096 #| (4, "1220703125"), // * 8192 #| (5, "6103515625"), // * 16384 #| (5, "30517578125"), // * 32768 #| (5, "152587890625"), // * 65536 #| (6, "762939453125"), // * 131072 #| (6, "3814697265625"), // * 262144 #| (6, "19073486328125"), // * 524288 #| (7, "95367431640625"), // * 1048576 #| (7, "476837158203125"), // * 2097152 #| (7, "2384185791015625"), // * 4194304 #| (7, "11920928955078125"), // * 8388608 #| (8, "59604644775390625"), // * 16777216 #| (8, "298023223876953125"), // * 33554432 #| (8, "1490116119384765625"), // * 67108864 #| (9, "7450580596923828125"), // * 134217728 #| (9, "37252902984619140625"), // * 268435456 #| (9, "186264514923095703125"), // * 536870912 #| (10, "931322574615478515625"), // * 1073741824 #| (10, "4656612873077392578125"), // * 2147483648 #| (10, "23283064365386962890625"), // * 4294967296 #| (10, "116415321826934814453125"), // * 8589934592 #| (11, "582076609134674072265625"), // * 17179869184 #| (11, "2910383045673370361328125"), // * 34359738368 #| (11, "14551915228366851806640625"), // * 68719476736 #| (12, "72759576141834259033203125"), // * 137438953472 #| (12, "363797880709171295166015625"), // * 274877906944 #| (12, "1818989403545856475830078125"), // * 549755813888 #| (13, "9094947017729282379150390625"), // * 1099511627776 #| (13, "45474735088646411895751953125"), // * 2199023255552 #| (13, "227373675443232059478759765625"), // * 4398046511104 #| (13, "1136868377216160297393798828125"), // * 8796093022208 #| (14, "5684341886080801486968994140625"), // * 17592186044416 #| (14, "28421709430404007434844970703125"), // * 35184372088832 #| (14, "142108547152020037174224853515625"), // * 70368744177664 #| (15, "710542735760100185871124267578125"), // * 140737488355328 #| (15, "3552713678800500929355621337890625"), // * 281474976710656 #| (15, "17763568394002504646778106689453125"), // * 562949953421312 #| (16, "88817841970012523233890533447265625"), // * 1125899906842624 #| (16, "444089209850062616169452667236328125"), // * 2251799813685248 #| (16, "2220446049250313080847263336181640625"), // * 4503599627370496 #| (16, "11102230246251565404236316680908203125"), // * 9007199254740992 #| (17, "55511151231257827021181583404541015625"), // * 18014398509481984 #| (17, "277555756156289135105907917022705078125"), // * 36028797018963968 #| (17, "1387778780781445675529539585113525390625"), // * 72057594037927936 #| (18, "6938893903907228377647697925567626953125"), // * 144115188075855872 #| (18, "34694469519536141888238489627838134765625"), // * 288230376151711744 #| (18, "173472347597680709441192448139190673828125"), // * 576460752303423488 #| (19, "867361737988403547205962240695953369140625"), // * 1152921504606846976 #|] #|fn new_digits(self : Decimal, s : Int) -> Int { #| let new_digits = left_shift_cheats[s].0 #| let cheat_num = left_shift_cheats[s].1 #| let mut less = false #| for i in 0..= self.digits_num { #| less = true #| break #| } #| let d = cheat_num.unsafe_charcode_at(i) - '0' #| if self.digits[i].to_int() != d { #| less = self.digits[i].to_int() < d #| break #| } #| } #| if less { #| new_digits - 1 #| } else { #| new_digits #| } #|} #|fn left_shift(self : Decimal, s : Int) -> Unit { #| let new_digits = self.new_digits(s) #| let mut read_index = self.digits_num #| let mut write_index = self.digits_num + new_digits #| let mut acc = 0L #| read_index -= 1 #| while read_index >= 0 { #| let d = self.digits[read_index].to_int64() #| acc += d << s #| let quo = acc / 10L #| let rem = (acc - quo * 10L).to_int() #| write_index -= 1 #| if write_index < self.digits.length() { #| self.digits[write_index] = rem.to_byte() #| } else if rem != 0 { #| self.truncated = true #| } #| acc = quo #| read_index -= 1 #| } #| while acc > 0L { #| let quo = acc / 10L #| let rem = (acc - 10L * quo).to_int() #| write_index -= 1 #| if write_index < self.digits.length() { #| self.digits[write_index] = rem.to_byte() #| } else if rem != 0 { #| self.truncated = true #| } #| acc = quo #| } #| self.digits_num += new_digits #| if self.digits_num > self.digits.length() { #| self.digits_num = self.digits.length() #| } #| self.decimal_point += new_digits #| self.trim() #|} #|fn trim(self : Decimal) -> Unit { #| while self.digits_num > 0 && self.digits[self.digits_num - 1] == 0 { #| self.digits_num -= 1 #| } #| if self.digits_num == 0 { #| self.decimal_point = 0 #| } #|} #|pub impl Show for Decimal with output(self, logger) { #| if self.digits_num == 0 { #| logger.write_char('0') #| return #| } #| if self.decimal_point <= 0 { #| logger.write_string("0.") #| for i in 0..<-self.decimal_point { #| logger.write_char('0') #| } #| for i in 0.. String { #| Show::to_string(self) #|} #|test "new" { #| let hpd = Decimal::from_int64_priv(1L) #| inspect(hpd.digits.length(), content="800") #| inspect(hpd.digits_num, content="1") #| inspect(hpd.decimal_point, content="1") #| inspect(hpd.negative, content="false") #| inspect(hpd.truncated, content="false") #|} #|test "from_int64" { #| let hpd = Decimal::from_int64_priv(123456789L) #| inspect(hpd.to_string(), content="123456789") #|} #|test "parse_decimal" { #| let s = "0.0000000000000000000000000000007888609052210118054117285652827862296732064351090230047702789306640625" #| assert_eq(parse_decimal_priv(s).to_string(), s) #| assert_eq(parse_decimal_priv("1.0e-10").to_string(), "0.0000000001") #|} #|test "to_string" { #| let hpd = Decimal::from_int64_priv(123456789L) #| hpd.decimal_point = 1 #| inspect(hpd.to_string(), content="1.23456789") #| hpd.decimal_point = 0 #| inspect(hpd.to_string(), content="0.123456789") #| hpd.decimal_point = -1 #| inspect(hpd.to_string(), content="0.0123456789") #| hpd.decimal_point = 10 #| inspect(hpd.to_string(), content="1234567890") #|} #|test "shift" { #| let tests : Array[_] = [ #| (0L, 100, "0"), #| (0L, -100, "0"), #| (1L, 100, "1267650600228229401496703205376"), #| ( #| 1L, -100, "0.0000000000000000000000000000007888609052210118054117285652827862296732064351090230047702789306640625", #| ), #| (12345678L, 8, "3160493568"), #| (12345678L, -8, "48225.3046875"), #| (195312L, 9, "99999744"), #| (1953125L, 9, "1000000000"), #| ] #| for i in 0.. Decimal { #| Decimal::new_priv() #|} #|#deprecated("Decimal will be changed to private. Use `@strconv.parse_double` instead") #|pub fn Decimal::from_int64(v : Int64) -> Decimal { #| Decimal::from_int64_priv(v) #|} #|#deprecated("use `@strconv.parse_double` instead") #|pub fn parse_decimal(str : @string.View) -> Decimal raise StrConvError { #| parse_decimal_from_view(str) #|} #|#deprecated("use `@strconv.parse_double` instead") #|pub fn Decimal::parse_decimal(str : @string.View) -> Decimal raise StrConvError { #| parse_decimal_from_view(str) #|} #|#deprecated("use `@strconv.parse_double` instead to avoid using this method.") #|pub fn to_double(self : Decimal) -> Double raise StrConvError { #| self.to_double_priv() #|} #|#deprecated("use `@strconv.parse_double` instead to avoid using this method.") #|pub fn shift(self : Decimal, s : Int) -> Unit { #| self.shift_priv(s) #|} ), "double.mbt": ( #|priv struct FloatInfo { #| mantissa_bits : Int #| exponent_bits : Int #| bias : Int #|} #|let double_info : FloatInfo = { #| mantissa_bits: 52, #| exponent_bits: 11, #| bias: -1023, #|} #|let mantissa_explicit_bits = 52 #|let min_exponent_fast_path : Int64 = -22L #|let max_exponent_fast_path : Int64 = 22L #|let max_exponent_disguised_fast_path : Int64 = 37L #|let max_mantissa_fast_path : UInt64 = 2UL << mantissa_explicit_bits #|pub fn parse_double(str : @string.View) -> Double raise StrConvError { #| if str.length() == 0 { #| syntax_err() #| } #| if !check_underscore(str) { #| syntax_err() #| } #| let (num, consumed) = match parse_number(str) { #| Some(r) => r #| None => #| match parse_inf_nan(str) { #| Some((num, consumed)) => #| if str.length() != consumed { #| syntax_err() #| } else { #| return num #| } #| None => syntax_err() #| } #| } #| if str.length() != consumed { #| syntax_err() #| } #| match num.try_fast_path() { #| Some(value) => value #| None => { #| let ret = parse_decimal_priv(str) #| ret.to_double_priv() #| } #| } #|} #|fn is_fast_path(self : Number) -> Bool { #| min_exponent_fast_path <= self.exponent && #| self.exponent <= max_exponent_disguised_fast_path && #| self.mantissa <= max_mantissa_fast_path && #| !self.many_digits #|} #|let table : FixedArray[Double] = [ #| 1.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0, 10000000.0, 100000000.0, #| 1000000000.0, 10000000000.0, 100000000000.0, 1000000000000.0, 10000000000000.0, #| 100000000000000.0, 1000000000000000.0, 10000000000000000.0, 100000000000000000.0, #| 1000000000000000000.0, 10000000000000000000.0, 100000000000000000000.0, 1000000000000000000000.0, #| 10000000000000000000000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, #|] #|fn pow10_fast_path(exponent : Int) -> Double { #| table[exponent & 31] #|} #|let int_pow10 : FixedArray[UInt64] = [ #| 1UL, 10UL, 100UL, 1000UL, 10000UL, 100000UL, 1000000UL, 10000000UL, 100000000UL, #| 1000000000UL, 10000000000UL, 100000000000UL, 1000000000000UL, 10000000000000UL, #| 100000000000000UL, 1000000000000000UL, #|] #|fn try_fast_path(self : Number) -> Double? { #| if self.is_fast_path() { #| let mut value = if self.exponent <= max_exponent_fast_path { #| let value = Double::convert_uint64(self.mantissa) #| if self.exponent < 0L { #| value / pow10_fast_path(-self.exponent.to_int()) #| } else { #| value * pow10_fast_path(self.exponent.to_int()) #| } #| } else { #| let shift = self.exponent - max_exponent_fast_path #| let mantissa = match #| checked_mul(self.mantissa, int_pow10[shift.to_int()]) { #| Some(m) => m #| None => return None #| } #| if mantissa > max_mantissa_fast_path { #| return None #| } #| Double::convert_uint64(mantissa) * #| pow10_fast_path(max_exponent_fast_path.to_int()) #| } #| if self.negative { #| value = -value #| } #| Some(value) #| } else { #| None #| } #|} #|test "parse_double" { #| let tests : Array[(String, Result[Double, String])] = [ #| ("", Err(syntax_err_str)), #| ("1x", Err(syntax_err_str)), #| ("1.1.", Err(syntax_err_str)), #| ("1e", Err(syntax_err_str)), #| ("1e-", Err(syntax_err_str)), #| (".e-1", Err(syntax_err_str)), #| ("1", Ok(1.0)), #| ("+1", Ok(1.0)), #| ("1e23", Ok(1.0e23)), #| ("1E23", Ok(1.0e23)), #| ("100000000000000000000000", Ok(1.0e23)), #| ("1e-100", Ok(1.0e-100)), #| ("123456700", Ok(1.234567e+08)), #| ("99999999999999974834176", Ok(9.999999999999997e+22)), #| ("100000000000000000000001", Ok(1.0000000000000001e+23)), #| ("100000000000000008388608", Ok(1.0000000000000001e+23)), #| ("100000000000000016777215", Ok(1.0000000000000001e+23)), #| ("100000000000000016777216", Ok(1.0000000000000003e+23)), #| ("-1", Ok(-1.0)), #| ("-0.1", Ok(-0.1)), #| ("-0", Ok(-0.0)), #| ("1e-20", Ok(1.0e-20)), #| ("625e-3", Ok(0.625)), #| ("6.62607015e-34", Ok(6.62607015e-34)), #| ("2.2250738585072012e-308", Ok(2.2250738585072014e-308)), #| ("2.2250738585072011e-308", Ok(2.225073858507201e-308)), #| ("0", Ok(0.0)), #| ("0e0", Ok(0.0)), #| ("-0e0", Ok(-0.0)), #| ("+0e0", Ok(0.0)), #| ("0e-0", Ok(0.0)), #| ("-0e-0", Ok(-0.0)), #| ("+0e-0", Ok(0.0)), #| ("0e+0", Ok(0.0)), #| ("-0e+0", Ok(-0.0)), #| ("+0e+0", Ok(0.0)), #| ("0e+01234567890123456789", Ok(0.0)), #| ("0.00e-01234567890123456789", Ok(0.0)), #| ("-0e+01234567890123456789", Ok(-0.0)), #| ("-0.00e-01234567890123456789", Ok(-0.0)), #| ("0e292", Ok(0.0)), #| ("0e347", Ok(0.0)), #| ("0e348", Ok(0.0)), #| ("-0e291", Ok(-0.0)), #| ("-0e292", Ok(-0.0)), #| ("-0e347", Ok(-0.0)), #| ("-0e348", Ok(-0.0)), #| ("1.7976931348623157e308", Ok(1.7976931348623157e308)), #| ("-1.7976931348623157e308", Ok(-1.7976931348623157e308)), #| ("1.7976931348623158e308", Ok(1.7976931348623157e308)), #| ("-1.7976931348623158e308", Ok(-1.7976931348623157e308)), #| ("1e308", Ok(1.0e308)), #| ( #| "1.7976931348623159e308", #| Err( #| range_err_str, #| ), #| ), #| ( #| "-1.7976931348623159e308", #| Err( #| range_err_str, #| ), #| ), #| ("2e308", Err(range_err_str)), #| ("1e309", Err(range_err_str)), #| ("1e310", Err(range_err_str)), #| ("1e400", Err(range_err_str)), #| ("1e40000", Err(range_err_str)), #| ("1e-305", Ok(1.0e-305)), #| ("1e-306", Ok(1.0e-306)), #| ("1e-307", Ok(1.0e-307)), #| ("1e-308", Ok(1.0e-308)), #| ("1e-309", Ok(1.0e-309)), #| ("1e-310", Ok(1.0e-310)), #| ("1e-322", Ok(1.0e-322)), #| ("5e-324", Ok(5.0e-324)), #| ("4e-324", Ok(5.0e-324)), #| ("3e-324", Ok(5.0e-324)), #| ("2e-324", Ok(0.0)), #| ("1e-350", Ok(0.0)), #| ("1e-400000", Ok(0.0)), #| ("1_23.50_0_0e+1_2", Ok(1.235e+14)), #| ("-_123.5e+12", Err(syntax_err_str)), #| ("+_123.5e+12", Err(syntax_err_str)), #| ("_123.5e+12", Err(syntax_err_str)), #| ("1__23.5e+12", Err(syntax_err_str)), #| ("123_.5e+12", Err(syntax_err_str)), #| ("123._5e+12", Err(syntax_err_str)), #| ("123.5_e+12", Err(syntax_err_str)), #| ("123.5__0e+12", Err(syntax_err_str)), #| ("123.5e_+12", Err(syntax_err_str)), #| ("123.5e+_12", Err(syntax_err_str)), #| ("123.5e_-12", Err(syntax_err_str)), #| ("123.5e-_12", Err(syntax_err_str)), #| ("123.5e+1__2", Err(syntax_err_str)), #| ("123.5e+12_", Err(syntax_err_str)), #| ] #| for i in 0.. Err(err) #| }, #| t.1, #| ) #| } #|} #|test "parse_double_inf" { #| assert_eq(parse_double("inf"), @double.infinity) #| assert_eq(parse_double("+Inf"), @double.infinity) #| assert_eq(parse_double("-Inf"), @double.neg_infinity) #| assert_eq(parse_double("+Infinity"), @double.infinity) #| assert_eq(parse_double("-Infinity"), @double.neg_infinity) #| assert_eq(parse_double("+INFINITY"), @double.infinity) #| assert_eq(parse_double("-INFINITY"), @double.neg_infinity) #|} #|test "parse_double_nan" { #| assert_true(parse_double("nan").is_nan()) #| assert_true(parse_double("NaN").is_nan()) #| assert_true(parse_double("NAN").is_nan()) #|} ), "errors.mbt": ( #|pub(all) suberror StrConvError String #|pub impl Show for StrConvError with output(self, logger) { #| match self { #| StrConvError(err) => logger.write_string(err) #| } #|} #|let range_err_str = "value out of range" #|let syntax_err_str = "invalid syntax" #|let base_err_str = "invalid base" #|fn[T] range_err() -> T raise StrConvError { #| raise StrConvError(range_err_str) #|} #|fn[T] syntax_err() -> T raise StrConvError { #| raise StrConvError(syntax_err_str) #|} #|fn[T] base_err() -> T raise StrConvError { #| raise StrConvError(base_err_str) #|} ), "int.mbt": ( #|const INT_MIN = 0x80000000 #|const INT_MAX = 0x7fffffff #|const INT64_MIN = -0x8000000000000000L #|const INT64_MAX = 0x7fffffffffffffffL #|fn check_and_consume_base( #| view : @string.View, #| base : Int, #|) -> (Int, @string.View, Bool) raise StrConvError { #| if base == 0 { #| match view { #| ['0', 'x' | 'X', .. rest] => (16, rest, true) #| ['0', 'o' | 'O', .. rest] => (8, rest, true) #| ['0', 'b' | 'B', .. rest] => (2, rest, true) #| _ => (10, view, false) #| } #| } else { #| match view { #| ['0', 'x' | 'X', .. rest] if base == 16 => (16, rest, true) #| ['0', 'o' | 'O', .. rest] if base == 8 => (8, rest, true) #| ['0', 'b' | 'B', .. rest] if base == 2 => (2, rest, true) #| _ => if base is (2..=36) { (base, view, false) } else { base_err() } #| } #| } #|} #|test { #| inspect(try? parse_int64("0b01", base=3), content="Err(invalid syntax)") #| inspect(try? parse_int64("0x01", base=3), content="Err(invalid syntax)") #| inspect(try? parse_int64("0o01", base=3), content="Err(invalid syntax)") #|} #|pub fn parse_int64( #| str : @string.View, #| base? : Int = 0, #|) -> Int64 raise StrConvError { #| guard str != "" else { syntax_err() } #| let (neg, rest) = match str.view() { #| ['+', .. rest] => (false, rest) #| ['-', .. rest] => (true, rest) #| rest => (false, rest) #| } #| let (num_base, rest, allow_underscore) = check_and_consume_base(rest, base) #| let overflow_threshold = overflow_threshold(num_base, neg) #| let has_digit = rest #| is (['0'..='9' | 'a'..='z' | 'A'..='Z', ..] #| | ['_', '0'..='9' | 'a'..='z' | 'A'..='Z', ..]) #| guard has_digit else { syntax_err() } #| loop (rest, 0L, allow_underscore) { #| (['_'], _, _) => #| syntax_err() #| (['_', ..], _, false) => syntax_err() #| (['_', .. rest], acc, true) => continue (rest, acc, false) #| ([c, .. rest], acc, _) => { #| let c = c.to_int() #| let d = match c { #| '0'..='9' => c - '0' #| 'a'..='z' => c + (10 - 'a') #| 'A'..='Z' => c + (10 - 'A') #| _ => syntax_err() #| } #| guard d < num_base else { syntax_err() } #| if neg { #| guard acc >= overflow_threshold else { range_err() } #| let next_acc = acc * num_base.to_int64() - d.to_int64() #| guard next_acc <= acc else { range_err() } #| continue (rest, next_acc, true) #| } else { #| guard acc < overflow_threshold else { range_err() } #| let next_acc = acc * num_base.to_int64() + d.to_int64() #| guard next_acc >= acc else { range_err() } #| continue (rest, next_acc, true) #| } #| } #| ([], acc, _) => acc #| } #|} #|pub fn parse_int(str : @string.View, base? : Int = 0) -> Int raise StrConvError { #| let n = parse_int64(str, base~) #| if n < INT_MIN.to_int64() || n > INT_MAX.to_int64() { #| range_err() #| } #| n.to_int() #|} #|fn check_underscore(str : @string.View) -> Bool { #| let rest = match str { #| ['+' | '-', .. rest] => rest #| rest => rest #| } #| let (rest, allow_underscore, hex) = match rest { #| ['0', 'x' | 'X', .. rest] => (rest, true, true) #| ['0', 'o' | 'O', .. rest] => (rest, true, false) #| ['0', 'b' | 'B', .. rest] => (rest, true, false) #| rest => (rest, false, false) #| } #| fn is_digit(c : Char) -> Bool { #| c is ('0'..='9') || (hex && c is ('a'..='f' | 'A'..='F')) #| } #| let follow_underscore = false #| loop (rest, allow_underscore, follow_underscore) { #| ([], _, _) => true #| (['_'], _, _) => false #| (['_', ..], false, _) => false #| (['_', .. rest], true, _) => continue (rest, false, true) #| ([c, .. rest], _, follow_underscore) => #| if is_digit(c) { #| continue (rest, true, false) #| } else if follow_underscore { #| false #| } else { #| continue (rest, false, false) #| } #| } #|} #|fn determine_base(s : String) -> Int { #| match s { #| ['0', 'x' | 'X', ..] => 16 #| ['0', 'o' | 'O', ..] => 8 #| ['0', 'b' | 'B', ..] => 2 #| _ => 10 #| } #|} #|fn overflow_threshold(base : Int, neg : Bool) -> Int64 { #| if !neg { #| if base == 10 { #| INT64_MAX / 10L + 1L #| } else if base == 16 { #| INT64_MAX / 16L + 1L #| } else { #| INT64_MAX / base.to_int64() + 1L #| } #| } else if base == 10 { #| INT64_MIN / 10L #| } else if base == 16 { #| INT64_MIN / 16L #| } else { #| INT64_MIN / base.to_int64() #| } #|} #|test "check_underscore" { #| assert_true(check_underscore("123")) #| assert_true(check_underscore("0x123")) #| assert_true(check_underscore("0o123")) #| assert_true(check_underscore("0b101")) #| assert_true(check_underscore("1_2_3")) #| assert_true(check_underscore("0x_1_2_3_A_F")) #| assert_true(check_underscore("0o_1_2_3")) #| assert_true(check_underscore("0b_1_0_1")) #| assert_false(check_underscore("1__2_3")) #| assert_false(check_underscore("_123")) #| assert_false(check_underscore("123_")) #|} #|test "determine_base" { #| inspect(determine_base("1234"), content="10") #| inspect(determine_base("0x1234"), content="16") #| inspect(determine_base("0X1234"), content="16") #| inspect(determine_base("0o1234"), content="8") #| inspect(determine_base("0O1234"), content="8") #| inspect(determine_base("0b1010"), content="2") #| inspect(determine_base("0B1010"), content="2") #|} #|test "parse_int64" { #| let tests : Array[(String, Result[Int64, String])] = [ #| ("", Err(syntax_err_str)), #| ("0", Ok(0L)), #| ("-0", Ok(0L)), #| ("+0", Ok(0L)), #| ("1", Ok(1L)), #| ("-1", Ok(-1L)), #| ("+1", Ok(1L)), #| ("12345", Ok(12345L)), #| ("-12345", Ok(-12345L)), #| ("012345", Ok(12345L)), #| ("-012345", Ok(-12345L)), #| ("9876543210", Ok(9876543210L)), #| ("-9876543210", Ok(-9876543210L)), #| ("9223372036854775807", Ok(9223372036854775807L)), #| ("-9223372036854775807", Ok(-9223372036854775807L)), #| ("9223372036854775808", Err(range_err_str)), #| ("-9223372036854775808", Ok(-9223372036854775808L)), #| ("9223372036854775809", Err(range_err_str)), #| ("-9223372036854775809", Err(range_err_str)), #| ("-1_2_3_4_5", Ok(-12345L)), #| ("-_12345", Err(syntax_err_str)), #| ("_12345", Err(syntax_err_str)), #| ("1__2345", Err(syntax_err_str)), #| ("12345_", Err(syntax_err_str)), #| ("12345%", Err(syntax_err_str)), #| ] #| for i in 0.. Err(err) #| }, #| t.1, #| ) #| } #|} #|test "parse_int64_base" { #| let tests : Array[(String, Int, Result[Int64, String])] = [ #| ("", 0, Err(syntax_err_str)), #| ("0", 0, Ok(0L)), #| ("-0", 0, Ok(0L)), #| ("1", 0, Ok(1L)), #| ("-1", 0, Ok(-1L)), #| ("12345", 0, Ok(12345L)), #| ("-12345", 0, Ok(-12345L)), #| ("012345", 0, Ok(12345L)), #| ("-012345", 0, Ok(-12345L)), #| ("0x12345", 0, Ok(0x12345L)), #| ("-0x12345", 0, Ok(-0x12345L)), #| ("9876543210", 0, Ok(9876543210L)), #| ("-9876543210", 0, Ok(-9876543210L)), #| ("9223372036854775807", 0, Ok(9223372036854775807L)), #| ("-9223372036854775807", 0, Ok(-9223372036854775807L)), #| ("9223372036854775808", 0, Err(range_err_str)), #| ("12345x", 0, Err(syntax_err_str)), #| ("-12345x", 0, Err(syntax_err_str)), #| ("-9223372036854775808", 0, Ok(-9223372036854775808L)), #| ("9223372036854775809", 0, Err(range_err_str)), #| ("-9223372036854775809", 0, Err(range_err_str)), #| ("h", 18, Ok(17L)), #| ("10", 25, Ok(25L)), #| ( #| "moonbit", #| 35, #| Ok( #| ( #| ((((22L * 35L + 24L) * 35L + 24L) * 35L + 23L) * 35L + 11L) * 35L + #| 18L #| ) * #| 35L + #| 29L, #| ), #| ), #| ( #| "moonbit", #| 36, #| Ok( #| ( #| ((((22L * 36L + 24L) * 36L + 24L) * 36L + 23L) * 36L + 11L) * 36L + #| 18L #| ) * #| 36L + #| 29L, #| ), #| ), #| ("0", 2, Ok(0L)), #| ("-1", 2, Ok(-1L)), #| ("1010", 2, Ok(10L)), #| ("1000000000000000", 2, Ok(1L << 15)), #| ( #| "111111111111111111111111111111111111111111111111111111111111111", #| 2, #| Ok((1L << 63) - 1L), #| ), #| ( #| "1000000000000000000000000000000000000000000000000000000000000000", #| 2, #| Err(range_err_str), #| ), #| ( #| "-1000000000000000000000000000000000000000000000000000000000000000", #| 2, #| Ok(-1L << 63), #| ), #| ( #| "-1000000000000000000000000000000000000000000000000000000000000001", #| 2, #| Err(range_err_str), #| ), #| ("-10", 8, Ok(-8L)), #| ("57635436545", 8, Ok(0o57635436545L)), #| ("100000000", 8, Ok(1L << 24)), #| ("10", 16, Ok(16L)), #| ("-123456789abcdef", 16, Ok(-0x123456789abcdefL)), #| ("7fffffffffffffff", 16, Ok((1L << 63) - 1L)), #| ("-0x_1_2_3_4_5", 0, Ok(-0x12345L)), #| ("0x_1_2_3_4_5", 0, Ok(0x12345L)), #| ("-_0x12345", 0, Err(syntax_err_str)), #| ("_-0x12345", 0, Err(syntax_err_str)), #| ("_0x12345", 0, Err(syntax_err_str)), #| ("0x__12345", 0, Err(syntax_err_str)), #| ("0x1__2345", 0, Err(syntax_err_str)), #| ("0x1234__5", 0, Err(syntax_err_str)), #| ("0x12345_", 0, Err(syntax_err_str)), #| ("-0_1_2_3_4_5", 0, Ok(-12345L)), #| ("0_1_2_3_4_5", 0, Ok(12345L)), #| ("-_012345", 0, Err(syntax_err_str)), #| ("_-012345", 0, Err(syntax_err_str)), #| ("_012345", 0, Err(syntax_err_str)), #| ("0__12345", 0, Err(syntax_err_str)), #| ("01234__5", 0, Err(syntax_err_str)), #| ("012345_", 0, Err(syntax_err_str)), #| ("+0xf", 0, Ok(0xfL)), #| ("-0xf", 0, Ok(-0xfL)), #| ("0x+f", 0, Err(syntax_err_str)), #| ("0x-f", 0, Err(syntax_err_str)), #| ] #| for i in 0.. Err(err) #| }, #| t.2, #| ) #| } #|} #|test "parse_int" { #| let tests : Array[(String, Result[Int, String])] = [ #| ("", Err(syntax_err_str)), #| ("0", Ok(0)), #| ("-0", Ok(0)), #| ("1", Ok(1)), #| ("-1", Ok(-1)), #| ("12345", Ok(12345)), #| ("-12345", Ok(-12345)), #| ("012345", Ok(12345)), #| ("-012345", Ok(-12345)), #| ("12345x", Err(syntax_err_str)), #| ("-12345x", Err(syntax_err_str)), #| ("987654321", Ok(987654321)), #| ("-987654321", Ok(-987654321)), #| ("2147483647", Ok((1 << 31) - 1)), #| ("-2147483647", Ok(-((1 << 31) - 1))), #| ("2147483648", Err(range_err_str)), #| ("-2147483648", Ok(-1 << 31)), #| ("2147483649", Err(range_err_str)), #| ("-2147483649", Err(range_err_str)), #| ("-1_2_3_4_5", Ok(-12345)), #| ("-_12345", Err(syntax_err_str)), #| ("_12345", Err(syntax_err_str)), #| ("1__2345", Err(syntax_err_str)), #| ("12345_", Err(syntax_err_str)), #| ("123%45", Err(syntax_err_str)), #| ] #| for i in 0.. Err(err) #| }, #| t.1, #| ) #| } #|} ), "number.mbt": ( #|let min_19digit_int : UInt64 = 100_0000_0000_0000_0000UL #|priv struct Number { #| exponent : Int64 #| mantissa : UInt64 #| negative : Bool #| many_digits : Bool #|} #|fn parse_digits(s : @string.View, x : UInt64) -> (@string.View, UInt64, Int) { #| s.fold_digits(x, (digit, acc : UInt64) => acc * 10UL + #| UInt64::extend_uint(digit.reinterpret_as_uint())) #|} #|fn try_parse_19digits( #| s : @string.View, #| x : UInt64, #|) -> (@string.View, UInt64, Int) { #| let mut x = x #| let mut len = 0 #| loop s { #| ['0'..='9' as ch, .. rest] if x < min_19digit_int => { #| len += 1 #| x = x * 10UL + #| UInt64::extend_uint((ch.to_int() - '0').reinterpret_as_uint()) // no overflows here #| continue rest #| } #| ['_', .. rest] => continue rest #| s => return (s, x, len) #| } #|} #|fn parse_scientific(s : @string.View) -> (@string.View, Int64)? { #| let mut s = match s.step(1) { #| Some(s) => s #| None => return None #| } #| let exp_num = 0L #| let mut neg_exp = false #| if s is ['+' | '-' as ch, .. rest] { #| neg_exp = ch == '-' #| s = rest #| } #| if s is ['0'..='9', ..] { #| let (s, exp_num, _) = s.fold_digits(exp_num, (digit, exp_num : Int64) => if exp_num < #| 0x10000L { #| 10L * exp_num + digit.to_int64() // no overflows here #| } else { #| exp_num #| }) #| if neg_exp { #| Some((s, -exp_num)) #| } else { #| Some((s, exp_num)) #| } #| } else { #| None #| } #|} #|fn parse_number(s : @string.View) -> (Number, Int)? { #| let mut s = s #| let start = s #| let mut negative = false #| if s is ['-', .. rest] { #| negative = true #| s = rest #| } else if s is ['+', .. rest] { #| s = rest #| } #| if s.is_empty() { #| return None #| } #| let (s, mantissa, consumed) = parse_digits(s, 0UL) #| let mut mantissa = mantissa #| let mut s = s #| let mut n_digits = consumed #| let mut n_after_dot = 0 #| let mut exponent = 0L #| if s is ['.', .. rest] { #| s = rest #| let (new_s, new_mantissa, consumed_digit) = parse_digits(s, mantissa) #| s = new_s #| mantissa = new_mantissa #| n_after_dot = consumed_digit #| exponent = -n_after_dot.to_int64() #| } #| n_digits += n_after_dot #| if n_digits == 0 { #| return None #| } #| let exp_number = 0L #| if s is ['e' | 'E', ..] { #| let (new_s, exp_number) = match parse_scientific(s) { #| Some(res) => res #| None => return None #| } #| s = new_s #| exponent += exp_number #| } #| let len = start.length() - s.length() #| if n_digits <= 19 { #| return Some(({ exponent, mantissa, negative, many_digits: false }, len)) #| } #| n_digits -= 19 #| let mut many_digits = false #| let mut p = start #| while p is ['0' | '.' as ch, .. rest] { #| n_digits -= (ch.to_int() - 46) / 2 // '0' = b'.' + 2 #| p = rest #| } #| let mut mantissa = mantissa #| if n_digits > 0 { #| many_digits = true #| mantissa = 0UL #| let s = start #| let (s, new_mantissa, consumed_digit) = try_parse_19digits(s, mantissa) #| mantissa = new_mantissa #| exponent = (if mantissa >= min_19digit_int { #| consumed_digit // big int #| } else { #| let s = match s.step(1) { #| Some(s) => s #| None => return None #| } // fractional component, skip the '.' #| let (_, new_mantissa, consumed_digit) = try_parse_19digits(s, mantissa) #| mantissa = new_mantissa #| consumed_digit #| }).to_int64() #| exponent += exp_number #| } // add back the explicit part #| Some(({ exponent, mantissa, negative, many_digits }, len)) #|} #|fn parse_inf_nan(s : @string.View) -> (Double, Int)? { #| let mut s = s #| let mut pos = true #| let mut len = 0 #| if s is ['-' | '+' as ch, .. rest] { #| pos = ch == '+' #| s = rest #| len += 1 #| } #| if s is ['n' | 'N', 'a' | 'A', 'n' | 'N', ..] { #| Some((@double.not_a_number, len + 3)) #| } else if s is ['i' | 'I', 'n' | 'N', 'f' | 'F', .. rest] { #| len += 3 #| if rest is ['i' | 'I', 'n' | 'N', 'i' | 'I', 't' | 'T', 'y' | 'Y', ..] { #| len += 5 #| } #| if pos { #| Some((@double.infinity, len)) #| } else { #| Some((@double.neg_infinity, len)) #| } #| } else { #| None #| } #|} #|fn checked_mul(a : UInt64, b : UInt64) -> UInt64? { #| if a == 0UL || b == 0UL { #| return Some(0UL) #| } #| if a == 1UL { #| return Some(b) #| } #| if b == 1UL { #| return Some(a) #| } #| if b.clz() == 0 || a.clz() == 0 { #| return None #| } #| let quotient : UInt64 = @uint64.max_value / b #| if a > quotient { #| return None #| } #| Some(a * b) #|} ), "string_view.mbt": ( #|fn @string.View::step(self : Self, step : Int) -> Self? { #| let mut step = step #| let mut str = self #| while str is [ch, .. rest] && step > 0 { #| if ch != '_' { #| step -= 1 #| } #| str = rest #| } #| if step == 0 { #| Some(str) #| } else { #| None #| } #|} #|fn[T] @string.View::fold_digits( #| self : Self, #| init : T, #| f : (Int, T) -> T, #|) -> (Self, T, Int) { #| let mut ret = init #| let mut len = 0 #| let mut str = self #| while str is [ch, .. rest] { #| if ch is ('0'..='9') { #| len += 1 #| ret = f(ch.to_int() - '0', ret) #| } else if ch != '_' { #| break #| } #| str = rest #| } #| (str, ret, len) #|} ), "traits.mbt": ( #|pub(open) trait FromStr { #| from_string(String) -> Self raise StrConvError #|} #|pub impl FromStr for Bool with from_string(str) { #| parse_bool(str) #|} #|pub impl FromStr for Int with from_string(str) { #| parse_int(str) #|} #|pub impl FromStr for Int64 with from_string(str) { #| parse_int64(str) #|} #|pub impl FromStr for UInt with from_string(str) { #| parse_uint(str) #|} #|pub impl FromStr for UInt64 with from_string(str) { #| parse_uint64(str) #|} #|pub impl FromStr for Double with from_string(str) { #| parse_double(str) #|} #|pub fn[A : FromStr] parse(str : String) -> A raise StrConvError { #| A::from_string(str) #|} #|test "parse" { #| let b : Bool = parse("true") #| inspect(b, content="true") #| let i : Int = parse("12345") #| inspect(i, content="12345") #| let i64 : Int64 = parse("9223372036854775807") #| assert_eq(i64, 9223372036854775807L) #| let ui : UInt = parse("4294967295") #| inspect(ui, content="4294967295") #| let ui64 : UInt64 = parse("18446744073709551615") #| assert_eq(ui64, 18446744073709551615UL) #| let d : Double = parse("1234.56789") #| assert_eq(d, 1234.56789) #|} ), "uint.mbt": ( #|const UINT_MAX : UInt = 0xffffffff #|const UINT64_MAX : UInt64 = 0xffffffffffffffffUL #|pub fn parse_uint64( #| str : @string.View, #| base? : Int = 0, #|) -> UInt64 raise StrConvError { #| guard str != "" else { syntax_err() } #| if str is ['+' | '-', ..] { #| syntax_err() #| } #| let (num_base, rest, allow_underscore) = check_and_consume_base(str, base) #| let overflow_threshold = match num_base { #| 10 => UINT64_MAX / 10 + 1 #| 16 => UINT64_MAX / 16 + 1 #| _ => UINT64_MAX / num_base.to_uint64() + 1 #| } #| let has_digit = rest #| is (['0'..='9' | 'a'..='z' | 'A'..='Z', ..] #| | ['_', '0'..='9' | 'a'..='z' | 'A'..='Z', ..]) #| guard has_digit else { syntax_err() } #| loop (rest, 0UL, allow_underscore) { #| (['_'], _, _) => #| syntax_err() #| (['_', ..], _, false) => syntax_err() #| (['_', .. rest], acc, true) => continue (rest, acc, false) #| ([c, .. rest], acc, _) => { #| let c = c.to_int() #| let d = match c { #| '0'..='9' => c - '0' #| 'a'..='z' => c + (10 - 'a') #| 'A'..='Z' => c + (10 - 'A') #| _ => syntax_err() #| } #| guard d < num_base else { syntax_err() } #| guard acc < overflow_threshold else { range_err() } #| let next_acc = acc * num_base.to_uint64() + d.to_uint64() #| guard next_acc >= acc && next_acc <= UINT64_MAX else { range_err() } #| continue (rest, next_acc, true) #| } #| ([], acc, _) => acc #| } #|} #|pub fn parse_uint( #| str : @string.View, #| base? : Int = 0, #|) -> UInt raise StrConvError { #| let n = parse_uint64(str, base~) #| if n > UINT_MAX.to_uint64() { #| range_err() #| } #| n.to_uint() #|} #|test "parse_uint64" { #| let tests : Array[(String, Result[UInt64, String])] = [ #| ("", Err(syntax_err_str)), #| ("0", Ok(0UL)), #| ("-0", Err(syntax_err_str)), #| ("+0", Err(syntax_err_str)), #| ("1", Ok(1UL)), #| ("-1", Err(syntax_err_str)), #| ("12345", Ok(12345UL)), #| ("-12345", Err(syntax_err_str)), #| ("012345", Ok(12345UL)), #| ("9876543210", Ok(9876543210UL)), #| ("18446744073709551615", Ok(18446744073709551615UL)), #| ("18446744073709551616", Err(range_err_str)), #| ("1_2_3_4_5", Ok(12345UL)), #| ("_12345", Err(syntax_err_str)), #| ("1__2345", Err(syntax_err_str)), #| ("12345_", Err(syntax_err_str)), #| ("12345%", Err(syntax_err_str)), #| ] #| for i in 0.. Err(err) #| }, #| t.1, #| ) #| } #|} #|test "parse_uint64_base" { #| let tests : Array[(String, Int, Result[UInt64, String])] = [ #| ("", 0, Err(syntax_err_str)), #| ("0", 0, Ok(0UL)), #| ("1", 0, Ok(1UL)), #| ("12345", 0, Ok(12345UL)), #| ("012345", 0, Ok(12345UL)), #| ("0x12345", 0, Ok(0x12345UL)), #| ("9876543210", 0, Ok(9876543210UL)), #| ("18446744073709551615", 0, Ok(UINT64_MAX)), #| ("0xffffffffffffffff", 0, Ok(UINT64_MAX)), #| ("18446744073709551616", 0, Err(range_err_str)), #| ("12345x", 0, Err(syntax_err_str)), #| ("-12345x", 0, Err(syntax_err_str)), #| ("h", 18, Ok(17UL)), #| ("10", 25, Ok(25UL)), #| ( #| "moonbit", #| 35, #| Ok( #| ( #| ((((22UL * 35UL + 24UL) * 35UL + 24UL) * 35UL + 23UL) * 35UL + 11UL) * #| 35UL + #| 18UL #| ) * #| 35UL + #| 29UL, #| ), #| ), #| ( #| "moonbit", #| 36, #| Ok( #| ( #| ((((22UL * 36UL + 24UL) * 36UL + 24UL) * 36UL + 23UL) * 36UL + 11UL) * #| 36UL + #| 18UL #| ) * #| 36UL + #| 29UL, #| ), #| ), #| ("0", 2, Ok(0UL)), #| ("-1", 2, Err(syntax_err_str)), #| ("1010", 2, Ok(10UL)), #| ("1000000000000000", 2, Ok(1UL << 15)), #| ( #| "1111111111111111111111111111111111111111111111111111111111111111", #| 2, #| Ok(UINT64_MAX), #| ), #| ( #| "1000000000000000000000000000000000000000000000000000000000000000", #| 2, #| Ok(1UL << 63), #| ), #| ("10", 8, Ok(8UL)), #| ("57635436545", 8, Ok(0o57635436545UL)), #| ("100000000", 8, Ok(1UL << 24)), #| ("10", 16, Ok(16UL)), #| ("ffffffffffffffff", 16, Ok(UINT64_MAX)), #| ("0x_1_2_3_4_5", 0, Ok(0x12345UL)), #| ("-_0x12345", 0, Err(syntax_err_str)), #| ("_-0x12345", 0, Err(syntax_err_str)), #| ("_0x12345", 0, Err(syntax_err_str)), #| ("0x__12345", 0, Err(syntax_err_str)), #| ("0x1__2345", 0, Err(syntax_err_str)), #| ("0x1234__5", 0, Err(syntax_err_str)), #| ("0x12345_", 0, Err(syntax_err_str)), #| ("0_1_2_3_4_5", 0, Ok(12345UL)), #| ("-_012345", 0, Err(syntax_err_str)), #| ("_-012345", 0, Err(syntax_err_str)), #| ("_012345", 0, Err(syntax_err_str)), #| ("0__12345", 0, Err(syntax_err_str)), #| ("01234__5", 0, Err(syntax_err_str)), #| ("012345_", 0, Err(syntax_err_str)), #| ("0xf", 0, Ok(0xfUL)), #| ("-0xf", 0, Err(syntax_err_str)), #| ("0x+f", 0, Err(syntax_err_str)), #| ("0x-f", 0, Err(syntax_err_str)), #| ] #| for i in 0.. Err(err) #| }, #| t.2, #| ) #| } #|} #|test "parse_uint" { #| let tests : Array[(String, Result[UInt, String])] = [ #| ("", Err(syntax_err_str)), #| ("0", Ok(0)), #| ("-0", Err(syntax_err_str)), #| ("+0", Err(syntax_err_str)), #| ("1", Ok(1)), #| ("-1", Err(syntax_err_str)), #| ("12345", Ok(12345)), #| ("012345", Ok(12345)), #| ("12345x", Err(syntax_err_str)), #| ("-12345x", Err(syntax_err_str)), #| ("987654321", Ok(987654321)), #| ("4294967295", Ok(UINT_MAX)), #| ("0xffffffff", Ok(UINT_MAX)), #| ("4294967296", Err(range_err_str)), #| ("1_2_3_4_5", Ok(12345)), #| ("-_12345", Err(syntax_err_str)), #| ("_12345", Err(syntax_err_str)), #| ("1__2345", Err(syntax_err_str)), #| ("12345_", Err(syntax_err_str)), #| ("123%45", Err(syntax_err_str)), #| ] #| for i in 0.. Err(err) #| }, #| t.1, #| ) #| } #|} #|test "parse_uint64 uppercase hex and invalid base" { #| inspect(try? parse_uint64("ABCD", base=16), content="Ok(43981)") #| inspect(try? parse_uint64("1234", base=37), content="Err(invalid base)") #|} ), }, ) ///| let moonbitlang_core_string_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/string", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/char": moonbitlang_core_char_module, }, files={ "moon.pkg.json": ( #|{ #| "import": ["moonbitlang/core/builtin", "moonbitlang/core/char"], #| "test-import": [ #| "moonbitlang/core/list", #| "moonbitlang/core/json", #| "moonbitlang/core/quickcheck" #| ], #| "targets": { #| "panic_test.mbt": ["not", "native", "llvm"] #| } #|} ), "deprecated.mbt": ( #|#deprecated("Use `@string.concat` instead") #|pub fn String::concat(self : Array[String], separator? : String = "") -> String { #| concat(self, separator~) #|} #|#deprecated("Use `Array::join` instead.") #|pub fn concat(strings : Array[String], separator? : String = "") -> String { #| match strings { #| [] => "" #| [hd, .. tl] => { #| let mut size_hint = hd.length() #| for s in tl { #| size_hint += s.length() + separator.length() #| } #| size_hint = size_hint << 1 #| let buf = StringBuilder::new(size_hint~) #| buf.write_string(hd) #| if separator == "" { #| for s in tl { #| buf.write_string(s) #| } #| } else { #| for s in tl { #| buf.write_string(separator) #| buf.write_string(s) #| } #| } #| buf.to_string() #| } #| } #|} #|#deprecated("Use `s.find(substr)` instead. If the optional argument `from` is not 0, take view from the string first. Please do not use an invalid `from` argument.") #|pub fn index_of(self : String, str : String, from? : Int = 0) -> Int { #| if from <= 0 { #| if self.find(str.view()) is Some(idx) { #| idx #| } else { #| -1 #| } #| } else if from > self.length() { #| if str.length() == 0 { #| self.length() #| } else { #| -1 #| } #| } else if self.view(start_offset=from).find(str.view()) is Some(idx) { #| idx + from #| } else { #| -1 #| } #|} #|#deprecated("Use `s.rev_find(substr)` instead. If the optional argument `from` is not 0, take view from the string first. Please do not use an invalid `from` argument.") #|pub fn last_index_of(self : String, str : String, from? : Int) -> Int { #| let from = if from is Some(f) { f } else { self.length() } #| if from >= self.length() { #| if self.rev_find(str.view()) is Some(idx) { #| idx #| } else { #| -1 #| } #| } else if from < 0 { #| if str.length() == 0 { #| self.length() #| } else { #| -1 #| } #| } else if self.view(end_offset=from).rev_find(str.view()) is Some(idx) { #| idx #| } else { #| -1 #| } #|} #|#deprecated("Use `s[i]` instead") #|pub fn View::charcode_at(self : View, index : Int) -> Int { #| guard index >= 0 && index < self.length() else { #| abort("Index out of bounds") #| } #| self.str().unsafe_charcode_at(self.start() + index) #|} #|#deprecated("Use `s.get_char(i).unwrap()` instead") #|pub fn View::char_at(self : View, index : Int) -> Char { #| self.get_char(index).unwrap() #|} #|#deprecated("Use `s.get_char(i).unwrap()` instead") #|pub fn String::char_at(self : String, offset : Int) -> Char { #| match self.get_char(offset) { #| Some(c) => c #| None => '�' #| } #|} ), "methods.mbt": ( #|pub fn View::find(self : View, str : View) -> Int? { #| if str.length() <= 4 { #| brute_force_find(self, str) #| } else { #| boyer_moore_horspool_find(self, str) #| } #|} #|fn brute_force_find(haystack : View, needle : View) -> Int? { #| let haystack_len = haystack.length() #| let needle_len = needle.length() #| guard needle_len > 0 else { return Some(0) } #| guard haystack_len >= needle_len else { return None } #| let needle_first = needle.unsafe_charcode_at(0) #| let forward_len = haystack_len - needle_len #| let mut i = 0 #| while i <= forward_len { #| while i <= forward_len && haystack.unsafe_charcode_at(i) != needle_first { #| i += 1 #| } #| if i <= forward_len { #| for j in 1.. Int? { #| let haystack_len = haystack.length() #| let needle_len = needle.length() #| guard needle_len > 0 else { return Some(0) } #| guard haystack_len >= needle_len else { return None } #| let skip_table = FixedArray::make(1 << 8, needle_len) #| for i in 0..<(needle_len - 1) { #| skip_table[needle.unsafe_charcode_at(i) & 0xFF] = needle_len - 1 - i #| } #| for i = 0 #| i <= haystack_len - needle_len #| i = i + skip_table[haystack.unsafe_charcode_at(i + needle_len - 1) & 0xFF] { #| for j in 0..=(needle_len - 1) { #| if haystack.unsafe_charcode_at(i + j) != needle.unsafe_charcode_at(j) { #| break #| } #| } else { #| return Some(i) #| } #| } #| None #|} #|test "boyer_moore_horspool_find edge cases" { #| inspect(boyer_moore_horspool_find("abc"[:], ""[:]), content="Some(0)") #| inspect(boyer_moore_horspool_find("ab"[:], "abcd"[:]), content="None") #|} #|test "boyer_moore_horspool_rev_find edge cases" { #| inspect(boyer_moore_horspool_rev_find("abc"[:], ""[:]), content="Some(3)") #| inspect(boyer_moore_horspool_rev_find("ab"[:], "abcd"[:]), content="None") #|} #|pub fn String::find(self : String, str : View) -> Int? { #| self[:].find(str) #|} #|test "find" { #| inspect("hello".find("o"), content="Some(4)") #| inspect("hello".find("l"), content="Some(2)") #| inspect("hello".find("hello"), content="Some(0)") #| inspect("hello".find("h"), content="Some(0)") #| inspect("hello".find(""), content="Some(0)") #| inspect("hello".find("world"), content="None") #| inspect("".find(""), content="Some(0)") #| inspect("".find("a"), content="None") #| inspect("hello hello".find("hello"), content="Some(0)") #| inspect("aaa".find("aa"), content="Some(0)") #| inspect("😀😀".find("😀"), content="Some(0)") #| inspect( #| ("😀😀aa".repeat(20) + "😀😀😀😀").find("😀😀😀😀"), #| content="Some(120)", #| ) #| inspect( #| ("😀😀😀😀" + "😀😀aa".repeat(20)).find("😀😀😀😀"), #| content="Some(0)", #| ) #|} #|pub fn View::find_by(self : View, pred : (Char) -> Bool) -> Int? { #| for i, c in self { #| if pred(c) { #| return Some(i) #| } #| } #| None #|} #|pub fn String::find_by(self : String, pred : (Char) -> Bool) -> Int? { #| self[:].find_by(pred) #|} #|test "find_by" { #| inspect("hello".find_by(c => c == 'o'), content="Some(4)") #| inspect("hello".find_by(c => c == 'l'), content="Some(2)") #| inspect("hello".find_by(c => c == 'z'), content="None") #| inspect("".find_by(c => c == 'a'), content="None") #| inspect("hello".find_by(c => c is ('0'..='9')), content="None") #| inspect("hello123".find_by(c => c is ('0'..='9')), content="Some(5)") #| inspect("hello".find_by(c => c is ('A'..='Z')), content="None") #| inspect("Hello".find_by(c => c is ('A'..='Z')), content="Some(0)") #| inspect("αβγ".find_by(c => c == 'β'), content="Some(1)") #| inspect("😀😁😂".find_by(c => c == '😂'), content="Some(2)") #|} #|pub fn View::rev_find(self : View, str : View) -> Int? { #| if str.length() <= 4 { #| brute_force_rev_find(self, str) #| } else { #| boyer_moore_horspool_rev_find(self, str) #| } #|} #|fn brute_force_rev_find(haystack : View, needle : View) -> Int? { #| let haystack_len = haystack.length() #| let needle_len = needle.length() #| guard needle_len > 0 else { return Some(haystack_len) } #| guard haystack_len >= needle_len else { return None } #| let needle_first = needle.unsafe_charcode_at(0) #| let mut i = haystack_len - needle_len #| while i >= 0 { #| while i >= 0 && haystack.unsafe_charcode_at(i) != needle_first { #| i -= 1 #| } #| if i >= 0 { #| for j in 1.. Int? { #| let haystack_len = haystack.length() #| let needle_len = needle.length() #| guard needle_len > 0 else { return Some(haystack_len) } #| guard haystack_len >= needle_len else { return None } #| let skip_table = FixedArray::make(1 << 8, needle_len) #| for i = needle_len - 1; i > 0; i = i - 1 { #| skip_table[needle.unsafe_charcode_at(i) & 0xFF] = i #| } #| for i = haystack_len - needle_len #| i >= 0 #| i = i - skip_table[haystack.unsafe_charcode_at(i) & 0xFF] { #| for j in 0.. Int? { #| self[:].rev_find(str) #|} #|test "rev_find" { #| inspect("hello".rev_find("o"), content="Some(4)") #| inspect("hello".rev_find("l"), content="Some(3)") #| inspect("hello".rev_find("hello"), content="Some(0)") #| inspect("hello".rev_find("h"), content="Some(0)") #| inspect("hello".rev_find(""), content="Some(5)") #| inspect("hello".rev_find("world"), content="None") #| inspect("".rev_find(""), content="Some(0)") #| inspect("".rev_find("a"), content="None") #| inspect("hello hello".rev_find("hello"), content="Some(6)") #| inspect("aaa".rev_find("aa"), content="Some(1)") #| inspect("😀😀".rev_find("😀"), content="Some(2)") #| inspect( #| ("😀😀aa".repeat(20) + "😀😀😀😀").rev_find("😀😀😀😀"), #| content="Some(120)", #| ) #| inspect( #| ("😀😀😀😀" + "😀😀aa".repeat(20)).rev_find("😀😀😀😀"), #| content="Some(4)", #| ) #|} #|pub fn View::has_suffix(self : View, str : View) -> Bool { #| self.rev_find(str) is Some(i) && i == self.length() - str.length() #|} #|pub fn String::has_suffix(self : String, str : View) -> Bool { #| self[:].has_suffix(str) #|} #|test "has_suffix" { #| inspect("hello".has_suffix("lo"), content="true") #| inspect("hello".has_suffix("hello"), content="true") #| inspect("hello".has_suffix(""), content="true") #| inspect("hello".has_suffix("world"), content="false") #| inspect("hello".has_suffix("hel"), content="false") #| inspect("".has_suffix(""), content="true") #| inspect("".has_suffix("a"), content="false") #| inspect("hello world".has_suffix("world"), content="true") #| inspect("😀😀".has_suffix("😀"), content="true") #| inspect("😀😀".has_suffix("😀😀"), content="true") #|} #|pub fn View::has_prefix(self : View, str : View) -> Bool { #| self.find(str) is Some(i) && i == 0 #|} #|pub fn String::has_prefix(self : String, str : View) -> Bool { #| self[:].has_prefix(str) #|} #|test "has_prefix" { #| inspect("hello".has_prefix("h"), content="true") #| inspect("hello".has_prefix("he"), content="true") #| inspect("hello".has_prefix(""), content="true") #| inspect("hello".has_prefix("world"), content="false") #| inspect("hello".has_prefix("lo"), content="false") #| inspect("".has_prefix(""), content="true") #| inspect("".has_prefix("a"), content="false") #| inspect("😀hello".has_prefix("😀"), content="true") #| inspect("😀😃hello".has_prefix("😀😃"), content="true") #| inspect("😀hello".has_prefix("😃"), content="false") #| inspect("hello😀".has_prefix("😀"), content="false") #|} #|#alias(ends_with, deprecated) #|pub fn strip_suffix(self : String, suffix : View) -> View? { #| if self.has_suffix(suffix) { #| Some(self.charcodes(end=self.length() - suffix.length())) #| } else { #| None #| } #|} #|test "strip_prefix" { #| inspect("hello world".strip_prefix("hello "), content="Some(\"world\")") #| inspect("hello world".strip_prefix("hi "), content="None") #| inspect("hello".strip_prefix("hello"), content="Some(\"\")") #| inspect("".strip_prefix(""), content="Some(\"\")") #| inspect("".strip_prefix("a"), content="None") #| inspect("abc".strip_prefix(""), content="Some(\"abc\")") #| inspect("😀hello".strip_prefix("😀"), content="Some(\"hello\")") #| inspect("😀😃hello".strip_prefix("😀😃"), content="Some(\"hello\")") #|} #|test "strip_suffix" { #| inspect("hello world".strip_suffix(" world"), content="Some(\"hello\")") #| inspect("hello world".strip_suffix(" moon"), content="None") #| inspect("hello".strip_suffix("hello"), content="Some(\"\")") #| inspect("".strip_suffix(""), content="Some(\"\")") #| inspect("".strip_suffix("a"), content="None") #| inspect("abc".strip_suffix(""), content="Some(\"abc\")") #| inspect("hello😀".strip_suffix("😀"), content="Some(\"hello\")") #| inspect("hello😀😃".strip_suffix("😀😃"), content="Some(\"hello\")") #|} #|#alias(starts_with, deprecated) #|pub fn strip_prefix(self : String, prefix : View) -> View? { #| if self.has_prefix(prefix) { #| Some(self.charcodes(start=prefix.length())) #| } else { #| None #| } #|} #|pub fn View::strip_prefix(self : View, prefix : View) -> View? { #| if self.has_prefix(prefix) { #| Some(self.view(start_offset=prefix.length())) #| } else { #| None #| } #|} #|pub fn View::strip_suffix(self : View, suffix : View) -> View? { #| if self.has_suffix(suffix) { #| Some(self.view(end_offset=self.length() - suffix.length())) #| } else { #| None #| } #|} #|pub fn View::to_array(self : View) -> Array[Char] { #| self #| .iter() #| .fold(init=Array::new(capacity=self.length()), (rv, c) => { #| rv.push(c) #| rv #| }) #|} #|pub fn View::to_bytes(self : View) -> Bytes { #| let array = FixedArray::make(self.length() * 2, Byte::default()) #| array.blit_from_string(0, self.data(), self.start_offset(), self.length()) #| array |> unsafe_to_bytes #|} #|test "View::strip_prefix" { #| let view = "hello world"[:] #| inspect(view.strip_prefix("hello "), content="Some(\"world\")") #| inspect(view.strip_prefix("hi "), content="None") #| inspect(view.strip_prefix("hello world"), content="Some(\"\")") #| inspect(view.strip_prefix(""), content="Some(\"hello world\")") #| let empty_view = ""[:] #| inspect(empty_view.strip_prefix(""), content="Some(\"\")") #| inspect(empty_view.strip_prefix("a"), content="None") #| let unicode_view = "😀hello😃"[:] #| inspect(unicode_view.strip_prefix("😀"), content="Some(\"hello😃\")") #| inspect(unicode_view.strip_prefix("😃"), content="None") #|} #|test "View::strip_suffix" { #| let view = "hello world"[:] #| inspect(view.strip_suffix(" world"), content="Some(\"hello\")") #| inspect(view.strip_suffix(" moon"), content="None") #| inspect(view.strip_suffix("hello world"), content="Some(\"\")") #| inspect(view.strip_suffix(""), content="Some(\"hello world\")") #| let empty_view = ""[:] #| inspect(empty_view.strip_suffix(""), content="Some(\"\")") #| inspect(empty_view.strip_suffix("a"), content="None") #| let unicode_view = "😀hello😃"[:] #| inspect(unicode_view.strip_suffix("😃"), content="Some(\"😀hello\")") #| inspect(unicode_view.strip_suffix("😀"), content="None") #|} #|test "View::to_array" { #| let view = "Hello🤣"[:] #| let chars = view.to_array() #| assert_eq(chars, ['H', 'e', 'l', 'l', 'o', '🤣']) #| let empty_view = ""[:] #| let empty_chars = empty_view.to_array() #| assert_eq(empty_chars, []) #| let sub_view = "Hello World"[6:11] // "World" #| let sub_chars = sub_view.to_array() #| assert_eq(sub_chars, ['W', 'o', 'r', 'l', 'd']) #|} #|test "View::to_bytes" { #| let view = "Hello"[:] #| let bytes = view.to_bytes() #| assert_eq(bytes.to_unchecked_string(), "Hello") #| let unicode_view = "🤣🤔"[:] #| let unicode_bytes = unicode_view.to_bytes() #| assert_eq(unicode_bytes.to_unchecked_string(), "🤣🤔") #| let sub_view = "Hello World"[0:5] // "Hello" #| let sub_bytes = sub_view.to_bytes() #| assert_eq(sub_bytes.to_unchecked_string(), "Hello") #|} #|pub fn View::contains(self : View, str : View) -> Bool { #| self.find(str) is Some(_) #|} #|pub fn contains(self : String, str : View) -> Bool { #| self[:].contains(str) #|} #|test "contains" { #| inspect("hello".contains("o"), content="true") #| inspect("hello".contains("l"), content="true") #| inspect("hello".contains("hello"), content="true") #| inspect("hello".contains("h"), content="true") #| inspect("hello".contains(""), content="true") #| inspect("hello".contains("world"), content="false") #| inspect("".contains(""), content="true") #| inspect("".contains("a"), content="false") #| inspect("hello hello".contains("hello"), content="true") #| inspect("aaa".contains("aa"), content="true") #| inspect("😀😀".contains("😀"), content="true") #|} #|pub fn View::contains_char(self : View, c : Char) -> Bool { #| let len = self.length() #| guard len > 0 else { return false } #| let c = c.to_int() #| if c <= 0xFFFF { #| for i in 0..= 2 else { return false } #| let adj = c - 0x10000 #| let high = 0xD800 + (adj >> 10) #| let low = 0xDC00 + (adj & 0x3FF) #| let mut i = 0 #| while i < len - 1 { #| if self.unsafe_charcode_at(i) == high { #| i += 1 #| if self.unsafe_charcode_at(i) == low { #| return true #| } #| } #| i += 1 #| } #| } #| false #|} #|pub fn contains_char(self : String, c : Char) -> Bool { #| self[:].contains_char(c) #|} #|test "contains_char" { #| inspect("hello".contains_char('h'), content="true") #| inspect("hello".contains_char('e'), content="true") #| inspect("hello".contains_char('l'), content="true") #| inspect("hello".contains_char('o'), content="true") #| inspect("hello".contains_char('x'), content="false") #| inspect("".contains_char('a'), content="false") #| inspect("hello world".contains_char(' '), content="true") #| inspect("hello world".contains_char('w'), content="true") #| inspect("😀😀".contains_char('😀'), content="true") #| inspect("😀😀".contains_char('😃'), content="false") #| inspect("hello".contains_char((104).unsafe_to_char()), content="true") // 'h' is 104 in ASCII #|} #|pub fn View::trim_start(self : View, char_set : View) -> View { #| loop self { #| [] as v => v #| [c, .. rest] as v => #| if char_set.contains_char(c) { #| continue rest #| } else { #| v #| } #| } #|} #|pub fn trim_start(self : String, char_set : View) -> View { #| self[:].trim_start(char_set) #|} #|test "trim_start" { #| inspect("hello".trim_start("h"), content="ello") #| inspect("hello".trim_start("he"), content="llo") #| inspect("hello".trim_start("eh"), content="llo") #| inspect("hello".trim_start("x"), content="hello") #| inspect("hello".trim_start(""), content="hello") #| inspect("".trim_start("a"), content="") #| inspect(" hello".trim_start(" "), content="hello") #| inspect("hello world".trim_start("helo"), content=" world") #| inspect("😀😀hello".trim_start("😀"), content="hello") #| inspect("😀😃hello".trim_start("😀😃"), content="hello") #| inspect("aaaabc".trim_start("a"), content="bc") #| inspect("aaaa".trim_start("a"), content="") #|} #|pub fn View::trim_end(self : View, char_set : View) -> View { #| loop self { #| [] as v => v #| [.. rest, c] as v => #| if char_set.contains_char(c) { #| continue rest #| } else { #| v #| } #| } #|} #|pub fn trim_end(self : String, char_set : View) -> View { #| self[:].trim_end(char_set) #|} #|test "trim_end" { #| inspect("hello".trim_end("o"), content="hell") #| inspect("hello".trim_end("lo"), content="he") #| inspect("hello".trim_end("x"), content="hello") #| inspect("hello".trim_end(""), content="hello") #| inspect("".trim_end("a"), content="") #| inspect("hello ".trim_end(" "), content="hello") #| inspect("hello world".trim_end("dlrow "), content="he") #| inspect("hello😀😀".trim_end("😀"), content="hello") #| inspect("hello😀😃".trim_end("😀😃"), content="hello") #| inspect("abcccc".trim_end("c"), content="ab") #| inspect("cccc".trim_end("c"), content="") #|} #|pub fn View::trim(self : View, char_set : View) -> View { #| self.trim_start(char_set).trim_end(char_set) #|} #|pub fn trim(self : String, char_set : View) -> View { #| self[:].trim(char_set) #|} #|test "trim" { #| inspect("hello".trim("h"), content="ello") #| inspect("hello".trim("o"), content="hell") #| inspect("hello".trim("ho"), content="ell") #| inspect("hello".trim("oh"), content="ell") #| inspect("hello".trim("x"), content="hello") #| inspect("hello".trim(""), content="hello") #| inspect("".trim("a"), content="") #| inspect(" hello ".trim(" "), content="hello") #| inspect("hello world".trim("hd"), content="ello worl") #| inspect("😀hello😀".trim("😀"), content="hello") #| inspect("😀😃hello😀😃".trim("😀😃"), content="hello") #| inspect("aaaabcaaa".trim("a"), content="bc") #| inspect("aaaa".trim("a"), content="") #| inspect(" hello world ".trim(" "), content="hello world") #| inspect("abcabc".trim("abc"), content="") #|} #|pub fn View::trim_space(self : View) -> View { #| self.trim(" \n\r\t") #|} #|pub fn trim_space(self : String) -> View { #| self[:].trim_space() #|} #|test "trim_space" { #| inspect("hello".trim_space(), content="hello") #| inspect(" hello ".trim_space(), content="hello") #| inspect("hello ".trim_space(), content="hello") #| inspect(" hello".trim_space(), content="hello") #| inspect("\t\nhello\r\n".trim_space(), content="hello") #| inspect(" hello world ".trim_space(), content="hello world") #| inspect(" ".trim_space(), content="") #| inspect("\n\r\t".trim_space(), content="") #| inspect("".trim_space(), content="") #| inspect(" hello\nworld\t".trim_space(), content="hello\nworld") #|} #|pub fn View::is_empty(self : View) -> Bool { #| self.length() == 0 #|} #|pub fn is_empty(self : String) -> Bool { #| self == "" #|} #|test "is_empty" { #| inspect("".is_empty(), content="true") #| inspect("hello".is_empty(), content="false") #| inspect(" ".is_empty(), content="false") #| inspect("\n".is_empty(), content="false") #| inspect("\t".is_empty(), content="false") #| inspect(" ".is_empty(), content="false") #| let s = "hello" #| let empty_view = s[0:0] #| let non_empty_view = s[0:3] #| inspect(empty_view.is_empty(), content="true") #| inspect(non_empty_view.is_empty(), content="false") #|} #|pub fn View::is_blank(self : View) -> Bool { #| self.trim_space().is_empty() #|} #|pub fn is_blank(self : String) -> Bool { #| self[:].is_blank() #|} #|test "is_blank" { #| inspect("".is_blank(), content="true") #| inspect("hello".is_blank(), content="false") #| inspect(" ".is_blank(), content="true") #| inspect("\n".is_blank(), content="true") #| inspect("\t".is_blank(), content="true") #| inspect(" ".is_blank(), content="true") #| inspect(" \n\t\r ".is_blank(), content="true") #| inspect("hello world".is_blank(), content="false") #| inspect(" hello ".is_blank(), content="false") #| let s = " hello " #| let blank_view = s[0:3] // " " #| let non_blank_view = s[3:8] // "hello" #| inspect(blank_view.is_blank(), content="true") #| inspect(non_blank_view.is_blank(), content="false") #|} #|pub fn View::pad_start( #| self : View, #| total_width : Int, #| padding_char : Char, #|) -> String { #| let len = self.length() #| guard len < total_width else { return self.to_string() } #| let padding = String::make(total_width - len, padding_char) #| [..padding, ..self] #|} #|pub fn pad_start( #| self : String, #| total_width : Int, #| padding_char : Char, #|) -> String { #| let len = self.length() #| guard len < total_width else { return self } #| let padding = String::make(total_width - len, padding_char) #| [..padding, ..self] #|} #|test "pad_start" { #| inspect("2".pad_start(3, '0'), content="002") #| inspect("abc".pad_start(5, 'x'), content="xxabc") #| inspect("hello".pad_start(4, ' '), content="hello") // No padding needed #| inspect("".pad_start(3, '-'), content="---") #| inspect("test".pad_start(8, '*'), content="****test") #| inspect("123".pad_start(6, '0'), content="000123") #| let s = "hello" #| let view = s[2:5] // "llo" #| inspect(view.pad_start(5, 'x'), content="xxllo") #| inspect("🌟".pad_start(3, '✨'), content="✨🌟") #| inspect("abc".pad_start(0, 'x'), content="abc") // width less than string length #| inspect("abc".pad_start(3, 'x'), content="abc") // width equal to string length #|} #|pub fn View::pad_end( #| self : View, #| total_width : Int, #| padding_char : Char, #|) -> String { #| let len = self.length() #| guard len < total_width else { return self.to_string() } #| let padding = String::make(total_width - len, padding_char) #| [..self, ..padding] #|} #|pub fn String::pad_end( #| self : String, #| total_width : Int, #| padding_char : Char, #|) -> String { #| let len = self.length() #| guard len < total_width else { return self } #| let padding = String::make(total_width - len, padding_char) #| [..self, ..padding] #|} #|test "pad_end" { #| inspect("2".pad_end(3, '0'), content="200") #| inspect("abc".pad_end(5, 'x'), content="abcxx") #| inspect("hello".pad_end(4, ' '), content="hello") // No padding needed #| inspect("".pad_end(3, '-'), content="---") #| inspect("test".pad_end(8, '*'), content="test****") #| inspect("123".pad_end(6, '0'), content="123000") #| let s = "hello" #| let view = s[2:5] // "llo" #| inspect(view.pad_end(5, 'x'), content="lloxx") #| inspect("🌟".pad_end(3, '✨'), content="🌟✨") #| inspect("abc".pad_end(0, 'x'), content="abc") // width less than string length #| inspect("abc".pad_end(3, 'x'), content="abc") // width equal to string length #|} #|pub fn View::repeat(self : View, n : Int) -> View { #| match n { #| _..=0 => "" #| 1 => self #| _ => { #| let len = self.length() #| let buf = StringBuilder::new(size_hint=len * n) #| let str = self.to_string() #| for _ in 0.. String { #| match n { #| _..=0 => "" #| 1 => self #| _ => { #| let len = self.length() #| let buf = StringBuilder::new(size_hint=len * n) #| let str = self.to_string() #| for _ in 0.. String { #| let buf = StringBuilder::new(size_hint=self.length()) #| for c in self.rev_iter() { #| buf.write_char(c) #| } #| buf.to_string() #|} #|pub fn rev(self : String) -> String { #| self[:].rev() #|} #|test "rev" { #| inspect("hello".rev(), content="olleh") #| inspect("".rev(), content="") #| inspect("abc".rev(), content="cba") #| inspect("😀😃".rev(), content="😃😀") #|} #|pub fn View::split(self : View, sep : View) -> Iter[View] { #| let sep_len = sep.length() #| if sep_len == 0 { #| return self.iter().map(c => c.to_string().view()) #| } #| Iter::new(yield_ => { #| let mut view = self #| while view.find(sep) is Some(end) { #| guard yield_(view.view(end_offset=end)) is IterContinue else { #| break IterEnd #| } #| view = view.view(start_offset=end + sep_len) #| } else { #| yield_(view) #| } #| }) #|} #|pub fn split(self : String, sep : View) -> Iter[View] { #| self[:].split(sep) #|} #|test "split" { #| assert_eq("a,b,c".split(",").map(View::to_string).collect(), ["a", "b", "c"]) #| assert_eq("a,b,c".split("").map(View::to_string).collect(), [ #| "a", ",", "b", ",", "c", #| ]) #| assert_eq( #| "apple::orange::banana".split("::").map(View::to_string).collect(), #| ["apple", "orange", "banana"], #| ) #| assert_eq("abc".split("").map(View::to_string).collect(), ["a", "b", "c"]) #| assert_eq("hello".split(",").map(View::to_string).collect(), ["hello"]) #| assert_eq(",a,b,c".split(",").map(View::to_string).collect(), [ #| "", "a", "b", "c", #| ]) #| assert_eq("a,b,c,".split(",").map(View::to_string).collect(), [ #| "a", "b", "c", "", #| ]) #| assert_eq("a,b,c".split("").map(View::to_string).collect(), [ #| "a", ",", "b", ",", "c", #| ]) #| assert_eq("".split("").map(View::to_string).collect(), []) #| assert_eq("".split(",").map(View::to_string).collect(), [""]) #| assert_eq("😀,😃,😄".split(",").map(View::to_string).collect(), [ #| "😀", "😃", "😄", #| ]) #| assert_eq("a😀b😀c".split("😀").map(View::to_string).collect(), [ #| "a", "b", "c", #| ]) #|} #|pub fn View::replace(self : View, old~ : View, new~ : View) -> View { #| match self.find(old) { #| Some(end) => #| [ #| ..self.view(end_offset=end), #| ..new, #| ..self.view(start_offset=end + old.length()), #| ] #| None => self #| } #|} #|pub fn replace(self : String, old~ : View, new~ : View) -> String { #| match self.find(old) { #| Some(end) => #| [ #| ..self.view(end_offset=end), #| ..new, #| ..self.view(start_offset=end + old.length()), #| ] #| None => self #| } #|} #|test "replace" { #| inspect("hello".replace(old="o", new="a"), content="hella") #| inspect("hello".replace(old="l", new="a"), content="healo") #| inspect("hello".replace(old="hello", new="a"), content="a") #| inspect("hello".replace(old="h", new="a"), content="aello") #| inspect("hello".replace(old="", new="a"), content="ahello") #| inspect("hello".replace(old="world", new="a"), content="hello") #| inspect("".replace(old="", new="a"), content="a") #|} #|pub fn View::replace_all(self : View, old~ : View, new~ : View) -> View { #| let len = self.length() #| let buf = StringBuilder::new(size_hint=len) #| let old_len = old.length() #| let new = new.to_string() #| if old_len == 0 { #| buf.write_string(new) #| for c in self { #| buf.write_char(c) #| buf.write_string(new) #| } #| buf.to_string() #| } else { #| let first_end = self.find(old) #| if first_end is Some(end) { #| for view = self, end = end { #| let seg = view.view(end_offset=end) #| buf.write_substring(seg.data(), seg.start_offset(), seg.length()) #| buf.write_string(new) #| guard end + old_len <= len else { break } #| let next_view = view.view(start_offset=end + old_len) #| guard next_view.find(old) is Some(next_end) else { #| buf.write_substring( #| next_view.data(), #| next_view.start_offset(), #| next_view.length(), #| ) #| break #| } #| continue next_view, next_end #| } #| buf.to_string() #| } else { #| self #| } #| } #|} #|pub fn replace_all(self : String, old~ : View, new~ : View) -> String { #| let len = self.length() #| let buf = StringBuilder::new(size_hint=len) #| let old_len = old.length() #| let new = new.to_string() #| if old_len == 0 { #| buf.write_string(new) #| for c in self { #| buf.write_char(c) #| buf.write_string(new) #| } #| buf.to_string() #| } else { #| let first_end = self.find(old) #| if first_end is Some(end) { #| for view = self[:], end = end { #| let seg = view.view(end_offset=end) #| buf.write_substring(seg.data(), seg.start_offset(), seg.length()) #| buf.write_string(new) #| guard end + old_len <= len else { break } #| let next_view = view.view(start_offset=end + old_len) #| guard next_view.find(old) is Some(next_end) else { #| buf.write_substring( #| next_view.data(), #| next_view.start_offset(), #| next_view.length(), #| ) #| break #| } #| continue next_view, next_end #| } #| buf.to_string() #| } else { #| self #| } #| } #|} #|test "replace_all" { #| assert_eq("hello".replace_all(old="o", new="a"), "hella") #| assert_eq("hello".replace_all(old="l", new="a"), "heaao") #| assert_eq("hello".replace_all(old="ll", new="rr"), "herro") #| assert_eq("hello".replace_all(old="hello", new="world"), "world") #| assert_eq("hello hello hello".replace_all(old="hello", new="hi"), "hi hi hi") #| assert_eq( #| "hello hello helloi".replace_all(old="hello", new="hi"), #| "hi hi hii", #| ) #| assert_eq( #| "hi hi hii".replace_all(old="hi", new="hello"), #| "hello hello helloi", #| ) #| assert_eq("hello".replace_all(old="", new="a"), "ahaealalaoa") #| assert_eq("hello".replace_all(old="world", new="a"), "hello") #| assert_eq("".replace_all(old="", new="a"), "a") #| assert_eq("aaa".replace_all(old="a", new="b"), "bbb") #| assert_eq("aaa".replace_all(old="a", new="bb"), "bbbbbb") #| assert_eq("aaa".replace_all(old="aa", new="b"), "ba") #| assert_eq("🤣🤣🤣".replace_all(old="🤣", new="😊"), "😊😊😊") #| assert_eq("abc123abc".replace_all(old="abc", new="xyz"), "xyz123xyz") #| assert_eq("abcabcabc".replace_all(old="abc", new=""), "") #| assert_eq("abc".replace_all(old="abc", new=""), "") #| assert_eq("abc".replace_all(old="", new="x"), "xaxbxcx") #|} #|test "View::replace_all" { #| assert_eq("hello"[:].replace_all(old="o", new="a"), "hella") #| assert_eq("hello"[:].replace_all(old="l", new="a"), "heaao") #| assert_eq("hello"[:].replace_all(old="ll", new="rr"), "herro") #| assert_eq("hello"[:].replace_all(old="hello", new="world"), "world") #| assert_eq( #| "hello hello hello"[:].replace_all(old="hello", new="hi"), #| "hi hi hi", #| ) #| assert_eq( #| "hello hello helloi"[:].replace_all(old="hello", new="hi"), #| "hi hi hii", #| ) #| assert_eq( #| "hi hi hii"[:].replace_all(old="hi", new="hello"), #| "hello hello helloi", #| ) #| assert_eq("hello"[:].replace_all(old="", new="a"), "ahaealalaoa") #| assert_eq("hello"[:].replace_all(old="world", new="a"), "hello") #| assert_eq(""[:].replace_all(old="", new="a"), "a") #| assert_eq("aaa"[:].replace_all(old="a", new="b"), "bbb") #| assert_eq("aaa"[:].replace_all(old="a", new="bb"), "bbbbbb") #| assert_eq("aaa"[:].replace_all(old="aa", new="b"), "ba") #| assert_eq( #| "🤣🤣🤣"[:].replace_all(old="🤣", new="😊"), #| "😊😊😊", #| ) #| assert_eq("abc123abc"[:].replace_all(old="abc", new="xyz"), "xyz123xyz") #| assert_eq("abcabcabc"[:].replace_all(old="abc", new=""), "") #| assert_eq("abc"[:].replace_all(old="abc", new=""), "") #| assert_eq("abc"[:].replace_all(old="", new="x"), "xaxbxcx") #|} #|pub fn View::to_lower(self : View) -> View { #| guard self.find_by(x => x.is_ascii_uppercase()) is Some(idx) else { #| return self #| } #| let buf = StringBuilder::new(size_hint=self.length()) #| let head = self.view(end_offset=idx) #| buf.write_substring(head.data(), head.start_offset(), head.length()) #| for c in self.view(start_offset=idx) { #| if c.is_ascii_uppercase() { #| buf.write_char((c.to_int() + 32).unsafe_to_char()) #| } else { #| buf.write_char(c) #| } #| } #| buf.to_string() #|} #|pub fn to_lower(self : String) -> String { #| guard self.find_by(x => x.is_ascii_uppercase()) is Some(idx) else { #| return self #| } #| let buf = StringBuilder::new(size_hint=self.length()) #| let head = self.view(end_offset=idx) #| buf.write_substring(head.data(), head.start_offset(), head.length()) #| for c in self.view(start_offset=idx) { #| if c.is_ascii_uppercase() { #| buf.write_char((c.to_int() + 32).unsafe_to_char()) #| } else { #| buf.write_char(c) #| } #| } #| buf.to_string() #|} #|test "to_lower" { #| assert_eq("Hello".to_lower(), "hello") #| assert_eq("HELLO".to_lower(), "hello") #| assert_eq("Hello, World!".to_lower(), "hello, world!") #|} #|test "View::to_lower" { #| assert_eq("Hello"[:].to_lower(), "hello") #| assert_eq("HELLO"[:].to_lower(), "hello") #| assert_eq("Hello, World!"[:].to_lower(), "hello, world!") #|} #|pub fn View::to_upper(self : View) -> View { #| guard self.find_by(_.is_ascii_lowercase()) is Some(idx) else { return self } #| let buf = StringBuilder::new(size_hint=self.length()) #| let head = self.view(end_offset=idx) #| buf.write_substring(head.data(), head.start_offset(), head.length()) #| for c in self.view(start_offset=idx) { #| if c.is_ascii_lowercase() { #| buf.write_char((c.to_int() - 32).unsafe_to_char()) #| } else { #| buf.write_char(c) #| } #| } #| buf.to_string() #|} #|pub fn to_upper(self : String) -> String { #| guard self.find_by(_.is_ascii_lowercase()) is Some(idx) else { return self } #| let buf = StringBuilder::new(size_hint=self.length()) #| let head = self.view(end_offset=idx) #| buf.write_substring(head.data(), head.start_offset(), head.length()) #| for c in self.view(start_offset=idx) { #| if c.is_ascii_lowercase() { #| buf.write_char((c.to_int() - 32).unsafe_to_char()) #| } else { #| buf.write_char(c) #| } #| } #| buf.to_string() #|} #|test "to_upper" { #| assert_eq("hello".to_upper(), "HELLO") #| assert_eq("HELLO".to_upper(), "HELLO") #| assert_eq("Hello, World!".to_upper(), "HELLO, WORLD!") #|} #|test "View::to_upper" { #| assert_eq("hello"[:].to_upper(), "HELLO") #| assert_eq("HELLO"[:].to_upper(), "HELLO") #| assert_eq("Hello, World!"[:].to_upper(), "HELLO, WORLD!") #|} #|pub fn[A] View::fold(self : View, init~ : A, f : (A, Char) -> A) -> A { #| let mut rv = init #| for c in self { #| rv = f(rv, c) #| } #| rv #|} #|pub fn[A] fold(self : String, init~ : A, f : (A, Char) -> A) -> A { #| self[:].fold(init~, f) #|} #|test "fold" { #| assert_eq( #| "hello".fold(init=[], (acc, c) => { #| acc.push(c) #| acc #| }), #| ['h', 'e', 'l', 'l', 'o'], #| ) #| assert_eq( #| "hello".fold(init=0, (acc, c) => acc + c.to_int()), #| 104 + 101 + 108 + 108 + 111, #| ) #|} #|pub fn[A] View::rev_fold(self : View, init~ : A, f : (A, Char) -> A) -> A { #| let mut rv = init #| for c in self.rev_iter() { #| rv = f(rv, c) #| } #| rv #|} #|pub fn[A] rev_fold(self : String, init~ : A, f : (A, Char) -> A) -> A { #| self[:].rev_fold(init~, f) #|} #|test "rev_fold" { #| assert_eq( #| "hello".rev_fold(init=[], (acc, c) => { #| acc.push(c) #| acc #| }), #| ['o', 'l', 'l', 'e', 'h'], #| ) #| assert_eq( #| "hello".rev_fold(init=0, (acc, c) => acc + c.to_int()), #| 111 + 108 + 108 + 101 + 104, #| ) #|} #|pub fn String::get(self : String, idx : Int) -> Int? { #| guard idx >= 0 && idx < self.length() else { return None } #| Some(self.unsafe_charcode_at(idx)) #|} #|pub fn View::get(self : View, idx : Int) -> Int? { #| guard idx >= 0 && idx < self.length() else { return None } #| Some(self.unsafe_charcode_at(idx)) #|} #|test "String::get supports emoji (surrogate pair)" { #| let s = "hello" #| inspect(s.get(0), content="Some(104)") #| inspect(s.get(4), content="Some(111)") #| inspect(s.get(5), content="None") #| inspect(s.get(-1), content="None") #| let s = "a🤣b" #| inspect(s.get(0), content="Some(97)") #| inspect(s.get(1), content="Some(55358)") #| inspect(s.get(2), content="Some(56611)") #| inspect(s.get(3), content="Some(98)") #| inspect(s.get(4), content="None") #|} #|test "View::get basic cases" { #| let v = "hello"[1:-1] #| inspect(v.get(0), content="Some(101)") #| inspect(v.get(2), content="Some(108)") #| inspect(v.get(3), content="None") #| inspect(v.get(-1), content="None") #| let v = "ab🤣cd"[1:-1] #| inspect(v.get(0), content="Some(98)") #| inspect(v.get(1), content="Some(55358)") #| inspect(v.get(2), content="Some(56611)") #|} #|pub fn String::get_char(self : String, idx : Int) -> Char? { #| guard idx >= 0 && idx < self.length() else { return None } #| let c = self.unsafe_charcode_at(idx) #| if c.is_leading_surrogate() { #| guard idx + 1 < self.length() else { return None } #| let next = self.unsafe_charcode_at(idx + 1) #| if next.is_trailing_surrogate() { #| Some(code_point_of_surrogate_pair(c, next)) #| } else { #| None #| } #| } else if c.is_trailing_surrogate() { #| None #| } else { #| Some(c.unsafe_to_char()) #| } #|} #|pub fn View::get_char(self : View, idx : Int) -> Char? { #| guard idx >= 0 && idx < self.length() else { return None } #| let c = self.unsafe_charcode_at(idx) #| if c.is_leading_surrogate() { #| guard idx + 1 < self.length() else { return None } #| let next = self.unsafe_charcode_at(idx + 1) #| if next.is_trailing_surrogate() { #| Some(code_point_of_surrogate_pair(c, next)) #| } else { #| None #| } #| } else if c.is_trailing_surrogate() { #| None #| } else { #| Some(c.unsafe_to_char()) #| } #|} #|test "String::get_char basic cases" { #| let s = "hello" #| inspect(s.get_char(0), content="Some('h')") #| inspect(s.get_char(1), content="Some('e')") #| inspect(s.get_char(4), content="Some('o')") #| inspect(s.get_char(5), content="None") #| inspect(s.get_char(-1), content="None") #| let s = "a🤣b" #| inspect(s.get_char(0), content="Some('a')") #| inspect(s.get_char(1), content="Some('🤣')") #| inspect(s.get_char(2), content="None") // Second half of surrogate pair is not a valid char #| inspect(s.get_char(3), content="Some('b')") #| inspect(s.get_char(4), content="None") #|} #|test "View::get_char basic cases" { #| let s = "a🤣b" #| let v = s[0:-1] #| inspect(v.get_char(0), content="Some('a')") #| inspect(v.get_char(1), content="Some('🤣')") #| inspect(v.get_char(2), content="None") #| inspect(v.get_char(3), content="None") #| inspect(v.get_char(4), content="None") #| let v2 = s[1:3] // Only contains the emoji surrogate pair #| inspect(v2.get_char(0), content="Some('🤣')") #| inspect(v2.get_char(1), content="None") #| inspect(v2.get_char(2), content="None") #|} ), "string.mbt": ( #|pub fn String::from_array(chars : Array[Char]) -> String { #| let buf = StringBuilder::new(size_hint=chars.length() * 4) #| for c in chars { #| buf.write_char(c) #| } #| buf.to_string() #|} #|pub fn from_array(chars : Array[Char]) -> String { #| String::from_array(chars) #|} #|pub fn String::from_iter(iter : Iter[Char]) -> String { #| let chars = iter.collect() #| String::from_array(chars) #|} #|pub fn from_iter(iter : Iter[Char]) -> String { #| let chars = iter.collect() #| String::from_array(chars) #|} #|pub impl Compare for String with compare(self, other) { #| let len = self.length() #| match len.compare(other.length()) { #| 0 => { #| for i in 0.. order #| } #|} #|pub impl Default for String with default() { #| "" #|} #|pub fn default() -> String { #| "" #|} #|pub fn to_bytes(self : String) -> Bytes { #| let array = FixedArray::make(self.length() * 2, Byte::default()) #| array.blit_from_string(0, self, 0, self.length()) #| array |> unsafe_to_bytes #|} #|fn unsafe_to_bytes(array : FixedArray[Byte]) -> Bytes = "%identity" #|pub fn to_array(self : String) -> Array[Char] { #| self #| .iter() #| .fold(init=Array::new(capacity=self.length()), (rv, c) => { #| rv.push(c) #| rv #| }) #|} #|pub fn iter(self : String) -> Iter[Char] { #| Iter::new(yield_ => { #| let len = self.length() #| for index in 0.. Iter2[Int, Char] { #| Iter2::new(yield_ => { #| let len = self.length() #| for index = 0, n = 0; index < len; index = index + 1, n = n + 1 { #| let c1 = self.unsafe_charcode_at(index) #| if c1.is_leading_surrogate() && index + 1 < len { #| let c2 = self.unsafe_charcode_at(index + 1) #| if c2.is_trailing_surrogate() { #| let c = code_point_of_surrogate_pair(c1, c2) #| guard yield_(n, c) is IterContinue else { break IterEnd } #| continue index + 2, n + 1 #| } #| } #| guard yield_(n, c1.unsafe_to_char()) is IterContinue else { #| break IterEnd #| } #| } else { #| IterContinue #| } #| }) #|} #|pub fn rev_iter(self : String) -> Iter[Char] { #| Iter::new(yield_ => { #| let len = self.length() #| for index = len - 1; index >= 0; index = index - 1 { #| let c1 = self.unsafe_charcode_at(index) #| if c1.is_trailing_surrogate() && index - 1 >= 0 { #| let c2 = self.unsafe_charcode_at(index - 1) #| if c2.is_leading_surrogate() { #| let c = code_point_of_surrogate_pair(c2, c1) #| guard yield_(c) is IterContinue else { break IterEnd } #| continue index - 2 #| } #| } #| guard yield_(c1.unsafe_to_char()) is IterContinue else { break IterEnd } #| } else { #| IterContinue #| } #| }) #|} #|fn String::offset_of_nth_char_forward( #| self : String, #| n : Int, #| start_offset~ : Int, #| end_offset~ : Int, #|) -> Int? { #| guard start_offset >= 0 && start_offset <= end_offset else { #| abort("Invalid start index") #| } #| let mut utf16_offset = start_offset #| let mut char_count = 0 #| while utf16_offset < end_offset && char_count < n { #| let c = self.unsafe_charcode_at(utf16_offset) #| if c.is_leading_surrogate() { #| utf16_offset = utf16_offset + 2 #| } else { #| utf16_offset = utf16_offset + 1 #| } #| char_count = char_count + 1 #| } #| if char_count < n || utf16_offset >= end_offset { #| None #| } else { #| Some(utf16_offset) #| } #|} #|fn String::offset_of_nth_char_backward( #| self : String, #| n : Int, #| start_offset~ : Int, #| end_offset~ : Int, #|) -> Int? { #| let mut char_count = 0 #| let mut utf16_offset = end_offset #| while utf16_offset - 1 >= start_offset && char_count < n { #| let c = self.unsafe_charcode_at(utf16_offset - 1) #| if c.is_trailing_surrogate() { #| utf16_offset = utf16_offset - 2 #| } else { #| utf16_offset = utf16_offset - 1 #| } #| char_count = char_count + 1 #| } #| if char_count < n || utf16_offset < start_offset { #| None #| } else { #| Some(utf16_offset) #| } #|} #|pub fn String::offset_of_nth_char( #| self : String, #| i : Int, #| start_offset? : Int = 0, #| end_offset? : Int, #|) -> Int? { #| let end_offset = if end_offset is Some(o) { o } else { self.length() } #| if i >= 0 { #| self.offset_of_nth_char_forward(i, start_offset~, end_offset~) #| } else { #| self.offset_of_nth_char_backward(-i, start_offset~, end_offset~) #| } #|} #|pub fn String::char_length_eq( #| self : String, #| len : Int, #| start_offset? : Int = 0, #| end_offset? : Int, #|) -> Bool { #| let end_offset = if end_offset is Some(o) { o } else { self.length() } #| for index = start_offset, count = 0 #| index < end_offset && count < len #| index = index + 1, count = count + 1 { #| let c1 = self.unsafe_charcode_at(index) #| if c1.is_leading_surrogate() && index + 1 < end_offset { #| let c2 = self.unsafe_charcode_at(index + 1) #| if c2.is_trailing_surrogate() { #| continue index + 2, count + 1 #| } else { #| abort("invalid surrogate pair") #| } #| } #| } else { #| count == len && index == end_offset #| } #|} #|pub fn String::char_length_ge( #| self : String, #| len : Int, #| start_offset? : Int = 0, #| end_offset? : Int, #|) -> Bool { #| let end_offset = if end_offset is Some(o) { o } else { self.length() } #| for index = start_offset, count = 0 #| index < end_offset && count < len #| index = index + 1, count = count + 1 { #| let c1 = self.unsafe_charcode_at(index) #| if c1.is_leading_surrogate() && index + 1 < end_offset { #| let c2 = self.unsafe_charcode_at(index + 1) #| if c2.is_trailing_surrogate() { #| continue index + 2, count + 1 #| } else { #| abort("invalid surrogate pair") #| } #| } #| } else { #| count >= len #| } #|} ), "string_like.mbt": ( #|pub trait ToStringView { #| to_string_view(Self) -> View #|} #|pub impl ToStringView for String with to_string_view(self) -> View { #| self[:] #|} #|pub impl ToStringView for View with to_string_view(self) -> View { #| self #|} ), "utils.mbt": ( #|fn code_point_of_surrogate_pair(leading : Int, trailing : Int) -> Char { #| ((leading - 0xD800) * 0x400 + trailing - 0xDC00 + 0x10000).unsafe_to_char() #|} #|test "code_point_of_surrogate_pair" { #| let s = "😀" #| let leading = s.charcode_at(0) #| let trailing = s.charcode_at(1) #| inspect(code_point_of_surrogate_pair(leading, trailing), content="😀") #|} #|test "is_leading_surrogate" { #| inspect("🤣".charcode_at(0).is_leading_surrogate(), content="true") #| inspect("🤣".charcode_at(1).is_leading_surrogate(), content="false") #|} #|test "is_trailing_surrogate" { #| inspect("🤣".charcode_at(0).is_trailing_surrogate(), content="false") #| inspect("🤣".charcode_at(1).is_trailing_surrogate(), content="true") #|} #|test "is_surrogate" { #| inspect((0xD800).is_surrogate(), content="true") // Leading surrogate #| inspect((0xDBFF).is_surrogate(), content="true") // Leading surrogate #| inspect((0xDC00).is_surrogate(), content="true") // Trailing surrogate #| inspect((0xDFFF).is_surrogate(), content="true") // Trailing surrogate #| inspect((0xD7FF).is_surrogate(), content="false") // Just before surrogates #| inspect((0xE000).is_surrogate(), content="false") // Just after surrogates #| inspect((0x41).is_surrogate(), content="false") // Regular ASCII 'A' #|} ), "view.mbt": ( #|#builtin.valtype #|type View #|fn View::str(self : View) -> String = "%stringview.str" #|fn View::start(self : View) -> Int = "%stringview.start" #|fn View::end(self : View) -> Int = "%stringview.end" #|fn View::make_view(str : String, start : Int, end : Int) -> View = "%stringview.make" #|pub fn View::op_get(self : View, index : Int) -> Int { #| guard index >= 0 && index < self.length() else { #| abort("Index out of bounds") #| } #| self.str().unsafe_charcode_at(self.start() + index) #|} #|pub fn data(self : View) -> String { #| self.str() #|} #|pub fn start_offset(self : View) -> Int { #| self.start() #|} #|pub fn length(self : View) -> Int { #| self.end() - self.start() #|} #|pub fn String::view( #| self : String, #| start_offset? : Int = 0, #| end_offset? : Int, #|) -> View { #| let end_offset = if end_offset is Some(o) { o } else { self.length() } #| guard start_offset >= 0 && #| start_offset <= end_offset && #| end_offset <= self.length() else { #| abort("Invalid index for View") #| } #| View::make_view(self, start_offset, end_offset) #|} #|pub fn View::view( #| self : View, #| start_offset? : Int = 0, #| end_offset? : Int, #|) -> View { #| let end_offset = if end_offset is Some(o) { o } else { self.length() } #| guard start_offset >= 0 && #| start_offset <= end_offset && #| end_offset <= self.length() else { #| abort("Invalid index for View") #| } #| View::make_view( #| self.str(), #| self.start() + start_offset, #| self.start() + end_offset, #| ) #|} #|#deprecated("use view instead") #|pub fn String::charcodes(self : String, start? : Int = 0, end? : Int) -> View { #| self.view(start_offset=start, end_offset?=end) #|} #|#deprecated("use view instead") #|pub fn View::charcodes(self : View, start? : Int = 0, end? : Int) -> View { #| self.view(start_offset=start, end_offset?=end) #|} #|pub fn View::offset_of_nth_char(self : View, i : Int) -> Int? { #| if self #| .str() #| .offset_of_nth_char(i, start_offset=self.start(), end_offset=self.end()) #| is Some(index) { #| Some(index - self.start()) #| } else { #| None #| } #|} #|pub fn View::unsafe_charcode_at(self : View, index : Int) -> Int { #| self.str().unsafe_charcode_at(self.start() + index) #|} #|pub fn View::char_length(self : View) -> Int { #| self.str().char_length(start_offset=self.start(), end_offset=self.end()) #|} #|pub fn View::char_length_eq(self : View, len : Int) -> Bool { #| self #| .str() #| .char_length_eq(len, start_offset=self.start(), end_offset=self.end()) #|} #|pub fn View::char_length_ge(self : View, len : Int) -> Bool { #| self #| .str() #| .char_length_ge(len, start_offset=self.start(), end_offset=self.end()) #|} #|pub impl Show for View with output(self, logger) { #| let substr = self.str().substring(start=self.start(), end=self.end()) #| String::output(substr, logger) #|} #|pub impl Show for View with to_string(self) { #| self.str().substring(start=self.start(), end=self.end()) #|} #|pub fn View::iter(self : View) -> Iter[Char] { #| Iter::new(yield_ => for index in self.start().. Iter2[Int, Char] { #| Iter2::new(yield_ => { #| let len = self.length() #| for index = 0, n = 0; index < len; index = index + 1, n = n + 1 { #| let c1 = self.str().unsafe_charcode_at(self.start() + index) #| if c1.is_leading_surrogate() && index + 1 < len { #| let c2 = self.str().unsafe_charcode_at(self.start() + index + 1) #| if c2.is_trailing_surrogate() { #| let c = code_point_of_surrogate_pair(c1, c2) #| guard yield_(n, c) is IterContinue else { break IterEnd } #| continue index + 2, n + 1 #| } #| } #| guard yield_(n, c1.unsafe_to_char()) is IterContinue else { #| break IterEnd #| } #| } else { #| IterContinue #| } #| }) #|} #|pub fn View::rev_iter(self : View) -> Iter[Char] { #| Iter::new(yield_ => for index = self.end() - 1 #| index >= self.start() #| index = index - 1 { #| let c1 = self.str().unsafe_charcode_at(index) #| if c1.is_trailing_surrogate() && index - 1 >= 0 { #| let c2 = self.str().unsafe_charcode_at(index - 1) #| if c2.is_leading_surrogate() { #| let c = code_point_of_surrogate_pair(c2, c1) #| guard yield_(c) is IterContinue else { break IterEnd } #| continue index - 2 #| } #| } #| guard yield_(c1.unsafe_to_char()) is IterContinue else { break IterEnd } #| } else { #| IterContinue #| }) #|} #|pub impl Eq for View with op_equal(self, other) { #| let len = self.length() #| guard len == other.length() else { return false } #| if physical_equal(self.str(), other.str()) && self.start() == other.start() { #| return true #| } #| for i in 0.. View { #| let s = String::from_array(chars) #| View::make_view(s, 0, s.length()) #|} #|pub fn View::from_iter(iter : Iter[Char]) -> View { #| let s = String::from_iter(iter) #| View::make_view(s, 0, s.length()) #|} #|pub fn View::make(length : Int, value : Char) -> View { #| String::make(length, value).view() #|} #|pub impl ToJson for View with to_json(self) { #| String::to_json(self.to_string()) #|} #|pub impl Hash for View with hash_combine(self : View, hasher : Hasher) -> Unit { #| for i in 0.. View raise CreatingViewError { #| let len = self.length() #| let end = match end { #| None => len #| Some(end) => if end < 0 { len + end } else { end } #| } #| let start = if start < 0 { len + start } else { start } #| guard start >= 0 && start <= end && end <= len else { raise IndexOutOfBounds } #| if start < len && self.unsafe_charcode_at(start).is_trailing_surrogate() { #| raise InvalidIndex #| } #| if end < len && self.unsafe_charcode_at(end).is_trailing_surrogate() { #| raise InvalidIndex #| } #| View::make_view(self, start, end) #|} #|pub fn View::op_as_view( #| self : View, #| start? : Int = 0, #| end? : Int, #|) -> View raise CreatingViewError { #| let str_len = self.str().length() #| let abs_end = match end { #| None => self.end() #| Some(end) => if end < 0 { self.end() + end } else { self.start() + end } #| } #| let abs_start = if start < 0 { #| self.end() + start #| } else { #| self.start() + start #| } #| guard abs_start >= self.start() && #| abs_start <= abs_end && #| abs_end <= self.end() else { #| raise IndexOutOfBounds #| } #| if abs_start < str_len && #| self.str().unsafe_charcode_at(abs_start).is_trailing_surrogate() { #| raise InvalidIndex #| } #| if abs_end < str_len && #| self.str().unsafe_charcode_at(abs_end).is_trailing_surrogate() { #| raise InvalidIndex #| } #| View::make_view(self.str(), abs_start, abs_end) #|} #|pub impl Add for View with op_add(self, other) { #| [..self, ..other] #|} ), }, ) ///| let moonbitlang_core_test_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/test", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/bench": moonbitlang_core_bench_module, "moonbitlang/core/json": moonbitlang_core_json_module, }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/builtin", #| "moonbitlang/core/bench", #| "moonbitlang/core/json" #| ] #|} ), "deprecated.mbt": ( #|#callsite(autofill(loc)) #|#deprecated("Use built-in `assert_eq` instead") #|#coverage.skip #|pub fn[T : Show + Eq] eq(a : T, b : T, loc~ : SourceLoc) -> Unit raise { #| if a != b { #| let a = debug_string(a) #| let b = debug_string(b) #| fail("`\{a} == \{b}`", loc~) #| } #|} #|#callsite(autofill(loc)) #|#deprecated("Use built-in `assert_not_eq` instead") #|#coverage.skip #|pub fn[T : Show + Eq] ne(a : T, b : T, loc~ : SourceLoc) -> Unit raise { #| if !(a != b) { #| let a = debug_string(a) #| let b = debug_string(b) #| fail("`\{a} != \{b}`", loc~) #| } #|} #|#callsite(autofill(loc)) #|#deprecated("Use built-in `assert_true` instead") #|#coverage.skip #|pub fn is_true(x : Bool, loc~ : SourceLoc) -> Unit raise { #| if !x { #| let x = debug_string(x) #| fail("`\{x}` is not true", loc~) #| } #|} #|#callsite(autofill(loc)) #|#deprecated("Use built-in `assert_false` instead") #|#coverage.skip #|pub fn is_false(x : Bool, loc~ : SourceLoc) -> Unit raise { #| if x { #| let x = debug_string(x) #| fail("`\{x}` is not false", loc~) #| } #|} #|#deprecated("Use `@bench.single_bench` instead") #|pub fn bench( #| self : T, #| f : () -> Unit, #| count? : UInt = 10, #|) -> Unit raise BenchError { #| ignore(self) #| let summary = @bench.single_bench(f, count~) #| raise BenchError("@BENCH \{summary.to_json().stringify()}\n") #|} ), "test.mbt": ( #|fn[T : Show] debug_string(t : T) -> String { #| let buf = StringBuilder::new(size_hint=50) #| t.output(buf) #| buf.to_string() #|} #|#callsite(autofill(loc)) #|pub fn[T : Show] same_object(a : T, b : T, loc~ : SourceLoc) -> Unit raise { #| if !physical_equal(a, b) { #| let a = debug_string(a) #| let b = debug_string(b) #| fail("`\{a} is \{b}`", loc~) #| } #|} #|#callsite(autofill(loc)) #|pub fn[T : Show] is_not(a : T, b : T, loc~ : SourceLoc) -> Unit raise { #| if physical_equal(a, b) { #| let a = debug_string(a) #| let b = debug_string(b) #| fail("`!(\{a} is \{b})`", loc~) #| } #|} #|#callsite(autofill(loc)) #|pub fn[T] fail(msg : String, loc~ : SourceLoc) -> T raise { #| @builtin.fail(msg, loc~) #|} #|pub fn write(self : T, obj : &Show) -> Unit { #| self.buffer.write_string(obj.to_string()) #|} #|pub fn writeln(self : T, obj : &Show) -> Unit { #| self.write(obj) #| self.buffer.write_char('\n') #|} #|#callsite(autofill(args_loc, loc)) #|pub fn snapshot( #| self : T, #| filename~ : String, #| loc~ : SourceLoc, #| args_loc~ : ArgsLoc, #|) -> Unit raise SnapshotError { #| let loc = loc.to_string().escape() #| let args_loc = args_loc.to_json().escape() #| let actual = self.buffer.to_string().escape() #| let expect = filename.escape() #| raise SnapshotError( #| "@SNAPSHOT_TESTING {\"loc\": \{loc}, \"args_loc\": \{args_loc}, \"expect\": \{expect}, \"actual\": \{actual}, \"snapshot\": true}", #| ) #|} ), "types.mbt": ( #|#visibility(change_to="abstract") #|pub(all) struct T { #| name : String #| buffer : StringBuilder #|} #|pub fn new(name : String) -> T { #| { name, buffer: StringBuilder::new() } #|} ), }, ) ///| let moonbitlang_core_tuple_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/tuple", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/quickcheck": moonbitlang_core_quickcheck_module, "moonbitlang/core/quickcheck/splitmix": moonbitlang_core_quickcheck_splitmix_module, }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/builtin", #| "moonbitlang/core/quickcheck", #| "moonbitlang/core/quickcheck/splitmix" #| ], #| "test-import": [ #| "moonbitlang/core/char" #| ] #|} ), "deprecated.mbt": ( #|#deprecated #|#coverage.skip #|pub fn[T, U] pair(x : T, y : U) -> (T, U) { #| (x, y) #|} #|#deprecated("use `tuple.0` instead") #|#coverage.skip #|pub fn[T, U] fst(tuple : (T, U)) -> T { #| tuple.0 #|} #|#deprecated("use `tuple.1` instead") #|#coverage.skip #|pub fn[T, U] snd(tuple : (T, U)) -> U { #| tuple.1 #|} #|#deprecated("use `{ let (a,b) = tuple; (f(a),b) }` instead") #|#coverage.skip #|pub fn[T, U, V] map_fst(f : (T) -> U, tuple : (T, V)) -> (U, V) { #| (f(tuple.0), tuple.1) #|} #|#deprecated("use `{ let (a,b) = tuple; (a,f(b)) }` instead") #|#coverage.skip #|pub fn[T, U, V] map_snd(f : (T) -> U, tuple : (V, T)) -> (V, U) { #| (tuple.0, f(tuple.1)) #|} #|#deprecated("use `{ let (a,b) = tuple; (f(a),f(b)) }` instead") #|#coverage.skip #|pub fn[T, U, V, W] map_both( #| f : (T) -> U, #| g : (V) -> W, #| tuple : (T, V), #|) -> (U, W) { #| (f(tuple.0), g(tuple.1)) #|} #|#deprecated #|#coverage.skip #|pub fn[T, U] swap(tuple : (T, U)) -> (U, T) { #| (tuple.1, tuple.0) #|} #|#deprecated #|#coverage.skip #|pub fn[T, U, V] curry(f : (T, U) -> V) -> (T) -> (U) -> V { #| (x : T) => (y : U) => f(x, y) #|} #|#deprecated #|#coverage.skip #|pub fn[T, U, V] uncurry(f : (T) -> (U) -> V) -> (T, U) -> V { #| (x : T, y : U) => f(x)(y) #|} ), "tuple.mbt": "", "tuple_arbitrary.mbt": ( #|traitalias @quickcheck.Arbitrary #|pub impl[A : Arbitrary, B : Arbitrary] Arbitrary for (A, B) with arbitrary( #| size, #| r0, #|) { #| let r1 = r0.split() #| (Arbitrary::arbitrary(size, r0), Arbitrary::arbitrary(size, r1)) #|} #|pub impl[A : Arbitrary, B : Arbitrary, C : Arbitrary] Arbitrary for (A, B, C) with arbitrary( #| size, #| r0, #|) { #| let r1 = r0.split() #| let (v1, v2) = Arbitrary::arbitrary(size, r1) #| (Arbitrary::arbitrary(size, r0), v1, v2) #|} #|pub impl[A : Arbitrary, B : Arbitrary, C : Arbitrary, D : Arbitrary] Arbitrary for ( #| A, #| B, #| C, #| D, #|) with arbitrary(size, r0) { #| let r1 = r0.split() #| let (v1, v2, v3) = Arbitrary::arbitrary(size, r1) #| (Arbitrary::arbitrary(size, r0), v1, v2, v3) #|} #|pub impl[ #| A : Arbitrary, #| B : Arbitrary, #| C : Arbitrary, #| D : Arbitrary, #| E : Arbitrary, #|] Arbitrary for (A, B, C, D, E) with arbitrary(size, r0) { #| let r1 = r0.split() #| let (v1, v2, v3, v4) = Arbitrary::arbitrary(size, r1) #| (Arbitrary::arbitrary(size, r0), v1, v2, v3, v4) #|} #|pub impl[ #| A : Arbitrary, #| B : Arbitrary, #| C : Arbitrary, #| D : Arbitrary, #| E : Arbitrary, #| F : Arbitrary, #|] Arbitrary for (A, B, C, D, E, F) with arbitrary(size, r0) { #| let r1 = r0.split() #| let (v1, v2, v3, v4, v5) = Arbitrary::arbitrary(size, r1) #| (Arbitrary::arbitrary(size, r0), v1, v2, v3, v4, v5) #|} #|pub impl[ #| A : Arbitrary, #| B : Arbitrary, #| C : Arbitrary, #| D : Arbitrary, #| E : Arbitrary, #| F : Arbitrary, #| G : Arbitrary, #|] Arbitrary for (A, B, C, D, E, F, G) with arbitrary(size, r0) { #| let r1 = r0.split() #| let (v1, v2, v3, v4, v5, v6) = Arbitrary::arbitrary(size, r1) #| (Arbitrary::arbitrary(size, r0), v1, v2, v3, v4, v5, v6) #|} ), "tuple_default.mbt": ( #|pub impl[A : Default, B : Default] Default for (A, B) with default() { #| (Default::default(), Default::default()) #|} #|pub impl[A : Default, B : Default, C : Default] Default for (A, B, C) with default() { #| (Default::default(), Default::default(), Default::default()) #|} #|pub impl[A : Default, B : Default, C : Default, D : Default] Default for ( #| A, #| B, #| C, #| D, #|) with default() { #| ( #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| ) #|} #|pub impl[A : Default, B : Default, C : Default, D : Default, E : Default] Default for ( #| A, #| B, #| C, #| D, #| E, #|) with default() { #| ( #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| ) #|} #|pub impl[ #| A : Default, #| B : Default, #| C : Default, #| D : Default, #| E : Default, #| F : Default, #|] Default for (A, B, C, D, E, F) with default() { #| ( #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| ) #|} #|pub impl[ #| A : Default, #| B : Default, #| C : Default, #| D : Default, #| E : Default, #| F : Default, #| G : Default, #|] Default for (A, B, C, D, E, F, G) with default() { #| ( #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| ) #|} #|pub impl[ #| A : Default, #| B : Default, #| C : Default, #| D : Default, #| E : Default, #| F : Default, #| G : Default, #| H : Default, #|] Default for (A, B, C, D, E, F, G, H) with default() { #| ( #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| ) #|} #|pub impl[ #| A : Default, #| B : Default, #| C : Default, #| D : Default, #| E : Default, #| F : Default, #| G : Default, #| H : Default, #| I : Default, #|] Default for (A, B, C, D, E, F, G, H, I) with default() { #| ( #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| ) #|} #|pub impl[ #| A : Default, #| B : Default, #| C : Default, #| D : Default, #| E : Default, #| F : Default, #| G : Default, #| H : Default, #| I : Default, #| J : Default, #|] Default for (A, B, C, D, E, F, G, H, I, J) with default() { #| ( #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| ) #|} #|pub impl[ #| A : Default, #| B : Default, #| C : Default, #| D : Default, #| E : Default, #| F : Default, #| G : Default, #| H : Default, #| I : Default, #| J : Default, #| K : Default, #|] Default for (A, B, C, D, E, F, G, H, I, J, K) with default() { #| ( #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| ) #|} #|pub impl[ #| A : Default, #| B : Default, #| C : Default, #| D : Default, #| E : Default, #| F : Default, #| G : Default, #| H : Default, #| I : Default, #| J : Default, #| K : Default, #| L : Default, #|] Default for (A, B, C, D, E, F, G, H, I, J, K, L) with default() { #| ( #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| ) #|} #|pub impl[ #| A : Default, #| B : Default, #| C : Default, #| D : Default, #| E : Default, #| F : Default, #| G : Default, #| H : Default, #| I : Default, #| J : Default, #| K : Default, #| L : Default, #| M : Default, #|] Default for (A, B, C, D, E, F, G, H, I, J, K, L, M) with default() { #| ( #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| ) #|} #|pub impl[ #| A : Default, #| B : Default, #| C : Default, #| D : Default, #| E : Default, #| F : Default, #| G : Default, #| H : Default, #| I : Default, #| J : Default, #| K : Default, #| L : Default, #| M : Default, #| N : Default, #|] Default for (A, B, C, D, E, F, G, H, I, J, K, L, M, N) with default() { #| ( #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| ) #|} #|pub impl[ #| A : Default, #| B : Default, #| C : Default, #| D : Default, #| E : Default, #| F : Default, #| G : Default, #| H : Default, #| I : Default, #| J : Default, #| K : Default, #| L : Default, #| M : Default, #| N : Default, #| O : Default, #|] Default for (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) with default() { #| ( #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| ) #|} #|pub impl[ #| A : Default, #| B : Default, #| C : Default, #| D : Default, #| E : Default, #| F : Default, #| G : Default, #| H : Default, #| I : Default, #| J : Default, #| K : Default, #| L : Default, #| M : Default, #| N : Default, #| O : Default, #| P : Default, #|] Default for (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) with default() { #| ( #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| Default::default(), #| ) #|} ), }, ) ///| let moonbitlang_core_uint_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/uint", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module }, files={ "moon.pkg.json": ( #|{ #| "import": ["moonbitlang/core/builtin"] #|} ), "uint.mbt": ( #|pub let min_value : UInt = 0U #|pub let max_value : UInt = 4294967295U #|pub fn to_int64(self : UInt) -> Int64 { #| self.to_uint64().reinterpret_as_int64() #|} #|pub impl Default for UInt with default() { #| 0 #|} #|pub fn default() -> UInt { #| 0 #|} #|pub fn to_be_bytes(self : UInt) -> Bytes { #| [ #| (self >> 24).to_byte(), #| (self >> 16).to_byte(), #| (self >> 8).to_byte(), #| self.to_byte(), #| ] #|} #|pub fn to_le_bytes(self : UInt) -> Bytes { #| [ #| self.to_byte(), #| (self >> 8).to_byte(), #| (self >> 16).to_byte(), #| (self >> 24).to_byte(), #| ] #|} ), }, ) ///| let moonbitlang_core_uint16_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/uint16", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module, "moonbitlang/core/json": moonbitlang_core_json_module, }, files={ "moon.pkg.json": ( #|{ #| "import": [ #| "moonbitlang/core/builtin", #| "moonbitlang/core/json" #| ] #|} ), "uint16.mbt": ( #|pub let max_value : UInt16 = 65535 #|pub let min_value : UInt16 = 0 #|pub impl Add for UInt16 with op_add(self : UInt16, that : UInt16) -> UInt16 { #| (self.to_int() + that.to_int()).to_uint16() #|} #|pub impl Sub for UInt16 with op_sub(self : UInt16, that : UInt16) -> UInt16 { #| (self.to_int() - that.to_int()).to_uint16() #|} #|pub impl Mul for UInt16 with op_mul(self : UInt16, that : UInt16) -> UInt16 { #| (self.to_int() * that.to_int()).to_uint16() #|} #|pub impl Div for UInt16 with op_div(self : UInt16, that : UInt16) -> UInt16 { #| (self.to_int() / that.to_int()).to_uint16() #|} #|pub impl Mod for UInt16 with op_mod(self : UInt16, that : UInt16) -> UInt16 { #| (self.to_int() % that.to_int()).to_uint16() #|} #|pub impl Eq for UInt16 with op_equal(self, that) { #| self.to_int() == that.to_int() #|} #|pub impl Compare for UInt16 with compare(self, that) { #| self.to_int().compare(that.to_int()) #|} #|pub impl Hash for UInt16 with hash(self) { #| self.to_int() #|} #|pub impl Hash for UInt16 with hash_combine(self, hasher) { #| hasher.combine_int(self.to_int()) #|} #|pub impl Shl for UInt16 with op_shl(self : UInt16, that : Int) -> UInt16 { #| (self.to_int() << that).to_uint16() #|} #|pub impl Shr for UInt16 with op_shr(self : UInt16, that : Int) -> UInt16 { #| (self.to_int() >> that).to_uint16() #|} #|pub impl BitOr for UInt16 with lor(self : UInt16, that : UInt16) -> UInt16 { #| (self.to_int() | that.to_int()).to_uint16() #|} #|pub impl BitAnd for UInt16 with land(self : UInt16, that : UInt16) -> UInt16 { #| (self.to_int() & that.to_int()).to_uint16() #|} #|pub impl BitXOr for UInt16 with lxor(self : UInt16, that : UInt16) -> UInt16 { #| (self.to_int() ^ that.to_int()).to_uint16() #|} #|pub impl Default for UInt16 with default() { #| 0 #|} #|pub impl ToJson for UInt16 with to_json(self : UInt16) -> Json { #| Json::number(self.to_int().to_double()) #|} #|pub fn UInt16::to_uint(self : UInt16) -> UInt { #| self.to_int().reinterpret_as_uint() #|} #|pub fn UInt16::to_uint64(self : UInt16) -> UInt64 { #| self.to_int().to_uint64() #|} ), }, ) ///| let moonbitlang_core_uint64_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/uint64", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module }, files={ "moon.pkg.json": ( #|{ #| "import": ["moonbitlang/core/builtin"], #| "test-import": ["moonbitlang/core/double"] #|} ), "uint64.mbt": ( #|pub let min_value : UInt64 = 0UL #|pub let max_value : UInt64 = 18446744073709551615UL #|pub fn to_be_bytes(self : UInt64) -> Bytes { #| [ #| (self >> 56).to_byte(), #| (self >> 48).to_byte(), #| (self >> 40).to_byte(), #| (self >> 32).to_byte(), #| (self >> 24).to_byte(), #| (self >> 16).to_byte(), #| (self >> 8).to_byte(), #| self.to_byte(), #| ] #|} #|pub fn to_le_bytes(self : UInt64) -> Bytes { #| [ #| self.to_byte(), #| (self >> 8).to_byte(), #| (self >> 16).to_byte(), #| (self >> 24).to_byte(), #| (self >> 32).to_byte(), #| (self >> 40).to_byte(), #| (self >> 48).to_byte(), #| (self >> 56).to_byte(), #| ] #|} #|test "to_be_bytes" { #| inspect( #| max_value.to_be_bytes(), #| content=( #| #|b"\xff\xff\xff\xff\xff\xff\xff\xff" #| ), #| ) #| inspect( #| min_value.to_be_bytes(), #| content=( #| #|b"\x00\x00\x00\x00\x00\x00\x00\x00" #| ), #| ) #| inspect( #| 0x123456789ABCDEF0UL.to_be_bytes(), #| content=( #| #|b"\x12\x34\x56\x78\x9a\xbc\xde\xf0" #| ), #| ) #|} #|test "to_le_bytes" { #| inspect( #| max_value.to_le_bytes(), #| content=( #| #|b"\xff\xff\xff\xff\xff\xff\xff\xff" #| ), #| ) #| inspect( #| min_value.to_le_bytes(), #| content=( #| #|b"\x00\x00\x00\x00\x00\x00\x00\x00" #| ), #| ) #| inspect( #| 0x123456789ABCDEF0UL.to_le_bytes(), #| content=( #| #|b"\xf0\xde\xbc\x9a\x78\x56\x34\x12" #| ), #| ) #|} ), }, ) ///| let moonbitlang_core_unit_module : RuntimePackage = RuntimePackage::new( "moonbitlang/core/unit", deps={ "moonbitlang/core/builtin": moonbitlang_core_builtin_module }, files={ "moon.pkg.json": ( #|{ #| "import": ["moonbitlang/core/builtin"] #|} ), "unit.mbt": ( #|pub fn to_string(self : Unit) -> String { #| let _ = self #| "()" #|} #|pub impl Hash for Unit with hash(self) { #| let _ = self #| 0 #|} #|pub impl Hash for Unit with hash_combine(self, hasher) -> Unit { #| let _ = self #| hasher.combine_unit() #|} #|pub impl Default for Unit with default() -> Unit { #| () #|} #|pub fn default() -> Unit { #| () #|} #|pub impl Compare for Unit with compare(_self, _other) { #| 0 #|} ), }, )